diff --git a/sql/v01/10.create.sql b/sql/v01/10.create.sql index 2286c4f..1319e60 100644 --- a/sql/v01/10.create.sql +++ b/sql/v01/10.create.sql @@ -347,11 +347,18 @@ CREATE TABLE member_billing_address ( ON DELETE RESTRICT ) STRICT; -CREATE TABLE contract ( - vnr INTEGER NOT NULL, +CREATE TABLE area_commitment ( + fbnr INTEGER NOT NULL, mgnr INTEGER NOT NULL, - date TEXT CHECK (date REGEXP '^[1-9][0-9]{3}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$') DEFAULT CURRENT_DATE, + sortid TEXT NOT NULL, + cultid TEXT NOT NULL, + area INTEGER NOT NULL, + + kgnr INTEGER NOT NULL, + gstnr TEXT NOT NULL, + rdnr INTEGER, + year_from INTEGER CHECK (year_from >= 1000 AND year_from <= 9999) DEFAULT NULL, year_to INTEGER CHECK (year_to >= 1000 AND year_to <= 9999) DEFAULT NULL, @@ -359,43 +366,16 @@ CREATE TABLE contract ( ctime INTEGER NOT NULL DEFAULT (UNIXEPOCH()), mtime INTEGER NOT NULL DEFAULT (UNIXEPOCH()), - CONSTRAINT pk_contract PRIMARY KEY (vnr), - CONSTRAINT fk_contract_member FOREIGN KEY (mgnr) REFERENCES member (mgnr) + CONSTRAINT pk_are_commitment PRIMARY KEY (fbnr), + CONSTRAINT fk_are_commitment_member FOREIGN KEY (mgnr) REFERENCES member (mgnr) ON UPDATE CASCADE - ON DELETE RESTRICT -) STRICT; - -CREATE TABLE area_commitment ( - vnr INTEGER NOT NULL, - sortid TEXT NOT NULL, - cultid TEXT NOT NULL, - - area INTEGER NOT NULL, - - CONSTRAINT pk_area_commitment PRIMARY KEY (vnr), - CONSTRAINT fk_area_commitment_contract FOREIGN KEY (vnr) REFERENCES contract (vnr) - ON UPDATE CASCADE - ON DELETE CASCADE, + ON DELETE RESTRICT, CONSTRAINT fk_area_commitment_wine_variety FOREIGN KEY (sortid) REFERENCES wine_variety (sortid) ON UPDATE CASCADE ON DELETE RESTRICT, CONSTRAINT fk_area_commitment_wine_cultivation FOREIGN KEY (cultid) REFERENCES wine_cultivation (cultid) ON UPDATE CASCADE - ON DELETE RESTRICT -) STRICT; - -CREATE TABLE area_commitment_parcel ( - vnr INTEGER NOT NULL, - kgnr INTEGER NOT NULL, - gstnr TEXT NOT NULL CHECK (gstnr REGEXP '^\.?[1-9][0-9]*(/[1-9][0-9]*)*$'), - - rdnr INTEGER, - area INTEGER, - - CONSTRAINT pk_area_commitment_parcel PRIMARY KEY (vnr, kgnr, gstnr), - CONSTRAINT fk_area_commitment_parcel_area_commitment FOREIGN KEY (vnr) REFERENCES area_commitment (vnr) - ON UPDATE CASCADE - ON DELETE CASCADE, + ON DELETE RESTRICT, CONSTRAINT fk_area_commitment_wb_kg FOREIGN KEY (kgnr) REFERENCES wb_kg (kgnr) ON UPDATE CASCADE ON DELETE RESTRICT, @@ -405,11 +385,11 @@ CREATE TABLE area_commitment_parcel ( ) STRICT; CREATE TABLE area_commitment_attribute ( - vnr INTEGER NOT NULL, + fbnr INTEGER NOT NULL, attrid TEXT NOT NULL, - CONSTRAINT pk_area_commitment_attribute PRIMARY KEY (vnr, attrid), - CONSTRAINT fk_area_commitment_attribute_area_commitment FOREIGN KEY (vnr) REFERENCES area_commitment (vnr) + CONSTRAINT pk_area_commitment_attribute PRIMARY KEY (fbnr, attrid), + CONSTRAINT fk_area_commitment_attribute_area_commitment FOREIGN KEY (fbnr) REFERENCES area_commitment (fbnr) ON UPDATE CASCADE ON DELETE CASCADE, CONSTRAINT fk_area_commitment_attribute_wine_attribute FOREIGN KEY (attrid) REFERENCES wine_attribute (attrid) diff --git a/sql/v01/11.timestamp-trigger.sql b/sql/v01/11.timestamp-trigger.sql index 0216f35..0b73b75 100644 --- a/sql/v01/11.timestamp-trigger.sql +++ b/sql/v01/11.timestamp-trigger.sql @@ -49,92 +49,52 @@ END; ---------------------------------------------------------------- -CREATE TRIGGER t_contract_i_ctime - AFTER INSERT ON contract FOR EACH ROW +CREATE TRIGGER t_area_commitment_i_ctime + AFTER INSERT ON area_commitment FOR EACH ROW WHEN NEW.ctime != UNIXEPOCH() BEGIN - UPDATE contract SET ctime = UNIXEPOCH() WHERE vnr = NEW.vnr; + UPDATE area_commitment SET ctime = UNIXEPOCH() WHERE fbnr = NEW.fbnr; END; -CREATE TRIGGER t_contract_u_ctime - BEFORE UPDATE ON contract FOR EACH ROW +CREATE TRIGGER t_area_commitment_u_ctime + BEFORE UPDATE ON area_commitment FOR EACH ROW WHEN OLD.ctime != NEW.ctime BEGIN SELECT RAISE(ABORT, 'It is not allowed to change ctime'); END; -CREATE TRIGGER t_contract_i_mtime - AFTER INSERT ON contract FOR EACH ROW - WHEN NEW.mtime != UNIXEPOCH() -BEGIN - UPDATE contract SET mtime = UNIXEPOCH() WHERE vnr = NEW.vnr; -END; - -CREATE TRIGGER t_contract_u_mtime - AFTER UPDATE ON contract FOR EACH ROW - WHEN NEW.mtime != UNIXEPOCH() -BEGIN - UPDATE contract SET mtime = UNIXEPOCH() WHERE vnr = NEW.vnr; -END; - ----------------------------------------------------------------- - -CREATE TRIGGER t_area_commitment_i_mtime_contract +CREATE TRIGGER t_area_commitment_i_mtime AFTER INSERT ON area_commitment FOR EACH ROW + WHEN NEW.mtime != UNIXEPOCH() BEGIN - UPDATE contract SET mtime = UNIXEPOCH() WHERE vnr = NEW.vnr; + UPDATE area_commitment SET mtime = UNIXEPOCH() WHERE fbnr = NEW.fbnr; END; -CREATE TRIGGER t_area_commitment_u_mtime_contract +CREATE TRIGGER t_area_commitment_u_mtime AFTER UPDATE ON area_commitment FOR EACH ROW + WHEN NEW.mtime != UNIXEPOCH() BEGIN - UPDATE contract SET mtime = UNIXEPOCH() WHERE vnr = OLD.vnr OR vnr = NEW.vnr; -END; - -CREATE TRIGGER t_area_commitment_d_mtime_contract - AFTER DELETE ON area_commitment FOR EACH ROW -BEGIN - UPDATE contract SET mtime = UNIXEPOCH() WHERE vnr = OLD.vnr; + UPDATE area_commitment SET mtime = UNIXEPOCH() WHERE fbnr = NEW.fbnr; END; ---------------------------------------------------------------- -CREATE TRIGGER t_area_commitment_parcel_i_mtime_contract - AFTER INSERT ON area_commitment_parcel FOR EACH ROW -BEGIN - UPDATE contract SET mtime = UNIXEPOCH() WHERE vnr = NEW.vnr; -END; - -CREATE TRIGGER t_area_commitment_parcel_u_mtime_contract - AFTER UPDATE ON area_commitment_parcel FOR EACH ROW -BEGIN - UPDATE contract SET mtime = UNIXEPOCH() WHERE vnr = OLD.vnr OR vnr = NEW.vnr; -END; - -CREATE TRIGGER t_area_commitment_parcel_d_mtime_contract - AFTER DELETE ON area_commitment_parcel FOR EACH ROW -BEGIN - UPDATE contract SET mtime = UNIXEPOCH() WHERE vnr = OLD.vnr; -END; - ----------------------------------------------------------------- - -CREATE TRIGGER t_area_commitment_attribute_i_mtime_contract +CREATE TRIGGER t_area_commitment_attribute_i_mtime_area_commitment AFTER INSERT ON area_commitment_attribute FOR EACH ROW BEGIN - UPDATE contract SET mtime = UNIXEPOCH() WHERE vnr = NEW.vnr; + UPDATE area_commitment SET mtime = UNIXEPOCH() WHERE fbnr = NEW.fbnr; END; -CREATE TRIGGER t_area_commitment_attribute_u_mtime_contract +CREATE TRIGGER t_area_commitment_attribute_u_mtime_area_commitment AFTER UPDATE ON area_commitment_attribute FOR EACH ROW BEGIN - UPDATE contract SET mtime = UNIXEPOCH() WHERE vnr = OLD.vnr OR vnr = NEW.vnr; + UPDATE area_commitment SET mtime = UNIXEPOCH() WHERE fbnr = OLD.fbnr OR fbnr = NEW.fbnr; END; -CREATE TRIGGER t_area_commitment_attribute_d_mtime_contract +CREATE TRIGGER t_area_commitment_attribute_d_mtime_area_commitment AFTER DELETE ON area_commitment_attribute FOR EACH ROW BEGIN - UPDATE contract SET mtime = UNIXEPOCH() WHERE vnr = OLD.vnr; + UPDATE area_commitment SET mtime = UNIXEPOCH() WHERE fbnr = OLD.fbnr; END; ---------------------------------------------------------------- diff --git a/wgmaster/import.py b/wgmaster/import.py index 068f057..149e9dc 100755 --- a/wgmaster/import.py +++ b/wgmaster/import.py @@ -14,8 +14,7 @@ import csv DIR: str TABLES = ['client_parameter', 'branch', 'wb_gl', 'wb_kg', 'wb_rd', 'wine_attribute', 'wine_cultivation', - 'member', 'member_billing_address', 'contract', - 'area_commitment', 'area_commitment_parcel', 'area_commitment_attribute', + 'member', 'member_billing_address', 'area_commitment', 'area_commitment_attribute', 'season', 'modifier', 'delivery', 'delivery_part', 'delivery_part_attribute', 'delivery_part_modifier', ] # 'payment_variant', 'delivery_payment', 'member_payment'] diff --git a/wgmaster/migrate.py b/wgmaster/migrate.py index 08457cc..db07d80 100755 --- a/wgmaster/migrate.py +++ b/wgmaster/migrate.py @@ -599,7 +599,7 @@ def migrate_members(in_dir: str, out_dir: str) -> None: f_mba.write(csv.format_row(mgnr, billing_name, 'AT', postal_dest, address or '-')) -def migrate_contracts(in_dir: str, out_dir: str) -> None: +def migrate_are_commitments(in_dir: str, out_dir: str) -> None: def parse_gstnrs(nr_str: str, kgnr: int, mgnr: int) -> List[str]: if nr_str is None: return [] @@ -614,7 +614,7 @@ def migrate_contracts(in_dir: str, out_dir: str) -> None: if nr_str.count('/') > 1: parts = nr_str.split('/') if all([p.isdigit() for p in parts]): - if all([len(p) <= 3 for p in parts[1:]]): + if all([len(p) <= 1 for p in parts[1:]]): return [f'{parts[0]}/{p}' for p in parts[1:]] elif all([len(p) == len(parts[0]) for p in parts]): return parts @@ -650,20 +650,58 @@ def migrate_contracts(in_dir: str, out_dir: str) -> None: invalid(mgnr, 'GstNr.', f'{kgnr:05}-{nr_str}') return [] - with open(f'{out_dir}/contract.csv', 'w+', encoding='utf-8') as f_c, \ - open(f'{out_dir}/area_commitment.csv', 'w+', encoding='utf-8') as f_fb, \ - open(f'{out_dir}/area_commitment_parcel.csv', 'w+', encoding='utf-8') as f_parc, \ + def replace_nrs(m: re.Match, sep: str) -> str: + end = m.group(0).endswith(sep) + parts = [int(p) for p in m.group(0).split(sep)] + text = '' + last = None + for i, p in enumerate(parts): + if last is not None: + if last + 1 == p: + last = p + continue + else: + text += f'{last}{sep}' + last = None + if len(parts) > i + 2 and p + 1 == parts[i + 1] and p + 2 == parts[i + 2]: + last = p + text += f'{p}-' + else: + text += f'{p}{sep}' + if last is not None: + text += str(last) + return text.strip().strip(sep) + (sep if end else '') + + def format_gstnr(nrs: List[str]) -> Optional[str]: + if len(nrs) == 0: + return None + nrs = [re.sub(r'\b0+', '', nr) + for nr in sorted([re.sub(r'[0-9]+', lambda m: m.group(0).rjust(6, '0'), nr) + for nr in nrs])] + last = None + text = '' + for nr in nrs: + if last is None: + text += nr + elif '/' in last and last.split('/')[:-1] == nr.split('/')[:-1]: + text += f'+{nr.split("/")[-1]}' + else: + text += f', {nr}' + last = nr + text = re.sub(r'[0-9]+\+[0-9]+(\+[0-9]+)+', lambda m: replace_nrs(m, '+'), text) + text = re.sub(r'([0-9]+(, |$)){3,}', lambda m: replace_nrs(m, ', '), text) + return text + + with open(f'{out_dir}/area_commitment.csv', 'w+', encoding='utf-8') as f_fb, \ open(f'{out_dir}/area_commitment_attribute.csv', 'w+', encoding='utf-8') as f_attr: - f_c.write('vnr;mgnr;date;year_from;year_to;comment\n') - f_fb.write('vnr;sortid;cultid;area\n') - f_parc.write('vnr;kgnr;gstnr;rdnr;area\n') - f_attr.write('vnr;attrid\n') + f_fb.write('fbnr;mgnr;sortid;cultid;area;kgnr;gstnr;rdnr;year_from;year_to;comment\n') + f_attr.write('fbnr;attrid\n') for fb in csv.parse_dict(f'{in_dir}/TFlaechenbindungen.csv'): if fb['Von'] is None and fb['Bis'] is None: continue parz: str = fb['Parzellennummer'] - vnr: int = fb['FBNR'] + fbnr: int = fb['FBNR'] mgnr: int = fb['MGNR'] gem = GEM_MAP[fb['GNR']] kgnr = gem[0][0] @@ -672,24 +710,25 @@ def migrate_contracts(in_dir: str, out_dir: str) -> None: area = int(fb['Flaeche']) gstnrs = parse_gstnrs(parz, kgnr, fb['MGNR']) - comment = None + comment, gstnr = None, None if parz is None or parz == '0000': invalid(mgnr, 'GstNr.', f'{kgnr or 0:05}-{parz}') gstnrs = [] + gstnr = '-' elif len(gstnrs) > 1 or (len(gstnrs) == 1 and gstnrs[0] != parz): convert(mgnr, 'GstNr.', f'{kgnr or 0:05}-{parz or ""}', ', '.join(gstnrs)) if len(gstnrs) == 0: - comment = f'KG {kgnr}: {parz}' + comment = f'KG {kgnr:05}: {parz}' + gstnr = format_gstnr(gstnrs) or gstnr or parz + if parz != gstnr: + print(f'{parz or "None":32} -> {gstnr}') + rdnr = REED_MAP[fb['RNR']][1] if fb['RNR'] else None to = fb['Bis'] if fb['Bis'] and fb['Bis'] < 3000 else None - f_c.write(csv.format_row(vnr, mgnr, None, fb['Von'], to, comment)) - - f_fb.write(csv.format_row(vnr, fb['SNR'], CULTIVATION_MAP[fb['BANR']], area)) + f_fb.write(csv.format_row(fbnr, mgnr, fb['SNR'], CULTIVATION_MAP[fb['BANR']], area, + kgnr, gstnr, rdnr, fb['Von'], to, comment)) if fb['SANR']: - f_attr.write(csv.format_row(vnr, fb['SANR'])) - for i, gstnr in enumerate(gstnrs): - rdnr = REED_MAP[fb['RNR']][1] if fb['RNR'] else None - f_parc.write(csv.format_row(vnr, kgnr, gstnr, rdnr, area if len(gstnrs) == 1 else None)) + f_attr.write(csv.format_row(fbnr, fb['SANR'])) def fix_deliveries(deliveries: Iterable[Dict[str, Any]]) -> Iterable[Tuple[str, List[int], datetime.date]]: @@ -979,7 +1018,7 @@ def main() -> None: migrate_attributes(args.in_dir, args.out_dir) migrate_cultivations(args.in_dir, args.out_dir) migrate_members(args.in_dir, args.out_dir) - migrate_contracts(args.in_dir, args.out_dir) + migrate_are_commitments(args.in_dir, args.out_dir) migrate_deliveries(args.in_dir, args.out_dir) migrate_payments(args.in_dir, args.out_dir) migrate_parameters(args.in_dir, args.out_dir)