GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

kerapu.command.TestsetShredderCommand   A
last analyzed

Complexity

Total Complexity 27

Size/Duplication

Total Lines 267
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
eloc 139
dl 0
loc 267
ccs 0
cts 109
cp 0
rs 10
c 0
b 0
f 0
wmc 27

10 Methods

Rating   Name   Duplication   Size   Complexity  
A TestShredderCommand.__convert_date() 0 10 1
C TestShredderCommand.__shred_xml_bestand() 0 93 10
A TestShredderCommand.__extract_zip_file() 0 11 2
A TestShredderCommand.__write_subtraject() 0 21 2
A TestShredderCommand.__leeftijd_geboorte_datum() 0 14 1
A TestShredderCommand.__lees_test_cases_lijst() 0 16 3
A TestShredderCommand.__extract_files() 0 10 2
A TestShredderCommand.ordinal() 0 10 1
A TestShredderCommand.__maak_xpath() 0 16 3
A TestShredderCommand.handle() 0 22 2
1
import csv
2
import datetime
3
import os
4
import random
5
import shutil
6
import string
7
import zipfile
8
from typing import Iterable, List, Dict
9
10
from cleo import Command
11
from lxml import etree
12
13
from kerapu.style.KerapuStyle import KerapuStyle
14
15
16
class TestShredderCommand(Command):
17
    """
18
    Converteert XML-bestand met de testset naar een CSV-bestand
19
20
    kerapu:test-shredder
21
        {testset-zip : ZIP-bestand met de testset}
22
        {testset-csv : Path waar het CSV-bestand met de tests moeten worden opgeslagen}
23
    """
24
25
    # ------------------------------------------------------------------------------------------------------------------
26
    def __extract_zip_file(self, zip_filename: str, tmp_dir: str):
27
        """
28
        Extracts het ZIP-bestand met de testset in een folder.
29
30
        :param str zip_filename: Het path naar het ZIP-bestand met de testset.
31
        :param str tmp_dir: Path naar de folder.
32
        """
33
        self.output.writeln('Uitpakken van <fso>{}</fso> in <fso>{}</fso>'.format(zip_filename, tmp_dir))
34
35
        with zipfile.ZipFile(zip_filename, 'r') as zip_ref:
36
            zip_ref.extractall(tmp_dir)
37
38
    # ------------------------------------------------------------------------------------------------------------------
39
    @staticmethod
40
    def ordinal(path: str) -> int:
41
        """
42
        Geeft het volgnummer van een test.
43
44
        :param str path: Het path naar het XML-bestand met de test case.
45
        """
46
        parts = os.path.basename(path).split('_')
47
48
        return int(parts[6])
49
50
    # ------------------------------------------------------------------------------------------------------------------
51
    def __lees_test_cases_lijst(self, folder: str) -> List:
52
        """
53
        Geeft een lijst met alle bestanden in een folder.
54
55
        :param str folder: Het path naar de folder.
56
        """
57
        entries = os.listdir(folder)
58
        filenames = list()
59
        for entry in entries:
60
            path = os.path.join(folder, entry)
61
            if os.path.isfile(path):
62
                filenames.append(path)
63
64
        self.output.writeln('Aantal gevonden test cases: {}'.format(len(filenames)))
65
66
        return sorted(filenames, key=TestShredderCommand.ordinal)
67
68
    # ------------------------------------------------------------------------------------------------------------------
69
    @staticmethod
70
    def __maak_xpath(parts: Iterable) -> str:
71
        """
72
        Maakt een string met een xpath.
73
74
        :param tuple parts: The onderdelen van het xpath.
75
76
        :rtype: str
77
        """
78
        xpath = ''
79
        for part in parts:
80
            if xpath:
81
                xpath += '/'
82
            xpath += 'xmlns:' + part
83
84
        return xpath
85
86
    # ------------------------------------------------------------------------------------------------------------------
87
    @staticmethod
88
    def __convert_date(date: str) -> str:
89
        """
90
        Converteert een datum in YYYYMMDD formaat naar YYYY-MM-DD format.
91
92
        :param str date: De datum in YYYYMMDD format.
93
94
        :rtype: str
95
        """
96
        return date[:4] + '-' + date[4:6] + '-' + date[6:8]
97
98
    # ------------------------------------------------------------------------------------------------------------------
99
    @staticmethod
100
    def __leeftijd_geboorte_datum(date: str, leeftijd: int) -> str:
101
        """
102
        Geeft de geboortedatum gegeven een datum en een leeftijd (en de persoon is niet jarig).
103
104
        :param str date: De gegeven datum in YYYY-MM-DD format.
105
        :param int leeftijd: De leeftijd in jaren.
106
107
        :rtype: int
108
        """
109
        date = datetime.date(int(date[:4]) - leeftijd, int(date[5:7]), int(date[8:10]))
110
        date -= datetime.timedelta(days=1)
111
112
        return date.isoformat()
113
114
    # ------------------------------------------------------------------------------------------------------------------
115
    def __shred_xml_bestand(self, filename: str) -> Dict:
116
        """
117
        Leest de relevante data in een XML-bestand met een test case.
118
119
        :param str filename: De filenaam van het XML bestand.
120
121
        :rtype: dict
122
        """
123
        doc = etree.parse(filename)
124
125
        xpath = '/soapenv:Envelope/soapenv:Body/xmlns:FICR_IN900101NL04'
126
        namespaces = {'soapenv': 'http://schemas.xmlsoap.org/soap/envelope/',
127
                      'xmlns':   'urn:hl7-org:v3'}
128
129
        # Lees declaratiecode.
130
        parts = ('ControlActProcess', 'subject', 'Declaratiedataset', 'component', 'subtraject', 'id')
131
        elements = doc.xpath(xpath + '/' + self.__maak_xpath(parts), namespaces=namespaces)
132
        declaratie_code = elements[0].get('extension')
133
134
        # Lees specialismecode.
135
        parts = ('ControlActProcess', 'subject', 'Declaratiedataset', 'component', 'subtraject', 'derivedFrom',
136
                 'zorgtraject', 'responsibleParty', 'assignedPerson', 'code')
137
        elements = doc.xpath(xpath + '/' + self.__maak_xpath(parts), namespaces=namespaces)
138
        specialisme_code = elements[0].get('code')
139
140
        # Lees diagnosecode.
141
        parts = (
142
            'ControlActProcess', 'subject', 'Declaratiedataset', 'component', 'subtraject', 'pertinentInformation1',
143
            'typerendeDiagnose', 'value')
144
        elements = doc.xpath(xpath + '/' + self.__maak_xpath(parts), namespaces=namespaces)
145
        diagnose_code = elements[0].get('code')
146
147
        # Lees zorgtypecode.
148
        parts = ('ControlActProcess', 'subject', 'Declaratiedataset', 'component', 'subtraject', 'code')
149
        elements = doc.xpath(xpath + '/' + self.__maak_xpath(parts), namespaces=namespaces)
150
        zorg_type_code = elements[0].get('code') if elements else None
151
152
        # Lees zorgvraagcode.
153
        parts = ('ControlActProcess', 'subject', 'Declaratiedataset', 'component', 'subtraject', 'derivedFrom',
154
                 'zorgtraject', 'reason', 'zorgvraag', 'value')
155
        elements = doc.xpath(xpath + '/' + self.__maak_xpath(parts), namespaces=namespaces)
156
        zorg_vraag_code = elements[0].get('code') if elements else None
157
158
        # Lees begindatum.
159
        parts = ('ControlActProcess', 'subject', 'Declaratiedataset', 'component', 'subtraject', 'effectiveTime', 'low')
160
        elements = doc.xpath(xpath + '/' + self.__maak_xpath(parts), namespaces=namespaces)
161
        begin_datum = self.__convert_date(elements[0].get('value')) if elements else None
162
163
        # Lees de geboortedatum van de patient.
164
        parts = ('ControlActProcess', 'subject', 'Declaratiedataset', 'subject', 'patient', 'subjectOf', 'leeftijd',
165
                 'value')
166
        elements = doc.xpath(xpath + '/' + self.__maak_xpath(parts), namespaces=namespaces)
167
        leeftijd = int(elements[0].get('value')) if elements else None
168
        geboorte_datum = self.__leeftijd_geboorte_datum(begin_datum, leeftijd)
169
170
        # Lees het geslacht van de patient.
171
        parts = ('ControlActProcess', 'subject', 'Declaratiedataset', 'subject', 'patient', 'patientPerson',
172
                 'administrativeGenderCode')
173
        elements = doc.xpath(xpath + '/' + self.__maak_xpath(parts), namespaces=namespaces)
174
        geslacht_code = elements[0].get('code') if elements else None
175
176
        # Lees de AGB-code van de zorginstelling.
177
        parts = ('ControlActProcess', 'subject', 'Declaratiedataset', 'author', 'assignedOrganization', 'id')
178
        elements = doc.xpath(xpath + '/' + self.__maak_xpath(parts), namespaces=namespaces)
179
        zorg_instelling_code = elements[0].get('extension') if elements else None
180
181
        # Lees alle zorgactiviteiten.
182
        zorg_activiteiten = list()
183
        parts = ('ControlActProcess', 'subject', 'Declaratiedataset', 'component', 'subtraject', 'debit',
184
                 'zorgactiviteit')
185
        elements = doc.xpath(xpath + '/' + self.__maak_xpath(parts), namespaces=namespaces)
186
        for element in elements:
187
            path = 'xmlns:code'
188
            sub_elements = element.xpath(path, namespaces=namespaces)
189
            zorg_activiteit_code = sub_elements[0].get('code') if sub_elements else None
190
191
            path = 'xmlns:repeatNumber'
192
            sub_elements = element.xpath(path, namespaces=namespaces)
193
            aantal = int(sub_elements[0].get('value')) if sub_elements else None
194
195
            zorg_activiteiten.append((zorg_activiteit_code, aantal))
196
197
        return {'subtraject_nummer':    os.path.basename(filename),
198
                'declaratie_code':      declaratie_code,
199
                'specialisme_code':     specialisme_code,
200
                'diagnose_code':        diagnose_code,
201
                'zorg_type_code':       zorg_type_code,
202
                'zorg_vraag_code':      zorg_vraag_code,
203
                'begin_datum':          begin_datum,
204
                'geboorte_datum':       geboorte_datum,
205
                'geslacht_code':        geslacht_code,
206
                'zorg_instelling_code': zorg_instelling_code,
207
                'zorg_activiteiten':    zorg_activiteiten}
208
209
    # ----------------------------------------------------------------------------------------------------------------------
210
    @staticmethod
211
    def __write_subtraject(writer, subtraject: Dict) -> None:
212
        """
213
        Schrijft het subtraject met alle zorgactiviteiten naar een CSV-bestand.
214
215
        :param writer: De handle naar de CSV writer.
216
        :param dict subtraject: De details van het subtract.
217
        """
218
        writer.writerow((subtraject['subtraject_nummer'],
219
                         subtraject['specialisme_code'],
220
                         subtraject['diagnose_code'],
221
                         subtraject['zorg_type_code'],
222
                         subtraject['zorg_vraag_code'],
223
                         subtraject['begin_datum'],
224
                         subtraject['geboorte_datum'],
225
                         subtraject['geslacht_code'],
226
                         subtraject['zorg_instelling_code'],
227
                         subtraject['declaratie_code']))
228
229
        for zorgactiviteit in subtraject['zorg_activiteiten']:
230
            writer.writerow((zorgactiviteit[0], zorgactiviteit[1]))
231
232
    # ----------------------------------------------------------------------------------------------------------------------
233
    def __extract_files(self, writer, filenames: List) -> None:
234
        """
235
        Extract de data van een lijst met XML-bestanden met test cases en schrijft deze data naar een CSV-bestand.
236
237
        :param writer:  De handle naar de CSV writer.
238
        :param list filenames: De lijst met bestandsnamen van XML-bestanden met test cases.
239
        """
240
        for filename in filenames:
241
            subtraject = self.__shred_xml_bestand(filename)
242
            self.__write_subtraject(writer, subtraject)
243
244
    # ------------------------------------------------------------------------------------------------------------------
245
    def handle(self) -> int:
246
        """
247
        Executes the command.
248
        """
249
        self.output = KerapuStyle(self.input, self.output)
250
251
        zip_filename = self.argument('testset-zip')
252
        csv_filename = self.argument('testset-csv')
253
        tmp_dir = '.kerapu-' + ''.join(random.choices(string.ascii_lowercase, k=12))
254
255
        os.mkdir(tmp_dir)
256
257
        self.__extract_zip_file(zip_filename, tmp_dir)
258
        files = self.__lees_test_cases_lijst(tmp_dir)
259
260
        with open(csv_filename, 'w', encoding='utf-8') as handle:
261
            csv_writer = csv.writer(handle, dialect=csv.unix_dialect)
262
            self.__extract_files(csv_writer, files)
263
264
        shutil.rmtree(tmp_dir)
265
266
        return 0
267
268
# ----------------------------------------------------------------------------------------------------------------------
269