FastAPI + PostgreSQL 16. KYC, issue sistemi, permission/group yönetimi, session yönetimi, API client auth (kışla kapısı), officials/persons CRUD. Migration 0001–0013 dahil.
101 lines
3.6 KiB
Python
101 lines
3.6 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
Eski CI4 backup'ından il ve ilçeleri yeni locations tablosuna aktarır.
|
||
"""
|
||
|
||
import os
|
||
import re
|
||
import unicodedata
|
||
import psycopg
|
||
from pathlib import Path
|
||
from dotenv import load_dotenv
|
||
|
||
load_dotenv(Path(__file__).parent.parent / ".env")
|
||
load_dotenv(Path(__file__).parent / ".env", override=False)
|
||
|
||
DSN = os.environ["DATABASE_URL"]
|
||
_here = Path(__file__).parent
|
||
BACKUP = next(
|
||
p for p in [
|
||
_here.parent.parent / "locations_backup.sql", # normal: new/../locations_backup.sql
|
||
_here.parent / "locations_backup.sql", # sunucu geçici
|
||
_here / "locations_backup.sql", # aynı dizin
|
||
]
|
||
if p.exists()
|
||
)
|
||
|
||
|
||
def slugify(text: str) -> str:
|
||
text = text.lower()
|
||
text = text.replace("ı", "i").replace("ğ", "g").replace("ü", "u")
|
||
text = text.replace("ş", "s").replace("ö", "o").replace("ç", "c")
|
||
text = unicodedata.normalize("NFD", text)
|
||
text = "".join(c for c in text if unicodedata.category(c) != "Mn")
|
||
text = re.sub(r"[^a-z0-9]+", "-", text).strip("-")
|
||
return text
|
||
|
||
|
||
def parse_inserts(sql: str, table: str):
|
||
pattern = rf"INSERT INTO public\.{table} VALUES \((.+?)\);"
|
||
rows = []
|
||
for m in re.finditer(pattern, sql):
|
||
parts = [p.strip().strip("'") for p in m.group(1).split(", ", 2)]
|
||
rows.append(parts)
|
||
return rows
|
||
|
||
|
||
def run():
|
||
sql = BACKUP.read_text(encoding="utf-8")
|
||
provinces = parse_inserts(sql, "locations_province") # (id, name, plate_no)
|
||
districts = parse_inserts(sql, "locations_district") # (id, name, province_id)
|
||
|
||
with psycopg.connect(DSN) as conn:
|
||
existing = conn.execute("SELECT COUNT(*) FROM locations").fetchone()[0]
|
||
if existing > 0:
|
||
print(f"locations tablosunda zaten {existing} kayıt var, atlanıyor.")
|
||
return
|
||
|
||
# Türkiye kök kaydı
|
||
tr_id = conn.execute(
|
||
"INSERT INTO locations (name, slug, type) VALUES (%s, %s, %s) RETURNING id",
|
||
("Türkiye", "turkiye", "ulke")
|
||
).fetchone()[0]
|
||
|
||
# İller — eski id → yeni id eşlemesi
|
||
province_id_map = {}
|
||
for old_id, name, _ in provinces:
|
||
slug = slugify(name)
|
||
new_id = conn.execute(
|
||
"INSERT INTO locations (parent_id, name, slug, type) VALUES (%s, %s, %s, %s) RETURNING id",
|
||
(tr_id, name, slug, "il")
|
||
).fetchone()[0]
|
||
province_id_map[old_id] = new_id
|
||
|
||
# İlçeler — slug = il_slug-ilce_slug (teklik garantisi)
|
||
province_slug_map = {old_id: slugify(name) for old_id, name, _ in provinces}
|
||
used_slugs = set()
|
||
for _, name, province_old_id in districts:
|
||
parent_id = province_id_map.get(province_old_id)
|
||
if not parent_id:
|
||
print(f" ⚠ İlçe '{name}' için province_id={province_old_id} bulunamadı, atlandı.")
|
||
continue
|
||
il_slug = province_slug_map.get(province_old_id, province_old_id)
|
||
base_slug = f"{il_slug}-{slugify(name)}"
|
||
slug = base_slug
|
||
counter = 1
|
||
while slug in used_slugs:
|
||
counter += 1
|
||
slug = f"{base_slug}-{counter}"
|
||
used_slugs.add(slug)
|
||
conn.execute(
|
||
"INSERT INTO locations (parent_id, name, slug, type) VALUES (%s, %s, %s, %s)",
|
||
(parent_id, name, slug, "ilce")
|
||
)
|
||
|
||
conn.commit()
|
||
total = conn.execute("SELECT COUNT(*) FROM locations").fetchone()[0]
|
||
print(f"Tamamlandı: {total} lokasyon eklendi (1 ülke, {len(provinces)} il, {len(districts)} ilçe).")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
run()
|