mediserv 0.1.0
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/lib/mediserv/api/client.rb +33 -0
- data/lib/mediserv/api/encoder.rb +66 -0
- data/lib/mediserv/api/error.rb +13 -0
- data/lib/mediserv/api/format.rb +19 -0
- data/lib/mediserv/api/storage.rb +7 -0
- data/lib/mediserv/api/types.rb +378 -0
- data/lib/mediserv/api.rb +6 -0
- data/lib/mediserv.rb +3 -0
- metadata +78 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5204dd01be4fb9c2d2094f8d905239744bfbc3994a37af6a03ba9498ae26749c
|
4
|
+
data.tar.gz: ec11e152aef07451253f7833697957d1a314e5668c0a5c00de8bc5432781dd84
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a043815bb4d3162fb02476447f4f5651d3f6a567f84051a772932db0f32f181b19e8508c56af1c34611e96eac09c00296bb35d05945553cca149aae67753fd14
|
7
|
+
data.tar.gz: 0cdde28234817de97f0dd3425feba8c868d07766f4e7faa68c7e1c5b1b8ed57fc994bd1c605f2dbb110ed04982645b2a36fc0445f943459dd96f408f8996f196
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module MediServ::API
|
2
|
+
require 'toml-rb'
|
3
|
+
|
4
|
+
require_relative "encoder"
|
5
|
+
require_relative "error"
|
6
|
+
require_relative "types"
|
7
|
+
|
8
|
+
class Client
|
9
|
+
# * *Args* :
|
10
|
+
def initialize(clientId, storage)
|
11
|
+
@storage = storage
|
12
|
+
@encoder = MediServ::API::Encoder.new
|
13
|
+
@default_header = {
|
14
|
+
programm: 'MediServ gem',
|
15
|
+
programm_version: '0.0.1', # TODO: Load from gemspec
|
16
|
+
version: 'v2',
|
17
|
+
kundennummer: clientId,
|
18
|
+
stapelnummer: 0,
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def batch(id, invoices, created_at: DateTime.now)
|
23
|
+
b = MediServ::API::Batch.new({
|
24
|
+
allgemein: @default_header.merge({
|
25
|
+
stapelnummer: id,
|
26
|
+
}),
|
27
|
+
rechnungen: invoices,
|
28
|
+
created_at: created_at,
|
29
|
+
})
|
30
|
+
@storage.put(id, @encoder.encode(b.to_h))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module MediServ::API
|
2
|
+
require_relative "format"
|
3
|
+
|
4
|
+
class Encoder
|
5
|
+
def encode(h)
|
6
|
+
build_tree(Node.new, h).to_ini
|
7
|
+
end
|
8
|
+
|
9
|
+
def build_tree(node, h)
|
10
|
+
h.each do |k, v|
|
11
|
+
case v
|
12
|
+
when Hash
|
13
|
+
child = Node.new(name: [node.name, k].compact.join('.'))
|
14
|
+
node.children << child
|
15
|
+
build_tree(child, v)
|
16
|
+
else
|
17
|
+
node.attributes[k] = v
|
18
|
+
end
|
19
|
+
end
|
20
|
+
node
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Node
|
25
|
+
include Format
|
26
|
+
|
27
|
+
attr_accessor :name, :attributes, :children
|
28
|
+
|
29
|
+
def initialize(name: nil, attributes: {}, children: [])
|
30
|
+
@name = name
|
31
|
+
@attributes = attributes
|
32
|
+
@children = children
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_ini(io = StringIO.new)
|
36
|
+
if name
|
37
|
+
io << '['
|
38
|
+
io << name
|
39
|
+
io << ']'
|
40
|
+
io << "\n"
|
41
|
+
end
|
42
|
+
attributes.each do |k, v|
|
43
|
+
next unless k && v
|
44
|
+
io << k.to_s
|
45
|
+
io << '='
|
46
|
+
|
47
|
+
v = case v
|
48
|
+
when Float
|
49
|
+
io << fmt_amount(v)
|
50
|
+
when String
|
51
|
+
io << '"'
|
52
|
+
io << v.tr("\n", '')
|
53
|
+
io << '"'
|
54
|
+
else
|
55
|
+
io << v
|
56
|
+
end
|
57
|
+
io << "\n"
|
58
|
+
end
|
59
|
+
children.each do |c|
|
60
|
+
io << "\n"
|
61
|
+
c.to_ini(io)
|
62
|
+
end
|
63
|
+
io.string.encode('windows-1252')
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module MediServ::API
|
2
|
+
class MissingError < StandardError
|
3
|
+
end
|
4
|
+
class BadRequestError < StandardError
|
5
|
+
end
|
6
|
+
class PermissionError < StandardError
|
7
|
+
end
|
8
|
+
class UnauthenticatedError < StandardError
|
9
|
+
end
|
10
|
+
class ConflictError < StandardError
|
11
|
+
# TODO: Add resource
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module MediServ::API
|
2
|
+
module Format
|
3
|
+
def fmt_date(d)
|
4
|
+
d ? d.strftime('%d.%m.%Y') : ''
|
5
|
+
end
|
6
|
+
|
7
|
+
def fmt_time(t)
|
8
|
+
t ? t.strftime('%H:%M') : ''
|
9
|
+
end
|
10
|
+
|
11
|
+
def fmt_amount(n)
|
12
|
+
n ? sprintf('%0.2f', n) : '0.00'
|
13
|
+
end
|
14
|
+
|
15
|
+
def fmt_string(s, max: nil)
|
16
|
+
max ? s[0..max] : s
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,378 @@
|
|
1
|
+
module MediServ::API
|
2
|
+
require 'dry-types'
|
3
|
+
require 'dry-struct'
|
4
|
+
|
5
|
+
require_relative "format"
|
6
|
+
|
7
|
+
module Types
|
8
|
+
include Dry.Types()
|
9
|
+
end
|
10
|
+
|
11
|
+
class Struct < Dry::Struct
|
12
|
+
include Format
|
13
|
+
end
|
14
|
+
|
15
|
+
class Recipient < Struct
|
16
|
+
# Nummer des Empfängers
|
17
|
+
attribute :nummer, Types::Strict::Integer
|
18
|
+
# Art des Empfängers (Garant oder Gesetz_Vertreter)
|
19
|
+
attribute :art, Types::Strict::String
|
20
|
+
# Anrede in der Sprache der Rechnung
|
21
|
+
attribute :anrede, Types::Strict::String
|
22
|
+
# Titel in der Sprache der Rechnung
|
23
|
+
attribute :titel, Types::Strict::String
|
24
|
+
# Name
|
25
|
+
attribute :name, Types::Strict::String
|
26
|
+
# Vorname
|
27
|
+
attribute :vorname, Types::Strict::String
|
28
|
+
# Strasse mit Nummer
|
29
|
+
attribute :strasse, Types::Strict::String.optional.default(nil)
|
30
|
+
# Land (CH / D / F / ...)
|
31
|
+
attribute :land, Types::Strict::String
|
32
|
+
# Postleitzahl
|
33
|
+
attribute :plz, Types::Strict::String
|
34
|
+
# Ort
|
35
|
+
attribute :ort, Types::Strict::String
|
36
|
+
# Geburtsdatum
|
37
|
+
attribute :geburtsdatum, Types::Strict::Date
|
38
|
+
end
|
39
|
+
|
40
|
+
class Patient < Struct
|
41
|
+
# Patientennummer
|
42
|
+
attribute :nummer, Types::Strict::Integer
|
43
|
+
# Anrede in der Sprache der Rechnung
|
44
|
+
attribute :anrede, Types::Strict::String
|
45
|
+
# Titel in der Sprache der Rechnung
|
46
|
+
attribute :titel, Types::Strict::String
|
47
|
+
# Name
|
48
|
+
attribute :name, Types::Strict::String
|
49
|
+
# Vorname
|
50
|
+
attribute :vorname, Types::Strict::String
|
51
|
+
# Strasse mit Nummer
|
52
|
+
attribute :strasse, Types::Strict::String.optional.default(nil)
|
53
|
+
# Zusatzadresse
|
54
|
+
attribute :zusatz, Types::Strict::String.optional.default(nil)
|
55
|
+
# Land (CH / D / F / ...)
|
56
|
+
attribute :land, Types::Strict::String
|
57
|
+
# Postleitzahl
|
58
|
+
attribute :plz, Types::Strict::String
|
59
|
+
# Ort
|
60
|
+
attribute :ort, Types::Strict::String
|
61
|
+
# Geburtsdatum
|
62
|
+
attribute :geburtsdatum, Types::Strict::Date
|
63
|
+
end
|
64
|
+
|
65
|
+
class InvoiceItem < Struct
|
66
|
+
Art = Types::Integer.enum(
|
67
|
+
0 => 'leistung',
|
68
|
+
1 => 'medikament',
|
69
|
+
2 => 'labo',
|
70
|
+
3 => 'diverse',
|
71
|
+
)
|
72
|
+
|
73
|
+
# Datum der Leistung
|
74
|
+
attribute :datum, Types::Strict::Date
|
75
|
+
# Anzahl der Leistung
|
76
|
+
attribute :anzahl, Types::Strict::Integer
|
77
|
+
# Zahnnummer der Leistung, Freie Eingabe des Zahnarztes.
|
78
|
+
attribute :zahnnummer, Types::Strict::String.optional.default(nil)
|
79
|
+
# Art der Leistung (0=Leistung, 1=Medikament, 2=Labo, 3=Diverse)
|
80
|
+
attribute :art, Art
|
81
|
+
# Nummer der Leistung
|
82
|
+
attribute :nummer, Types::Strict::String.optional.default(nil)
|
83
|
+
# Bezeichnung in der Sprache der Rechnung
|
84
|
+
attribute :bezeichnung, Types::Strict::String
|
85
|
+
# Ansatz der Leistung
|
86
|
+
attribute :ansatz, Types::Strict::Float.optional.default(nil)
|
87
|
+
# Punkte der Leistung
|
88
|
+
attribute :punkte, Types::Strict::Float.optional.default(nil)
|
89
|
+
# Auf der Leistung ist ein Rabatt gewährt (0 = ohne Rabatt; 1 = mit Rabatt)
|
90
|
+
attribute :rabatt, Types::Strict::Bool.default(false)
|
91
|
+
# Betrag
|
92
|
+
attribute :betrag, Types::Strict::Float
|
93
|
+
|
94
|
+
# Bruttobetrag (Anzahl * Betrag)
|
95
|
+
def total
|
96
|
+
anzahl * betrag
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class Invoice < Struct
|
101
|
+
BehandlungStatus = Types::Integer.enum(
|
102
|
+
0 => 'laufend',
|
103
|
+
1 => 'abgeschlossen',
|
104
|
+
)
|
105
|
+
BehandlungTyp = Types::String.enum(
|
106
|
+
'PP',
|
107
|
+
'VS',
|
108
|
+
'IV',
|
109
|
+
'KK',
|
110
|
+
)
|
111
|
+
Sprache = Types::Integer.enum(
|
112
|
+
1 => 'DE',
|
113
|
+
2 => 'FR',
|
114
|
+
3 => 'IT',
|
115
|
+
4 => 'EN',
|
116
|
+
)
|
117
|
+
|
118
|
+
# Rechnungsnummer aus dem Programm
|
119
|
+
attribute :nummer, Types::Strict::Integer
|
120
|
+
# Datum der Rechnung (kann auch vordatiert sein)
|
121
|
+
attribute :datum, Types::Strict::Date
|
122
|
+
# Behandlungsbeginn
|
123
|
+
attribute :behandlungsbeginn, Types::Strict::Date
|
124
|
+
# Behandlungsende
|
125
|
+
attribute :behandlungsende, Types::Strict::Date
|
126
|
+
# 0=Behandlung laufend, 1=Behandlung abgeschlossen
|
127
|
+
attribute :behandlungstatus, BehandlungStatus
|
128
|
+
# Typ der Behandlung (PP / VS / IV / KK)
|
129
|
+
attribute :behandlungstyp, BehandlungTyp
|
130
|
+
# Sprache der Rechnung (1=deu, 2=franz. 3=ital. 4=engl.)
|
131
|
+
attribute :sprache, Sprache
|
132
|
+
# Rechnungsüberschrift
|
133
|
+
attribute :rech_titel, Types::Strict::String.optional.default(nil)
|
134
|
+
# Rechnungstext pro Zeile ein Eintrag
|
135
|
+
attribute :rech_text, Types::Strict::String.optional.default(nil)
|
136
|
+
# Versicherungsnummer
|
137
|
+
attribute :versicherungsnummer, Types::Strict::String.optional.default(nil)
|
138
|
+
# Rabatt in Prozent auf den markierten Leistungen
|
139
|
+
attribute :rabatt, Types::Strict::Integer.optional.default(nil)
|
140
|
+
# Datum der Verfügung
|
141
|
+
attribute :verfugungs_datum, Types::Strict::Date.optional.default(nil)
|
142
|
+
# Nummer der Verfügung
|
143
|
+
attribute :verfugungs_nummer, Types::Strict::Integer.optional.default(nil)
|
144
|
+
# Anhang
|
145
|
+
attribute :anhange, Types::Strict::Array.of(Types::Strict::String).default([].freeze)
|
146
|
+
|
147
|
+
# Rechnungsbetrag (ohne Vorauszahlungen)
|
148
|
+
attribute :total_rabatt, Types::Strict::Float
|
149
|
+
# Total aller Vorauszahlungen dieser Rechnung
|
150
|
+
attribute :total_vz, Types::Strict::Float
|
151
|
+
|
152
|
+
attribute :empfanger, Recipient.optional.default(nil)
|
153
|
+
attribute :patient, Patient
|
154
|
+
attribute :leistungen, Types::Strict::Array.of(InvoiceItem)
|
155
|
+
|
156
|
+
def total_punkte
|
157
|
+
leistungen.select{|l| l.punkte != nil }.map(&:punkte).reduce(0.0, :+)
|
158
|
+
end
|
159
|
+
|
160
|
+
# Total von allen Leistungen
|
161
|
+
def total_leis
|
162
|
+
leistungen.select{|l| l.art == 0 }.map(&:total).reduce(0.0, :+)
|
163
|
+
end
|
164
|
+
|
165
|
+
# Rechnungsbetrag (ohne Vorauszahlungen)
|
166
|
+
def total_med
|
167
|
+
leistungen.select{|l| l.art == 1 }.map(&:total).reduce(0.0, :+)
|
168
|
+
end
|
169
|
+
|
170
|
+
# Rechnungsbetrag (ohne Vorauszahlungen)
|
171
|
+
def total_labor
|
172
|
+
leistungen.select{|l| l.art == 2 }.map(&:total).reduce(0.0, :+)
|
173
|
+
end
|
174
|
+
|
175
|
+
# Rechnungsbetrag (ohne Vorauszahlungen)
|
176
|
+
def total_diverse
|
177
|
+
leistungen.select{|l| l.art == 3 }.map(&:total).reduce(0.0, :+)
|
178
|
+
end
|
179
|
+
|
180
|
+
# Total minus Vorauszahlungen dieser Rechnung
|
181
|
+
def total_netto
|
182
|
+
total_leis + total_med + total_labor + total_diverse + total_rabatt
|
183
|
+
end
|
184
|
+
|
185
|
+
# Rechnungsbetrag (ohne Vorauszahlungen)
|
186
|
+
def rechnungsbetrag
|
187
|
+
total_netto + total_vz
|
188
|
+
end
|
189
|
+
|
190
|
+
def to_h
|
191
|
+
h = {
|
192
|
+
RechNr: nummer,
|
193
|
+
RechDat: datum.strftime('%d.%m.%Y'),
|
194
|
+
BehBeginn: behandlungsbeginn.strftime('%d.%m.%Y'),
|
195
|
+
BehEnde: behandlungsende.strftime('%d.%m.%Y'),
|
196
|
+
BehStatus: behandlungstatus,
|
197
|
+
BehTyp: behandlungstyp,
|
198
|
+
RechBetrag: rechnungsbetrag,
|
199
|
+
TotalLeis: total_leis,
|
200
|
+
TotalMed: total_med,
|
201
|
+
TotalLabor: total_labor,
|
202
|
+
TotalDiverse: total_diverse,
|
203
|
+
TotalRabatt: total_rabatt,
|
204
|
+
TotalVZ: total_vz,
|
205
|
+
TotalNetto: total_netto,
|
206
|
+
Sprache: sprache,
|
207
|
+
PatNr: patient.nummer,
|
208
|
+
PatAnrede: fmt_string(patient.anrede, max: 4),
|
209
|
+
PatTitel: fmt_string(patient.titel, max: 20),
|
210
|
+
PatName: fmt_string(patient.name, max: 40),
|
211
|
+
PatVorname: fmt_string(patient.vorname, max: 40),
|
212
|
+
PatStrasse: fmt_string(patient.strasse, max: 30),
|
213
|
+
PatZusatz: fmt_string(patient.zusatz, max: 20),
|
214
|
+
PatLand: fmt_string(patient.land, max: 3),
|
215
|
+
PatPLZ: fmt_string(patient.plz, max: 10),
|
216
|
+
PatOrt: fmt_string(patient.ort, max: 40),
|
217
|
+
PatGebDatum: fmt_date(patient.geburtsdatum),
|
218
|
+
}
|
219
|
+
h[:RechTitel] = rech_titel[0..180] unless rech_titel.nil?
|
220
|
+
h[:VersNr] = versicherungsnummer unless versicherungsnummer.nil?
|
221
|
+
h[:Rabatt] = rabatt unless rabatt.nil?
|
222
|
+
h[:VerfügungsDat] = verfugungs_datum unless verfugungs_datum.nil?
|
223
|
+
h[:VerfügungsNr] = verfugungs_nummer unless verfugungs_nummer.nil?
|
224
|
+
if empfanger
|
225
|
+
h[:EmpfNr] = empfanger.nummer
|
226
|
+
h[:EmpfArt] = fmt_string(empfanger.art, max: 20)
|
227
|
+
h[:EmpfAnrede] = fmt_string(empfanger.anrede, max: 4)
|
228
|
+
h[:EmpfTitel] = fmt_string(empfanger.titel, max: 20)
|
229
|
+
h[:EmpfName] = fmt_string(empfanger.name, max: 40)
|
230
|
+
h[:EmpfVorname] = fmt_string(empfanger.vorname, max: 40)
|
231
|
+
h[:EmpfStrasse] = fmt_string(empfanger.strasse, max: 20)
|
232
|
+
h[:EmpfLand] = fmt_string(empfanger.land, max: 3)
|
233
|
+
h[:EmpfPLZ] = fmt_string(empfanger.plz, max: 10)
|
234
|
+
h[:EmpfOrt] = fmt_string(empfanger.ort, max: 40)
|
235
|
+
h[:EmpfGebDatum] = fmt_date(empfanger.geburtsdatum)
|
236
|
+
end
|
237
|
+
anhange.each.with_index(1) do |a, i|
|
238
|
+
# Path to attachment file
|
239
|
+
h["Anhang#{i}"] = a
|
240
|
+
end
|
241
|
+
rech_text.scan(/.{1,180}/).each.with_index(1) do |s, i|
|
242
|
+
# A line will go up to 180 characters, but could be shorter in case of a
|
243
|
+
# new line or simply a short line.
|
244
|
+
h["RechText[#{i}]"] = s
|
245
|
+
end unless rech_text.nil?
|
246
|
+
leistungen.each.with_index(1) do |l, i|
|
247
|
+
# Total der Punkt von Ansatz
|
248
|
+
# h["TotalPkt[#{i}]"] = l.punkte || 0.0
|
249
|
+
# Ansatz für Punkte
|
250
|
+
# h["TotalAnsatz[#{i}]"] = l.ansatz || 0.0
|
251
|
+
|
252
|
+
h["LeisDatum[#{i}]"] = fmt_date(l.datum)
|
253
|
+
h["LeisAnz[#{i}]"] = fmt_amount(l.anzahl)
|
254
|
+
h["LeisZahnNr[#{i}]"] = l.zahnnummer
|
255
|
+
h["LeisArt[#{i}]"] = l.art
|
256
|
+
h["LeisPosNr[#{i}]"] = l.nummer
|
257
|
+
h["LeisBez[#{i}]"] = l.bezeichnung
|
258
|
+
h["LeisAnsatz[#{i}]"] = l.ansatz
|
259
|
+
h["LeisPkt[#{i}]"] = l.punkte
|
260
|
+
h["LeisRabatt[#{i}]"] = l.rabatt ? 1 : 0
|
261
|
+
h["LeisBetrag[#{i}]"] = l.betrag
|
262
|
+
h["LeisTotal[#{i}]"] = l.total
|
263
|
+
end
|
264
|
+
h
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
# Folgende Einträge sind 1x pro Datei vorhanden
|
269
|
+
class Header < Struct
|
270
|
+
# Programmname
|
271
|
+
attribute :programm, Types::Strict::String
|
272
|
+
# Programm Version
|
273
|
+
attribute :programm_version, Types::Strict::String
|
274
|
+
# Schnittstellenversion
|
275
|
+
attribute :version, Types::Strict::String
|
276
|
+
# Eindeutige Kundennummer bei Mediserv
|
277
|
+
attribute :kundennummer, Types::Strict::Integer
|
278
|
+
# Die Stapelnummer ist eine fortlaufende Nummer. Für jede Datei eine neue Nummer
|
279
|
+
attribute :stapelnummer, Types::Strict::Integer
|
280
|
+
|
281
|
+
def to_h
|
282
|
+
{
|
283
|
+
Programm: programm,
|
284
|
+
ProgrammVersion: programm_version,
|
285
|
+
Version: version,
|
286
|
+
KuNr: kundennummer,
|
287
|
+
StapelNr: stapelnummer,
|
288
|
+
}
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
class Batch < Struct
|
293
|
+
attribute :allgemein, MediServ::API::Header
|
294
|
+
attribute :rechnungen, Types::Strict::Array.of(MediServ::API::Invoice)
|
295
|
+
attribute :created_at, Types::Strict::DateTime
|
296
|
+
|
297
|
+
# Anzahl Rechnungen
|
298
|
+
def anzahl_rechnungen
|
299
|
+
rechnungen.length
|
300
|
+
end
|
301
|
+
|
302
|
+
# Gesamtsumme Taxpunkte
|
303
|
+
def total_pkt
|
304
|
+
rechnungen.map(&:total_punkte).reduce(0.0, :+)
|
305
|
+
end
|
306
|
+
|
307
|
+
# Gesamtsumme aller Leistungen
|
308
|
+
def total_leis
|
309
|
+
rechnungen.map(&:total_leis).reduce(0.0, :+)
|
310
|
+
end
|
311
|
+
|
312
|
+
# Gesamtsumme aller Medikamente
|
313
|
+
def total_med
|
314
|
+
rechnungen.map(&:total_med).reduce(0.0, :+)
|
315
|
+
end
|
316
|
+
|
317
|
+
# Gesamtsumme aller Laborkosten
|
318
|
+
def total_labor
|
319
|
+
rechnungen.map(&:total_labor).reduce(0.0, :+)
|
320
|
+
end
|
321
|
+
|
322
|
+
# Gesamtsumme Diverse Positionen
|
323
|
+
def total_diverse
|
324
|
+
rechnungen.map(&:total_diverse).reduce(0.0, :+)
|
325
|
+
end
|
326
|
+
|
327
|
+
# Gesamtsumme Rabatte
|
328
|
+
def total_rabatt
|
329
|
+
rechnungen.map(&:total_rabatt).reduce(0.0, :+)
|
330
|
+
end
|
331
|
+
|
332
|
+
# Gesamtsumme der abgezogenen Vorauszahlungen
|
333
|
+
def total_vz
|
334
|
+
rechnungen.map(&:total_vz).reduce(0.0, :+)
|
335
|
+
end
|
336
|
+
|
337
|
+
# Gesamtsumme Total (ist auch die Summe von TotalLeis + TotalMed + TotalLabor + TotalDiverse + TotalRabatt)
|
338
|
+
def total
|
339
|
+
total_leis + total_med + total_labor + total_diverse + total_rabatt
|
340
|
+
end
|
341
|
+
|
342
|
+
# Nettosumme (Total – Vorauszahlung)
|
343
|
+
def total_netto
|
344
|
+
total - total_vz
|
345
|
+
end
|
346
|
+
|
347
|
+
def to_h
|
348
|
+
h = {
|
349
|
+
Allgemein: allgemein.to_h.merge({
|
350
|
+
Total: total,
|
351
|
+
TotalPkt: total_pkt,
|
352
|
+
TotalLeis: total_leis,
|
353
|
+
TotalMed: total_med,
|
354
|
+
TotalLabor: total_labor,
|
355
|
+
TotalDiverse: total_diverse,
|
356
|
+
TotalRabatt: total_rabatt,
|
357
|
+
TotalVz: total_vz,
|
358
|
+
TotalNetto: total_netto,
|
359
|
+
Datum: fmt_date(created_at),
|
360
|
+
Zeit: fmt_time(created_at),
|
361
|
+
AnzRech: anzahl_rechnungen,
|
362
|
+
}),
|
363
|
+
}
|
364
|
+
rechnungen.each.with_index(1) do |r,i|
|
365
|
+
h["R#{i}"] = r.to_h
|
366
|
+
end
|
367
|
+
stringify_keys h
|
368
|
+
end
|
369
|
+
|
370
|
+
def stringify_keys(h)
|
371
|
+
h.reduce({}) do |h, (k,v)|
|
372
|
+
v = stringify_keys(v) if v.kind_of?(Hash)
|
373
|
+
h.merge({k.to_s => v})
|
374
|
+
end
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
end
|
data/lib/mediserv/api.rb
ADDED
data/lib/mediserv.rb
ADDED
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mediserv
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Denteo AG
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-10-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: dry-types
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.5.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.5.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: dry-struct
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.4.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.4.0
|
41
|
+
description: Ruby client interacting with MediServ
|
42
|
+
email: simon@denteo.ch
|
43
|
+
executables: []
|
44
|
+
extensions: []
|
45
|
+
extra_rdoc_files: []
|
46
|
+
files:
|
47
|
+
- lib/mediserv.rb
|
48
|
+
- lib/mediserv/api.rb
|
49
|
+
- lib/mediserv/api/client.rb
|
50
|
+
- lib/mediserv/api/encoder.rb
|
51
|
+
- lib/mediserv/api/error.rb
|
52
|
+
- lib/mediserv/api/format.rb
|
53
|
+
- lib/mediserv/api/storage.rb
|
54
|
+
- lib/mediserv/api/types.rb
|
55
|
+
homepage: https://rubygems.org/gems/mediserv
|
56
|
+
licenses:
|
57
|
+
- MIT
|
58
|
+
metadata: {}
|
59
|
+
post_install_message:
|
60
|
+
rdoc_options: []
|
61
|
+
require_paths:
|
62
|
+
- lib
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
requirements: []
|
74
|
+
rubygems_version: 3.1.2
|
75
|
+
signing_key:
|
76
|
+
specification_version: 4
|
77
|
+
summary: Ruby client interacting with MediServ
|
78
|
+
test_files: []
|