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 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,7 @@
1
+ module MediServ::API
2
+ class Storage
3
+ def put(k, v)
4
+ raise StandardError, 'unimplemented method #put'
5
+ end
6
+ end
7
+ 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
@@ -0,0 +1,6 @@
1
+ module MediServ::API
2
+ require 'mediserv/api/error'
3
+ require 'mediserv/api/types'
4
+ require 'mediserv/api/storage'
5
+ require 'mediserv/api/client'
6
+ end
data/lib/mediserv.rb ADDED
@@ -0,0 +1,3 @@
1
+ module MediServ
2
+ require 'mediserv/api'
3
+ end
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: []