supplier_payments 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![CircleCI](https://circleci.com/gh/barsoom/supplier_payments.svg?style=svg)](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: []
|