supplier_payments 0.0.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/.circleci/config.yml +14 -0
- data/.gitignore +5 -0
- data/Gemfile +11 -0
- data/README.md +10 -0
- data/Rakefile +5 -0
- data/lib/supplier_payments.rb +6 -0
- data/lib/supplier_payments/payment_file.rb +44 -0
- data/lib/supplier_payments/payment_file/domestic_records.rb +161 -0
- data/lib/supplier_payments/payment_file/records.rb +101 -0
- data/lib/supplier_payments/version.rb +3 -0
- data/spec/fixtures/LBin-exempel1.txt +28 -0
- data/spec/fixtures/LBin-exempel2.txt +57 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/supplier_payments/payment_file/records_spec.rb +52 -0
- data/spec/supplier_payments/payment_file_spec.rb +53 -0
- data/supplier_payments.gemspec +17 -0
- metadata +59 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 813cbd012bead806a978feef2a8c647eb12bc6d8884631b4dc63dacac9216b20
|
4
|
+
data.tar.gz: c0b6453b3ed89d2c6c2f14a5e1e3f9393f7c4a5ce4ff7496230abebdba52375a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 424e8b77af02672e0a71940a8ea28aa17ca8d14bd83d85e5f09ed80be21d22eeb5156c01c4f07ed326f971f2b06ee43488c30682a778a9ed913904a570c2eae8
|
7
|
+
data.tar.gz: 8e2130999d73019f3bd099cc963fcde2fa5fe0ec51b664c0bcd81f25eb6c361273aa14621df0f4eb37aa4720747c3e8fd6c803c28649994fc24d09e88bb20065
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# Supplier Payments
|
2
|
+
|
3
|
+
[](https://circleci.com/gh/barsoom/supplier_payments)
|
4
|
+
|
5
|
+
Library for making Bankgirot supplier payment files, _Leverantörsbetalningar_.
|
6
|
+
|
7
|
+
## Documentation
|
8
|
+
|
9
|
+
* På svenska: ["Leverantörsbetalningar, teknisk manual"](http://www.bgc.se/globalassets/dokument/tekniska-manualer/leverantorsbetalningar_tekniskmanual_sv.pdf) (PDF)
|
10
|
+
* In English: ["Supplier Payments (Leverantörsbetalningar), technical manual"](http://www.bgc.se/globalassets/dokument/tekniska-manualer/supplierpayments_leverantorsbetalningar_technicalmanual_en.pdf) (PDF)
|
data/Rakefile
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
module SupplierPayments
|
2
|
+
class PaymentFile
|
3
|
+
class << self
|
4
|
+
@@record_classes = []
|
5
|
+
|
6
|
+
def record_classes
|
7
|
+
@@record_classes
|
8
|
+
end
|
9
|
+
|
10
|
+
def register_record_class(record_class)
|
11
|
+
record_classes << record_class
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_accessor :records
|
16
|
+
|
17
|
+
def initialize(records)
|
18
|
+
@records = records
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
records.map { |record|
|
23
|
+
"#{ record.to_s.dup.force_encoding("ISO-8859-15") }\r\n"
|
24
|
+
}.join
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.load(data)
|
28
|
+
records = data.lines.map do |line|
|
29
|
+
line.strip!
|
30
|
+
next if line.empty?
|
31
|
+
record_class(line).parse(line)
|
32
|
+
end
|
33
|
+
new(records)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def self.record_class(line)
|
39
|
+
record_classes.find do |record_class|
|
40
|
+
line.match(/^#{record_class.transaction_code}/)
|
41
|
+
end or raise "No record class found for line: #{ line.inspect }"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
module SupplierPayments
|
2
|
+
class PaymentFile
|
3
|
+
class OpeningRecord < AbstractRecord
|
4
|
+
self.transaction_code = '11'
|
5
|
+
self.layout = [
|
6
|
+
[ :transaction_code!, 2, 'N' ],
|
7
|
+
[ :sender_bankgiro, 10, 'N', :right_align, :zerofill ],
|
8
|
+
[ :date_written, 6, 'N' ],
|
9
|
+
[ :product, 22, 'A' ],
|
10
|
+
[ :payment_date, 6, 'N' ],
|
11
|
+
[ :reserved!, 13, 'N' ],
|
12
|
+
[ :currency_code, 3, 'A' ],
|
13
|
+
[ :reserved!, 18, 'A' ],
|
14
|
+
]
|
15
|
+
end
|
16
|
+
|
17
|
+
class FixedInformationRecord < AbstractRecord
|
18
|
+
self.transaction_code = '12'
|
19
|
+
self.layout = [
|
20
|
+
[ :transaction_code!, 2, 'N' ],
|
21
|
+
[ :information_text, 50, 'A' ], # Information reported to recipients with bankgiro number in
|
22
|
+
# all sections with the same forwarding bankgiro number
|
23
|
+
# (For example: Merry Christmas, We have moved etc.) or blank.
|
24
|
+
[ :end_date, 6, 'A' ],
|
25
|
+
[ :reserved!, 22, 'A' ]
|
26
|
+
]
|
27
|
+
end
|
28
|
+
|
29
|
+
class HeaderRecord < AbstractRecord
|
30
|
+
self.transaction_code = '13'
|
31
|
+
self.layout = [
|
32
|
+
[ :transaction_code!, 2, 'N' ],
|
33
|
+
[ :payment_specifications_header, 25, 'A' ],
|
34
|
+
[ :net_amount_header, 12, 'A' ],
|
35
|
+
[ :reserved!, 41, 'A' ]
|
36
|
+
]
|
37
|
+
end
|
38
|
+
|
39
|
+
class PaymentRecord < AbstractRecord
|
40
|
+
self.transaction_code = '14'
|
41
|
+
self.layout = [
|
42
|
+
[ :transaction_code!, 2, 'N' ],
|
43
|
+
[ :bankgiro_or_credit_transfer_number, 10, 'N', :right_align, :zerofill ],
|
44
|
+
[ :ocr, 25, 'A' ],
|
45
|
+
[ :amount, 12, 'N', :right_align, :zerofill ],
|
46
|
+
[ :payment_date, 6, 'N' ], # YYMMDD or GENAST
|
47
|
+
[ :reserved!, 5, 'A' ],
|
48
|
+
[ :information_to_sender, 20, 'A' ]
|
49
|
+
]
|
50
|
+
end
|
51
|
+
|
52
|
+
class DeductionRecord < AbstractRecord
|
53
|
+
self.transaction_code = '15'
|
54
|
+
self.layout = [
|
55
|
+
[ :transaction_code!, 2, 'N' ],
|
56
|
+
[ :bankgiro_or_credit_transfer_number, 10, 'N', :right_align, :zerofill ],
|
57
|
+
[ :ocr, 25, 'A' ],
|
58
|
+
[ :deduction_amount, 12, 'N', :right_align, :zerofill ],
|
59
|
+
[ :deduction_date, 6, 'N' ], # YYMMDD or GENAST
|
60
|
+
[ :reserved!, 5, 'A' ],
|
61
|
+
[ :information_to_sender, 20, 'A' ]
|
62
|
+
]
|
63
|
+
end
|
64
|
+
|
65
|
+
class CreditInvoiceWithMonitoringRecord < AbstractRecord
|
66
|
+
self.transaction_code = '16'
|
67
|
+
self.layout = [
|
68
|
+
[ :transaction_code!, 2, 'N' ],
|
69
|
+
[ :bankgiro_or_credit_transfer_number, 10, 'N', :right_align, :zerofill ],
|
70
|
+
[ :ocr, 25, 'A' ],
|
71
|
+
[ :amount, 12, 'N', :right_align, :zerofill ],
|
72
|
+
[ :last_monitoring_day, 6, 'A' ], # YYMMDD or GENAST
|
73
|
+
[ :reserved!, 5, 'A' ],
|
74
|
+
[ :information_to_sender, 20, 'N' ]
|
75
|
+
]
|
76
|
+
end
|
77
|
+
|
78
|
+
class InformationRecord < AbstractRecord
|
79
|
+
self.transaction_code = '25'
|
80
|
+
self.layout = [
|
81
|
+
[ :transaction_code!, 2, 'N' ],
|
82
|
+
[ :bankgiro_or_credit_transfer_number, 10, 'N', :right_align, :zerofill ],
|
83
|
+
[ :information_text, 50, 'A' ],
|
84
|
+
[ :reserved!, 18, 'A' ],
|
85
|
+
]
|
86
|
+
end
|
87
|
+
|
88
|
+
class TotalAmountRecord < AbstractRecord
|
89
|
+
self.transaction_code = '29'
|
90
|
+
self.layout = [
|
91
|
+
[ :transaction_code!, 2, 'N' ],
|
92
|
+
[ :sender_bankgiro, 10, 'N', :right_align, :zerofill ],
|
93
|
+
[ :number_of_payment_records, 8, 'N', :right_align, :zerofill ],
|
94
|
+
[ :total_amount, 12, 'N', :right_align, :zerofill ],
|
95
|
+
[ :negative_total_amount, 1, 'A' ], # Minus sign (if total amount is negative) or blank.
|
96
|
+
[ :reserved!, 47, 'A' ]
|
97
|
+
]
|
98
|
+
end
|
99
|
+
|
100
|
+
class NameRecord < AbstractRecord
|
101
|
+
self.transaction_code = '26'
|
102
|
+
self.layout = [
|
103
|
+
[ :transaction_code!, 2, 'N' ],
|
104
|
+
[ :reserved!, 4, 'N', :zerofill ], # 0000
|
105
|
+
[ :credit_transfer_number, 6, 'N', :right_align, :zerofill ], # Must be the same as in the payment record or account number record, to which it belongs.
|
106
|
+
[ :payee_name, 35, 'A', :upcase ],
|
107
|
+
[ :extra_information, 33, 'A' ], # Used, for example, for C/O addresses.
|
108
|
+
]
|
109
|
+
end
|
110
|
+
|
111
|
+
class AddressRecord < AbstractRecord
|
112
|
+
self.transaction_code = '27'
|
113
|
+
self.layout = [
|
114
|
+
[ :transaction_code!, 2, 'N' ],
|
115
|
+
[ :reserved!, 4, 'N', :zerofill ],
|
116
|
+
[ :credit_transfer_number, 6, 'N', :right_align, :zerofill ],
|
117
|
+
[ :payee_address, 35, 'A', :upcase ],
|
118
|
+
[ :post_code, 5, 'N' ], # No spaces
|
119
|
+
[ :town, 20, 'A', :upcase ],
|
120
|
+
[ :reserved!, 8, 'A' ]
|
121
|
+
]
|
122
|
+
end
|
123
|
+
|
124
|
+
class AccountNumberRecord < AbstractRecord
|
125
|
+
self.transaction_code = '40'
|
126
|
+
self.layout = [
|
127
|
+
[ :transaction_code!, 2, 'N' ],
|
128
|
+
[ :reserved!, 4, 'N', :zerofill ], # 0000
|
129
|
+
[ :credit_transfer_number, 6, 'N', :right_align, :zerofill ],
|
130
|
+
[ :clearing_number, 4, 'N' ],
|
131
|
+
[ :account_number, 12, 'N', :right_align, :zerofill ],
|
132
|
+
[ :payment_identification, 12, 'A' ], # Information to the payee to identify the payment. Printed on the payee's bank statement.
|
133
|
+
[ :code_for_salary, 1, 'A' ], # L for salary, else blank.
|
134
|
+
[ :reserved!, 39, 'A' ]
|
135
|
+
]
|
136
|
+
end
|
137
|
+
|
138
|
+
class PlusGiroPaymentRecord < AbstractRecord
|
139
|
+
self.transaction_code = '54'
|
140
|
+
self.layout = [
|
141
|
+
[ :transaction_code!, 2, 'N' ],
|
142
|
+
[ :plusgiro_account, 10, 'N', :right_align, :zerofill ],
|
143
|
+
[ :ocr, 25, 'A' ],
|
144
|
+
[ :amount, 12, 'N', :right_align, :zerofill ],
|
145
|
+
[ :payment_date, 6, 'A' ], # YYMMDD or GENAST.
|
146
|
+
[ :reserved!, 5, 'A' ],
|
147
|
+
[ :information_to_sender, 20, 'A' ] # Optional text or blank.
|
148
|
+
]
|
149
|
+
end
|
150
|
+
|
151
|
+
class PlusGiroInformationRecord < AbstractRecord
|
152
|
+
self.transaction_code = '65'
|
153
|
+
self.layout = [
|
154
|
+
[ :transaction_code!, 2, 'N' ],
|
155
|
+
[ :plusgiro_account, 10, 'N', :right_align, :zerofill ],
|
156
|
+
[ :information_text, 35, 'A' ], # Optional text, printed on notifications and lists.
|
157
|
+
[ :reserved!, 33, 'A' ]
|
158
|
+
]
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
module SupplierPayments
|
2
|
+
class PaymentFile
|
3
|
+
class AbstractRecord
|
4
|
+
LayoutError = Class.new(Exception)
|
5
|
+
FormatError = Class.new(Exception)
|
6
|
+
|
7
|
+
class << self
|
8
|
+
attr_accessor :transaction_code
|
9
|
+
attr_reader :layout
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
def layout=(layout)
|
14
|
+
length = layout_length(layout)
|
15
|
+
raise LayoutError.new("Layout length #{ length } is not 80") unless length == 80
|
16
|
+
|
17
|
+
layout.each do |field, length, format, *opts|
|
18
|
+
next if field[-1] == "!"
|
19
|
+
attr_accessor field
|
20
|
+
end
|
21
|
+
|
22
|
+
@layout = layout
|
23
|
+
end
|
24
|
+
|
25
|
+
def layout_length(layout)
|
26
|
+
layout.inject(0) do |total, (field, length, format, *opts)|
|
27
|
+
total + length
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def inherited(klass)
|
32
|
+
PaymentFile.register_record_class(klass)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.parse(line)
|
37
|
+
io = StringIO.new(line)
|
38
|
+
record = new
|
39
|
+
|
40
|
+
layout.each do |field, length, format, *opts|
|
41
|
+
if field[-1] == "!"
|
42
|
+
io.seek(length, IO::SEEK_CUR)
|
43
|
+
else
|
44
|
+
record.send("#{ field }=", io.read(length))
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
record
|
49
|
+
end
|
50
|
+
|
51
|
+
def initialize(attrs = {})
|
52
|
+
attrs.each do |key, value|
|
53
|
+
self.send("#{ key }=", value)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_s
|
58
|
+
self.class.layout.map { |field, length, format, *opts|
|
59
|
+
format_field(field, length, format, *opts)
|
60
|
+
}.join
|
61
|
+
end
|
62
|
+
|
63
|
+
def inspect
|
64
|
+
str = self.class.layout.map { |field, length, format, *opts|
|
65
|
+
next if field[-1] == "!"
|
66
|
+
":#{ field } => #{ send(field).inspect }"
|
67
|
+
}.compact.join(", ")
|
68
|
+
"<#{ self.class.name }(#{ transaction_code }) #{ str }>"
|
69
|
+
end
|
70
|
+
|
71
|
+
def transaction_code
|
72
|
+
self.class.transaction_code
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def format_field(field, length, format, *opts)
|
78
|
+
value = field_value(field)
|
79
|
+
value.upcase! if opts.include?(:upcase)
|
80
|
+
|
81
|
+
padding = opts.include?(:zerofill) ? "0" : " "
|
82
|
+
align_method = opts.include?(:right_align) ? :rjust : :ljust
|
83
|
+
|
84
|
+
value[0, length].send(align_method, length, padding)
|
85
|
+
end
|
86
|
+
|
87
|
+
def field_value(field)
|
88
|
+
case field
|
89
|
+
when :reserved!
|
90
|
+
+""
|
91
|
+
when :transaction_code!
|
92
|
+
transaction_code.dup
|
93
|
+
else
|
94
|
+
send(field).to_s.dup
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
require "supplier_payments/payment_file/domestic_records"
|
@@ -0,0 +1,28 @@
|
|
1
|
+
1100XXXXXXXX060328LEVERANT�RSBETALNINGAR
|
2
|
+
13REFERENS BELOPP
|
3
|
+
1400XXXXXXXX56897456986 000000098000060330 VERIF 12
|
4
|
+
1400XXXXXXXX12356986799 000000021000060404 VERIF 13
|
5
|
+
1400XXXXXXXX421948311319 000000528000060404 VERIF 14
|
6
|
+
1400XXXXXXXX15204076 000000063000060407 VERIF 16
|
7
|
+
1400XXXXXXXX49060593 000000003000060407 VERIF 18
|
8
|
+
1400XXXXXXXX48774616 000000098000060330 VERIF 19
|
9
|
+
1600XXXXXXXX563258967410 000000086000060412 VERIF 32
|
10
|
+
1600XXXXXXXX566986547214 000000023300060630 VERIF 33
|
11
|
+
1600XXXXXXXX08570215155 000000445000060630 VERIF 34
|
12
|
+
1400XXXXXXXX18404079 000000021000060404 VERIF 20
|
13
|
+
1400XXXXXXXX49243777 000000528000060404 VERIF 22
|
14
|
+
1400XXXXXXXX34136606 000000063000060407 VERIF 23
|
15
|
+
1400XXXXXXXX49342306 000000003000060407 VERIF 24
|
16
|
+
400000990010XXXX00XXXXXXXXXXRESEERS
|
17
|
+
14000099001015204076 000000230000060330 VERIF 25
|
18
|
+
400000990028XXXX000000XXXXXX
|
19
|
+
14000099002849060593 000000140000060330 VERIF 26
|
20
|
+
40000099003 XXXX0000000XXXXX
|
21
|
+
14000099003 48774616 000000800000060330 VERIF 27
|
22
|
+
26000099004 HANDELSBOLAGET HB
|
23
|
+
27000099004 TORSGATAN 84 11225STOCKHOLM
|
24
|
+
14000099004 563258911111 000001500000060330 VERIF 29
|
25
|
+
26000099005 ENSKILDA FIRMAN
|
26
|
+
27000099005 J�RNV�GSGATAN 84 64554HALLSBERG
|
27
|
+
14000099005 12356986799 000000500000060330 VERIF 30
|
28
|
+
2900XXXXXXXX00000018000004041700
|
@@ -0,0 +1,57 @@
|
|
1
|
+
1100XXXXXXXX060328LEVERANT�RSBETALNINGAR060401
|
2
|
+
12NY ADRESS:HOLMV�GEN 20 10518 NYSTAD 060514
|
3
|
+
13REFERENS
|
4
|
+
1400XXXXXXXX56325811111 000000980000
|
5
|
+
2500XXXXXXXXVERIFNR 11111 LEVERANS DECEMBER
|
6
|
+
1400XXXXXXXX08570215155 000000210000
|
7
|
+
2500XXXXXXXXVERIFNR 11112
|
8
|
+
1500XXXXXXXX123133 000000050000
|
9
|
+
2500XXXXXXXXVERIFNR 11117 KREDIT NOVEMBER
|
10
|
+
1500XXXXXXXX866525 000000250000
|
11
|
+
2500XXXXXXXXVERIFNR 11118 KREDIT NOVEMBER
|
12
|
+
5400XXXXXXXX88327416 000000010000
|
13
|
+
6500XXXXXXXXVERIFNR 11113
|
14
|
+
5400XXXXXXXX49231855 000000500000
|
15
|
+
6500XXXXXXXXVERIFNR 11114
|
16
|
+
2900XXXXXXXX00000006000001400000
|
17
|
+
110009912346060328LEVERANT�RSBETALNINGAR060415
|
18
|
+
12NY ADRESS:HOLMV�GEN 20 10518 NYSTAD 060514
|
19
|
+
13REFERENS
|
20
|
+
400000990010XXXX00XXXXXXXXXX
|
21
|
+
260000990010NILS PETTERSSON C/O NILSSON
|
22
|
+
270000990010SAGOV�GEN 10516STOCKHOLM
|
23
|
+
140000990010VERIFNR 11110 000000156000
|
24
|
+
250000990010�TERBETALNING AV BOENDEPARKERING KVARTAL 1
|
25
|
+
150000990010AVG�R F PERIODEN 1/1-15/2000000100000
|
26
|
+
400000990028XXXX00XXXXXXXXXX
|
27
|
+
260000990028BOLAGET HB
|
28
|
+
270000990028SOCKENV�GEN 4 32153G�TEBORG
|
29
|
+
1400009900288450413 000000039600
|
30
|
+
250000990028VERIFNR 11115
|
31
|
+
40000099003 XXXX0000XXXXXXXX
|
32
|
+
26000099003 JOHANNA AXELSSON
|
33
|
+
27000099003 STR�V�GEN 5 95334HAPARANDA
|
34
|
+
14000099003 56325892225 000005500000
|
35
|
+
25000099003 SKADEUTBETALNING
|
36
|
+
15000099003 AVG�R SJ�LVRISK 000000500000
|
37
|
+
40000099004 XXXX00000XXXXXXX L
|
38
|
+
26000099004 ERIK PERSSON
|
39
|
+
27000099004 J�RNV�GSGATAN 84 64554HALLSBERG
|
40
|
+
14000099004 L�N 000001200000
|
41
|
+
25000099004 AVSER PERIODEN 1/3-1/4
|
42
|
+
14000099004 SEMESTERERS�TTNING 000000050000
|
43
|
+
15000099004 LUNCHAVDRAG 000000050000
|
44
|
+
29000991234600000008000006295600
|
45
|
+
1100XXXXXXXX060328LEVERANT�RSBETALNINGAR060415 EUR
|
46
|
+
12NY ADRESS:HOLMV�GEN 20 10518 NYSTAD 060514
|
47
|
+
1400XXXXXXXX566986547214 000000005200
|
48
|
+
1400XXXXXXXX421948311319 000000063200
|
49
|
+
40000099006 XXXX00000XXXXXXX
|
50
|
+
26000099006 SOFIA OLSSON
|
51
|
+
27000099006 TORSGATAN 28 44180ALINGS�S
|
52
|
+
14000099006 Resers�ttning 000000012000
|
53
|
+
25000099006 AVSER PERIODEN 1/3-1/4
|
54
|
+
14000099006 Milers�ttning 000000010000
|
55
|
+
15000099006 Skuld 000000006000
|
56
|
+
2900XXXXXXXX00000005000000084400
|
57
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SupplierPayments::PaymentFile::AbstractRecord do
|
4
|
+
context 'with a test record class' do
|
5
|
+
class TestRecord < SupplierPayments::PaymentFile::AbstractRecord
|
6
|
+
self.transaction_code = '99'
|
7
|
+
self.layout = [
|
8
|
+
[ :transaction_code!, 2, 'N' ],
|
9
|
+
[ :foo, 14, 'N', :zerofill, :right_align ],
|
10
|
+
[ :bar, 20, 'A' ],
|
11
|
+
[ :reserved!, 5, 'N', :zerofill ],
|
12
|
+
[ :baz, 10, 'A', :right_align, :upcase ],
|
13
|
+
[ :reserved!, 29, 'A' ]
|
14
|
+
]
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should parse a line' do
|
18
|
+
record = TestRecord.parse("9900000000054321BBBBBBBBBBBBBBBBBBBBxxxxx YYYYY ")
|
19
|
+
expect(record.transaction_code).to eq("99")
|
20
|
+
expect(record.foo).to eq("00000000054321")
|
21
|
+
expect(record.bar).to eq("BBBBBBBBBBBBBBBBBBBB")
|
22
|
+
expect(record.baz).to eq(" YYYYY")
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should make a line' do
|
26
|
+
record = TestRecord.new
|
27
|
+
record.foo = 1234
|
28
|
+
record.bar = "ASDFG"
|
29
|
+
record.baz = "Ghijk"
|
30
|
+
expect(record.to_s).to eq("9900000000001234ASDFG 00000 GHIJK ")
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should strip long lines' do
|
34
|
+
record = TestRecord.new
|
35
|
+
record.foo = 314159265358979323846
|
36
|
+
expect(record.to_s.length).to eq(80)
|
37
|
+
expect(record.to_s).to eq("9931415926535897 00000 ")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should complain if the sum of the lengths don't equal 80" do
|
42
|
+
expect {
|
43
|
+
Class.new(SupplierPayments::PaymentFile::AbstractRecord) do
|
44
|
+
self.transaction_code = "98"
|
45
|
+
self.layout = [
|
46
|
+
[ :transaction_code, 2, 'N' ]
|
47
|
+
]
|
48
|
+
end
|
49
|
+
}.to raise_error(SupplierPayments::PaymentFile::AbstractRecord::LayoutError)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SupplierPayments::PaymentFile do
|
4
|
+
describe ".load" do
|
5
|
+
context 'with LBin-exempel1.txt' do
|
6
|
+
before do
|
7
|
+
@raw_data = File.read(fixture_path('LBin-exempel1.txt'))
|
8
|
+
@raw_data.force_encoding("iso-8859-15")
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should load a file' do
|
12
|
+
file = SupplierPayments::PaymentFile.load(@raw_data)
|
13
|
+
@raw_data.lines.zip(file.to_s.lines).each do |line1, line2|
|
14
|
+
expect(line1.strip).to eq(line2.force_encoding("iso-8859-15").strip)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'with LBin-exempel2.txt' do
|
20
|
+
before do
|
21
|
+
@raw_data = File.read(fixture_path('LBin-exempel2.txt'))
|
22
|
+
@raw_data.force_encoding("iso-8859-15")
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should load a file' do
|
26
|
+
file = SupplierPayments::PaymentFile.load(@raw_data)
|
27
|
+
@raw_data.lines.zip(file.to_s.lines).each do |line1, line2|
|
28
|
+
expect(line1.strip).to eq(line2.force_encoding("iso-8859-15").strip)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#to_s" do
|
35
|
+
class TestRecord < SupplierPayments::PaymentFile::AbstractRecord
|
36
|
+
self.transaction_code = '99'
|
37
|
+
self.layout = [
|
38
|
+
[ :transaction_code!, 2, 'N' ],
|
39
|
+
[ :foo, 14, 'N', :zerofill, :right_align ],
|
40
|
+
[ :bar, 20, 'A' ],
|
41
|
+
[ :reserved!, 5, 'N', :zerofill ],
|
42
|
+
[ :baz, 10, 'A', :right_align, :upcase ],
|
43
|
+
[ :reserved!, 29, 'A' ]
|
44
|
+
]
|
45
|
+
end
|
46
|
+
|
47
|
+
it "enforces ISO-8859-15 encoding" do
|
48
|
+
record = TestRecord.new
|
49
|
+
expect(record.to_s.encoding).to eq(Encoding::UTF_8) # Sanity
|
50
|
+
expect(SupplierPayments::PaymentFile.new([ record ]).to_s.encoding).to eq(Encoding::ISO_8859_15)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "supplier_payments/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "supplier_payments"
|
7
|
+
s.version = SupplierPayments::VERSION
|
8
|
+
s.authors = ["Andreas Alin"]
|
9
|
+
s.email = ["andreas.alin@gmail.com"]
|
10
|
+
s.homepage = "https://github.com/barsoom/supplier_payments"
|
11
|
+
s.summary = %q{Parse and generate supplier payment files for Bankgirot.}
|
12
|
+
s.description = %q{Parse and generate supplier payment files for "Leverantörsbetalningar" in Bankgirot.}
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
end
|
metadata
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: supplier_payments
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andreas Alin
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-04-30 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Parse and generate supplier payment files for "Leverantörsbetalningar"
|
14
|
+
in Bankgirot.
|
15
|
+
email:
|
16
|
+
- andreas.alin@gmail.com
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- ".circleci/config.yml"
|
22
|
+
- ".gitignore"
|
23
|
+
- Gemfile
|
24
|
+
- README.md
|
25
|
+
- Rakefile
|
26
|
+
- lib/supplier_payments.rb
|
27
|
+
- lib/supplier_payments/payment_file.rb
|
28
|
+
- lib/supplier_payments/payment_file/domestic_records.rb
|
29
|
+
- lib/supplier_payments/payment_file/records.rb
|
30
|
+
- lib/supplier_payments/version.rb
|
31
|
+
- spec/fixtures/LBin-exempel1.txt
|
32
|
+
- spec/fixtures/LBin-exempel2.txt
|
33
|
+
- spec/spec_helper.rb
|
34
|
+
- spec/supplier_payments/payment_file/records_spec.rb
|
35
|
+
- spec/supplier_payments/payment_file_spec.rb
|
36
|
+
- supplier_payments.gemspec
|
37
|
+
homepage: https://github.com/barsoom/supplier_payments
|
38
|
+
licenses: []
|
39
|
+
metadata: {}
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options: []
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
requirements: []
|
55
|
+
rubygems_version: 3.1.2
|
56
|
+
signing_key:
|
57
|
+
specification_version: 4
|
58
|
+
summary: Parse and generate supplier payment files for Bankgirot.
|
59
|
+
test_files: []
|