diff --git a/sql/sample.sql b/sql/sample.sql index 980b8b6..a4a0644 100644 --- a/sql/sample.sql +++ b/sql/sample.sql @@ -135,12 +135,13 @@ SELECT k.kgnr, 2 FROM wb_gem wg LEFT JOIN AT_gem g ON g.gkz = wg.gkz LEFT JOIN AT_kg k ON k.gkz = g.gkz -WHERE hkid = 'WLWV' AND g.gkz / 100 IN (308, 316) AND k.name IN ('Bockfließ', 'Großengersdorf', 'Wolkersdorf'); +WHERE hkid = 'WLWV' AND g.gkz / 100 IN (308, 316) AND k.name IN + ('Bockfließ', 'Großengersdorf', 'Wolkersdorf', 'Pillichsdorf'); INSERT INTO wb_kg SELECT k.kgnr, 3 FROM wb_gem wg LEFT JOIN AT_gem g ON g.gkz = wg.gkz LEFT JOIN AT_kg k ON k.gkz = g.gkz -WHERE hkid = 'WLWV' AND g.gkz / 100 IN (308, 316) AND - k.name IN ('Erdpreß', 'Martinsdorf', 'Niedersulz', 'Großinzersdorf', 'Palterndorf'); +WHERE hkid = 'WLWV' AND g.gkz / 100 IN (308, 316) AND k.name IN + ('Erdpreß', 'Martinsdorf', 'Niedersulz', 'Obersulz', 'Großinzersdorf', 'Palterndorf', 'Gaweinstal', 'Zistersdorf'); diff --git a/sql/v01/01.create.sql b/sql/v01/01.create.sql index c89a2e6..50d9943 100644 --- a/sql/v01/01.create.sql +++ b/sql/v01/01.create.sql @@ -250,12 +250,12 @@ CREATE TABLE member ( suffix TEXT DEFAULT NULL, birthday TEXT CHECK (birthday REGEXP '^[1-9][0-9]{3}(-(0[1-9]|1[012])(-(0[1-9]|[12][0-9]|3[01]))?)?$') DEFAULT NULL, - entry_date TEXT NOT NULL CHECK (entry_date REGEXP '^[1-9][0-9]{3}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$') DEFAULT CURRENT_DATE, + entry_date TEXT CHECK (entry_date REGEXP '^[1-9][0-9]{3}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$') DEFAULT CURRENT_DATE, exit_date TEXT CHECK (exit_date REGEXP '^[1-9][0-9]{3}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$') DEFAULT NULL, business_shares INTEGER NOT NULL DEFAULT 0, accounting_nr TEXT DEFAULT NULL, - zwstid TEXT NOT NULL, + zwstid TEXT CHECK (NOT active OR zwstid IS NOT NULL), lfbis_nr TEXT CHECK (lfbis_nr REGEXP '^[0-9]{7}$') DEFAULT NULL, ustid TEXT CHECK (ustid REGEXP '^[A-Z]{2}[A-Z0-9]{2,12}$') DEFAULT NULL, @@ -276,7 +276,7 @@ CREATE TABLE member ( phone_mobile_1 TEXT CHECK (phone_mobile_1 REGEXP '^\+[0-9]+$') DEFAULT NULL, phone_mobile_2 TEXT CHECK (phone_mobile_2 REGEXP '^\+[0-9]+$') DEFAULT NULL, - default_kgnr INTEGER NOT NULL, + default_kgnr INTEGER CHECK (NOT active OR default_kgnr IS NOT NULL), comment TEXT DEFAULT NULL, CONSTRAINT pk_member PRIMARY KEY (mgnr), diff --git a/wgmaster/migrate.py b/wgmaster/migrate.py index ac4c4b5..7e1b38a 100755 --- a/wgmaster/migrate.py +++ b/wgmaster/migrate.py @@ -1,11 +1,15 @@ #!/bin/env python3 -from typing import Dict, Any, Tuple, Optional, Iterator +from typing import Dict, Any, Tuple, Optional, Iterator, List import argparse import datetime import os import re import sys +import sqlite3 + + +DB_CNX: Optional[sqlite3.Connection] = None USTID_RE = re.compile('[A-Z]{2}[A-Z0-9]{2,12}') @@ -177,6 +181,52 @@ def parse_branches(in_dir: str) -> Dict[str, Any]: return {b['ZNR']: b for b in parse_csv(f'{in_dir}/TZweigstellen.csv')} +def lookup_plz(plz: Optional[int], ort: Optional[str], address: Optional[str] = None) -> Optional[int]: + if plz is None or ort is None: + return None + + cur = DB_CNX.cursor() + cur.execute("SELECT o.okz, p.dest, o.name FROM AT_plz p JOIN AT_ort o ON o.okz = p.okz WHERE plz = ?", (plz,)) + rows: List[Tuple[int, str, str]] = cur.fetchall() + cur.close() + + ort_m = ort.lower().replace('gr.', 'groß').replace(' ', '').replace('-', '').replace('ß', 'ss') + rows_m = [r[0] for r in rows if ort_m in r[2].lower().replace(' ', '').replace('-', '').replace('ß', 'ss')] + if len(rows_m) == 1: + return plz * 100000 + rows_m[0] + + parts = address.split(' ') + street = parts[:-1] + nr = int(parts[-1].split('-')[0]) + + if ort == 'VELM-GÖTZENDORF': + if street == 'Landstraße' and nr <= 48 \ + or street == 'Winterzeile' and (nr <= 49 or nr in (52, 54, 56)) \ + or street == 'Hauptstraße' and (nr <= 106 or nr in (117, 115, 113, 111, 109, 107)): + # Velm + return plz * 100000 + 3572 + else: + # Götzendorf + return plz * 100000 + 3571 + + print(ort, address) + raise RuntimeError() + + +def lookup_kgnr(okz: Optional[int]) -> Optional[int]: + if okz is None: + return None + + cur = DB_CNX.cursor() + cur.execute("SELECT k.kgnr FROM AT_ort o JOIN wb_kg k ON k.kgnr = o.kgnr WHERE okz = ?", (okz,)) + rows: List[Tuple[int]] = cur.fetchall() + cur.close() + + if len(rows) == 1: + return rows[0][0] + return None + + def migrate_members(in_dir: str, out_dir: str) -> None: members = parse_csv(f'{in_dir}/TMitglieder.csv') branches = parse_branches(in_dir) @@ -369,15 +419,21 @@ def migrate_members(in_dir: str, out_dir: str) -> None: invalid(mgnr, 'Tel.Nr.', phone_2) zwstid = m['ZNR'] and branches[m['ZNR']]['Kennbst'] or len(branches) == 1 and list(branches.values())[0]['Kennbst'] + postal_dest = lookup_plz(int(m['PLZ']) if m['PLZ'] else None, m['Ort'], address) + + okz = postal_dest % 100000 if postal_dest else None + kgnr = lookup_kgnr(okz) + if kgnr is None: + invalid(mgnr, 'KgNr', ort) f_m.write(format_row( mgnr, m['MGNR-Vorgänger'], prefix, given_name, middle_names, family_name, suffix, - m['Geburtsjahr'], m['Eintrittsdatum'], m['Austrittsdatum'], m['Geschäftsanteile1'], + m['Geburtsjahr'], m['Eintrittsdatum'], m['Austrittsdatum'], m['Geschäftsanteile1'] or 0, m['BHKontonummer'], zwstid, bnr, ustid, m['Volllieferant'] or False, m['Buchführend'] or False, False, m['Aktives Mitglied'] or False, - iban, bic, 'AT', None, address, email, phone_landline, + iban, bic, 'AT', postal_dest, address, email, phone_landline, phone_mobile[0] if len(phone_mobile) > 0 else None, phone_mobile[1] if len(phone_mobile) > 1 else None, - None, m['Anmerkung'] + kgnr, m['Anmerkung'] )) if billing_name: f_mba.write(format_row(mgnr, billing_name, 'AT', None, None)) @@ -387,8 +443,13 @@ if __name__ == '__main__': parser.add_argument('in_dir') parser.add_argument('out_dir') parser.add_argument('-q', '--quiet', action='store_true', default=False) + parser.add_argument('-d', '--database', required=True) args = parser.parse_args() os.makedirs(args.out_dir, exist_ok=True) + DB_CNX = sqlite3.connect(args.database) + migrate_members(args.in_dir, args.out_dir) + + DB_CNX.close()