#!/usr/bin/env python3 """Hocks Mieterportal – Beispieldaten-Generator. Erzeugt deterministisch die Demo-Daten des Portals und schreibt sie nach ``src/data/generated.json`` (Units + Transaktionen). Die handschriftlichen Inhalte (Tickets, Dokumente, Nachrichten, Ankündigungen) liegen weiterhin in ``src/data/seed.ts``. Aufruf: python beispieldaten.py (Standard-Seed 20261002) python beispieldaten.py 42 (eigener Seed zum Experimentieren) Achtung: Der Demo-Mieter „Anna Berger" (Whg. Hauptstraße 12 Nr. 7) und die Algorithmen sind synchron zu src/data/seed.ts zu halten. """ import json import sys from pathlib import Path SEED = int(sys.argv[1]) if len(sys.argv) > 1 else 20261002 BUILDINGS = [ {"name": "Hauptstraße 12", "prefix": "HS", "count": 20, "baseRent": 9.8}, {"name": "Ringweg 3", "prefix": "RW", "count": 15, "baseRent": 8.9}, {"name": "Am Park 5", "prefix": "AP", "count": 15, "baseRent": 10.4}, ] FIRST_NAMES = [ "Anna", "Jonas", "Marta", "Leon", "Sofia", "Felix", "Lena", "Paul", "Emma", "Noah", "Clara", "Ben", "Nora", "Max", "Julia", "Tim", "Sarah", "Finn", "Laura", "Jan", "Mia", "Tom", "Ela", "Kim", ] LAST_NAMES = [ "Berger", "Klein", "Wolf", "Neumann", "Schäfer", "Krüger", "Brandt", "Vogel", "Otto", "Horn", "Busch", "Thomas", "Pohl", "Sander", "Lindner", ] DEMO_TENANT = "Anna Berger" DEMO_UNIT_ID = "hs-7" MONTHS = [ "Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember", ] def gen_units() -> list[dict]: units: list[dict] = [] name_idx = 0 def next_name() -> str: nonlocal name_idx n = f"{FIRST_NAMES[name_idx % len(FIRST_NAMES)]} {LAST_NAMES[name_idx % len(LAST_NAMES)]}" name_idx += 1 return n for b in BUILDINGS: for i in range(b["count"]): num = i + 1 size = 38 + ((num * 7 + len(b["prefix"]) * 3) % 78) # 38–115 m² cold = round(size * b["baseRent"]) warm = cold + round(2.4 * size) + (35 if num % 3 == 0 else 0) floor = 0 if num <= 2 else min(4, (num - 1) // 4) occupied = num % 9 != 0 # ~89 % Vermietung if b["prefix"] == "HS" and num == 7: tenant: str | None = DEMO_TENANT elif occupied: tenant = next_name() else: tenant = None units.append({ "id": f"{b['prefix'].lower()}-{num}", "building": b["name"], "number": str(num), "floor": floor, "size": size, "coldRent": cold, "warmRent": warm, "tenant": tenant, "status": "vermietet" if occupied else "frei", }) return units def gen_transactions(units: list[dict]) -> list[dict]: txs: list[dict] = [] for u in units: if u["status"] != "vermietet": continue for m in range(12): due = m + 1 if due <= 9: status = "überfällig" if (ord(u["id"][3]) + m) % 11 == 0 else "bezahlt" else: status = "offen" txs.append({ "id": f"tx-{u['id']}-{m}", "unitId": u["id"], "tenant": u["tenant"], "month": MONTHS[m], "year": 2026, "amount": u["warmRent"], "type": "Miete", "status": status, **({"paidAt": f"0{(m % 8) + 1}.0{due}.2026"} if status == "bezahlt" else {}), }) return txs def main() -> None: units = gen_units() data = { "meta": {"seed": SEED, "units": len(units), "rented": sum(1 for u in units if u["status"] == "vermietet")}, "units": units, "transactions": gen_transactions(units), } out = Path(__file__).parent / "src" / "data" / "generated.json" out.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8") print(f"{out} geschrieben: {data['meta']['units']} Wohnungen " f"({data['meta']['rented']} vermietet), {len(data['transactions'])} Buchungen") if __name__ == "__main__": main()