Download pilot/belge_uret.py from SevdanurGenc/Text-to-SQL: direct link, hf CLI and curl.
- Browser
- Download file 33.2 kB
-
https://huggingface.co/SevdanurGenc/Text-to-SQL/resolve/main/pilot/belge_uret.py
- Command line
-
hf download hf://SevdanurGenc/Text-to-SQL/pilot/belge_uret.py
-
curl -L -o belge_uret.py https://huggingface.co/SevdanurGenc/Text-to-SQL/resolve/main/pilot/belge_uret.py
33.2 kB
| """Pilot çalışması için gerçek belge düzenlerini taklit eden KURGUSAL belgeler, sorular ve altın cevaplar üretir. | |
| Amaç: gerçek belgeler bulunana kadar sistemi, geliştirme sırasında hiç görmediği düzenlerde sınamak. | |
| Belgeler ana test kümesinden (data/docs) bilerek farklı tasarlanmıştır: | |
| * çok sayfaya bölünen ve başlığı her sayfada tekrar eden tablo | |
| * yalnızca yatay çizgili (dikey çizgisiz) KAP tarzı finansal tablolar, dipnot sütunu, girintili kalemler, | |
| ara toplam satırları, parantezli negatifler, 4 ondalıklı pay başına kazanç | |
| * birimi yalnızca sütun başlığında "(%)" olan yüzde sütunları, "-" ile gösterilen tanımsız değerler | |
| * dipnot işaretli satır adları ("Şirket Personeli (*)") ve tablo altı açıklama satırları | |
| * HTML'de <tfoot> içinde kaynak notu, çeyrek (Ç1–Ç4) başlıkları, "Ocak 2025" biçimli ay satırları | |
| Altın cevaplar soruların metninden değil, belgeyi üreten ham verilerden programla hesaplanır. | |
| Bütün kurum, il ve ilçe adları kurgusaldır; her sayfada "KURGUSAL ÖRNEK BELGE" uyarısı bulunur. | |
| Kullanım: python pilot/belge_uret.py -> pilot/belgeler/*, pilot/sorular.json | |
| """ | |
| from __future__ import annotations | |
| import json | |
| import random | |
| from pathlib import Path | |
| from reportlab.lib import colors | |
| from reportlab.lib.enums import TA_CENTER | |
| from reportlab.lib.pagesizes import A4 | |
| from reportlab.lib.styles import ParagraphStyle | |
| from reportlab.lib.units import cm | |
| from reportlab.pdfbase import pdfmetrics | |
| from reportlab.pdfbase.ttfonts import TTFont | |
| from reportlab.platypus import Paragraph, SimpleDocTemplate, Spacer, Table, TableStyle, PageBreak | |
| ROOT = Path(__file__).resolve().parent.parent | |
| OUT = ROOT / "pilot" / "belgeler" | |
| FONTS = ROOT / "assets" / "fonts" | |
| pdfmetrics.registerFont(TTFont("DejaVu", str(FONTS / "DejaVuSans.ttf"))) | |
| pdfmetrics.registerFont(TTFont("DejaVu-Bold", str(FONTS / "DejaVuSans-Bold.ttf"))) | |
| rng = random.Random(31) | |
| UYARI = "KURGUSAL ÖRNEK BELGE — Tablo2SQL-TR pilot çalışması için üretilmiştir; gerçek kurum verisi değildir." | |
| # ------------------------------------------------------------------ biçimlendirme | |
| def tr(x, dec=2): | |
| s = f"{abs(x):,.{dec}f}".replace(",", "§").replace(".", ",").replace("§", ".") | |
| return ("-" if x < 0 else "") + s | |
| def paren(x, dec=0): | |
| return f"({tr(abs(x), dec)})" if x < 0 else tr(x, dec) | |
| ST = { | |
| "h1": ParagraphStyle("h1", fontName="DejaVu-Bold", fontSize=15, leading=19, spaceAfter=10, alignment=TA_CENTER), | |
| "h2": ParagraphStyle("h2", fontName="DejaVu-Bold", fontSize=11.5, leading=15, spaceBefore=10, spaceAfter=6), | |
| "p": ParagraphStyle("p", fontName="DejaVu", fontSize=9.5, leading=13.5, spaceAfter=6), | |
| "cap": ParagraphStyle("cap", fontName="DejaVu-Bold", fontSize=9.5, leading=12, spaceBefore=8, spaceAfter=4), | |
| "note": ParagraphStyle("note", fontName="DejaVu", fontSize=7.8, leading=10, spaceAfter=8), | |
| "cell": ParagraphStyle("cell", fontName="DejaVu", fontSize=8, leading=9.6), | |
| "cellb": ParagraphStyle("cellb", fontName="DejaVu-Bold", fontSize=8, leading=9.6), | |
| } | |
| def footer(canvas, doc): | |
| canvas.saveState() | |
| canvas.setFont("DejaVu", 7) | |
| canvas.setFillColor(colors.HexColor("#9a3412")) | |
| canvas.drawCentredString(A4[0] / 2, 1.1 * cm, UYARI) | |
| canvas.setFillColor(colors.grey) | |
| canvas.drawRightString(A4[0] - 2 * cm, 1.1 * cm, str(doc.page)) | |
| canvas.restoreState() | |
| def P(t, s="p"): | |
| return Paragraph(t, ST[s]) | |
| # ================================================================== D1: belediye faaliyet raporu | |
| KOD = [("01", "Personel Giderleri"), ("02", "Sosyal Güvenlik Kurumlarına Devlet Primi Giderleri"), | |
| ("03", "Mal ve Hizmet Alım Giderleri"), ("04", "Faiz Giderleri"), ("05", "Cari Transferler"), | |
| ("06", "Sermaye Giderleri"), ("07", "Sermaye Transferleri"), ("08", "Borç Verme"), | |
| ("09", "Yedek Ödenekler")] | |
| MAHALLE = ["Cumhuriyet", "Atatürk", "Yenidoğan", "Fatih", "Yavuz Selim", "Kurtuluş", "İstiklal", "Bahçelievler", | |
| "Gazi Osman Paşa", "Hürriyet", "Barbaros", "Mimar Sinan", "Yunus Emre", "Mevlana", "Karşıyaka", | |
| "Çamlıbel", "Esentepe", "Güzeltepe", "İnönü", "Kazım Karabekir", "Sakarya", "Turgut Özal", "Zafer", | |
| "Ilıca", "Örnekköy", "Şirinevler", "Çiftlik", "Değirmenönü", "Gülbahçe", "Akarca", "Yeşilyurt", | |
| "Pınarönü", "Selçuklu", "Ulubatlı", "Kocatepe", "Hacı Bayram", "Kemalpaşa", "Fevzi Çakmak", "Malazgirt", | |
| "Dumlupınar", "Sütçü İmam", "Namık Kemal", "Ziya Gökalp", "Mehmet Akif", "Akşemsettin", "Emek", "Gençlik", | |
| "Bağlarbaşı", "Yıldırım Beyazıt", "Osmangazi", "Orhangazi", "Alparslan", "Kayabaşı", "Çınarlı", "Söğütlü", | |
| "Kavaklı", "Ihlamur", "Nergis", "Lale", "Menekşe", "Papatya", "Sümbül", "Işıklar"] | |
| def d1_data(): | |
| b = {} | |
| for kod, ad in KOD: | |
| if kod == "09": | |
| butce = 18_500_000.00 | |
| b[kod] = dict(ad=ad, butce=butce, ekl=0.0, dus=butce, top=0.0, gerc=0.0, oran=None) | |
| continue | |
| butce = round(rng.uniform(4e6, 160e6), -3) + rng.choice([0, 0.5, 0.25]) | |
| if kod == "08": | |
| butce = round(rng.uniform(1e6, 3e6), -3) | |
| ekl = round(butce * rng.uniform(0, 0.12), 2) if kod not in ("08",) else 0.0 | |
| dus = round(butce * rng.uniform(0, 0.06), 2) | |
| top = round(butce + ekl - dus, 2) | |
| oran_r = {"01": 0.97, "02": 0.95, "06": 0.58, "08": 0.41}.get(kod, rng.uniform(0.70, 0.93)) | |
| gerc = round(top * oran_r, 2) | |
| b[kod] = dict(ad=ad, butce=butce, ekl=ekl, dus=dus, top=top, gerc=gerc, oran=round(100 * gerc / top, 2)) | |
| tot = {k: round(sum(v[k] for v in b.values()), 2) for k in ("butce", "ekl", "dus", "top", "gerc")} | |
| tot["oran"] = round(100 * tot["gerc"] / tot["top"], 2) | |
| pers = {"Memur": (142, 38), "Sözleşmeli Personel": (27, 9), "Kadrolu İşçi": (64, 21), "Geçici İşçi": (12, 0), | |
| "Şirket Personeli (*)": (318, None)} | |
| mah = {} | |
| for m in MAHALLE: | |
| n24 = rng.randint(1_800, 24_000) | |
| ch = rng.uniform(-0.035, 0.06) | |
| n25 = int(round(n24 * (1 + ch))) | |
| hane = int(round(n25 / rng.uniform(2.6, 3.6))) | |
| mah[m] = dict(n24=n24, n25=n25, hane=hane, deg=round(100 * (n25 - n24) / n24, 2)) | |
| return b, tot, pers, mah | |
| def d1_pdf(b, tot, pers, mah, path): | |
| doc = SimpleDocTemplate(str(path), pagesize=A4, leftMargin=1.8 * cm, rightMargin=1.8 * cm, topMargin=1.8 * cm, | |
| bottomMargin=2 * cm, title="Yeşilvadi Belediyesi 2025 Yılı Faaliyet Raporu") | |
| el = [P("T.C.<br/>YEŞİLVADİ BELEDİYESİ<br/>2025 YILI FAALİYET RAPORU", "h1"), | |
| P("Bu rapor, 5018 sayılı Kamu Mali Yönetimi ve Kontrol Kanunu'nun 41. maddesi ile Kamu İdarelerince Hazırlanacak " | |
| "Faaliyet Raporları Hakkında Yönetmelik uyarınca hazırlanmıştır. Raporda belediyenin 2025 mali yılına ait bütçe " | |
| "uygulama sonuçları, insan kaynakları ve mahalle bazında nüfus bilgileri yer almaktadır."), | |
| P("3. MALİ BİLGİLER", "h2"), | |
| P("3.1. Bütçe Uygulama Sonuçları", "h2"), | |
| P("2025 mali yılı bütçesi ile verilen ödenekler, yıl içinde yapılan aktarmalar sonucunda eklenen ve düşülen " | |
| "tutarlar ile birlikte aşağıda ekonomik sınıflandırmanın birinci düzeyine göre sunulmuştur."), | |
| P("Tablo 4: Bütçe Giderlerinin Ekonomik Sınıflandırmaya Göre Dağılımı (TL)", "cap")] | |
| H = lambda t: Paragraph(t, ParagraphStyle("bh", fontName="DejaVu-Bold", fontSize=6.4, leading=7.8)) # noqa: E731 | |
| hdr1 = [H("Ekonomik Kod"), H("Gider Türü"), H("Ödenek"), "", "", "", H("Gerçekleşme"), H("Gerçekleşme Oranı (%)")] | |
| hdr2 = ["", "", H("Bütçe Ödeneği"), H("Eklenen"), H("Düşülen"), H("Toplam Ödenek"), "", ""] | |
| rows = [hdr1, hdr2] | |
| for kod, _ in KOD: | |
| v = b[kod] | |
| rows.append([kod, P(v["ad"], "cell"), tr(v["butce"]), tr(v["ekl"]), tr(v["dus"]), tr(v["top"]), tr(v["gerc"]), | |
| "-" if v["oran"] is None else tr(v["oran"])]) | |
| rows.append(["", P("TOPLAM", "cellb"), tr(tot["butce"]), tr(tot["ekl"]), tr(tot["dus"]), tr(tot["top"]), | |
| tr(tot["gerc"]), tr(tot["oran"])]) | |
| t = Table(rows, colWidths=[1.9 * cm, 2.5 * cm, 2.15 * cm, 2.0 * cm, 2.0 * cm, 2.15 * cm, 2.3 * cm, 2.15 * cm], | |
| repeatRows=2) | |
| t.setStyle(TableStyle([ | |
| ("FONT", (0, 0), (-1, -1), "DejaVu", 6.2), ("FONT", (0, 0), (-1, 1), "DejaVu-Bold", 6.2), | |
| ("GRID", (0, 0), (-1, -1), 0.5, colors.black), ("SPAN", (2, 0), (5, 0)), ("SPAN", (0, 0), (0, 1)), | |
| ("SPAN", (1, 0), (1, 1)), ("SPAN", (6, 0), (6, 1)), ("SPAN", (7, 0), (7, 1)), | |
| ("BACKGROUND", (0, 0), (-1, 1), colors.HexColor("#e8eef6")), ("ALIGN", (2, 2), (-1, -1), "RIGHT"), | |
| ("VALIGN", (0, 0), (-1, -1), "MIDDLE"), ("ALIGN", (0, 0), (-1, 1), "CENTER"), | |
| ("FONT", (0, -1), (-1, -1), "DejaVu-Bold", 6.0)])) | |
| el += [t, P("Kaynak: Yeşilvadi Belediyesi Mali Hizmetler Müdürlüğü, 2025 yılı kesin hesap verileri.", "note")] | |
| el += [P("4. İNSAN KAYNAKLARI", "h2"), P("Tablo 5: Norm Kadro ve Personel Durumu (Kişi)", "cap")] | |
| rows = [["Personel Türü", "Dolu", "Boş", "Toplam"]] | |
| td = tb = 0 | |
| for k, (dolu, bos) in pers.items(): | |
| rows.append([k, tr(dolu, 0), "-" if bos is None else tr(bos, 0), tr(dolu + (bos or 0), 0)]) | |
| td += dolu | |
| tb += bos or 0 | |
| rows.append(["TOPLAM", tr(td, 0), tr(tb, 0), tr(td + tb, 0)]) | |
| t = Table(rows, colWidths=[6 * cm, 2.4 * cm, 2.4 * cm, 2.4 * cm]) | |
| t.setStyle(TableStyle([("FONT", (0, 0), (-1, -1), "DejaVu", 8.4), ("FONT", (0, 0), (-1, 0), "DejaVu-Bold", 8.4), | |
| ("FONT", (0, -1), (-1, -1), "DejaVu-Bold", 8.4), | |
| ("GRID", (0, 0), (-1, -1), 0.5, colors.black), ("ALIGN", (1, 0), (-1, -1), "RIGHT"), | |
| ("BACKGROUND", (0, 0), (-1, 0), colors.HexColor("#e8eef6"))])) | |
| el += [t, P("(*) 4734 sayılı Kamu İhale Kanunu kapsamında hizmet alımı yoluyla çalıştırılan personeli ifade eder; " | |
| "norm kadro kapsamında değildir.", "note")] | |
| el += [P("5. MAHALLE BİLGİLERİ", "h2"), | |
| P("Belediye sınırları içindeki mahallelerin Adrese Dayalı Nüfus Kayıt Sistemi (ADNKS) sonuçlarına göre nüfusları " | |
| "ve hane sayıları aşağıda verilmiştir."), | |
| P("Tablo 6: Mahallelere Göre Nüfus ve Hane Sayısı", "cap")] | |
| rows = [["Mahalle", "Nüfus (2024)", "Nüfus (2025)", "Hane Sayısı (2025)", "Değişim (%)"]] | |
| for m, v in mah.items(): | |
| rows.append([m, tr(v["n24"], 0), tr(v["n25"], 0), tr(v["hane"], 0), tr(v["deg"], 2)]) | |
| s24 = sum(v["n24"] for v in mah.values()) | |
| s25 = sum(v["n25"] for v in mah.values()) | |
| sh = sum(v["hane"] for v in mah.values()) | |
| rows.append(["Genel Toplam", tr(s24, 0), tr(s25, 0), tr(sh, 0), tr(round(100 * (s25 - s24) / s24, 2), 2)]) | |
| t = Table(rows, colWidths=[4.6 * cm, 2.8 * cm, 2.8 * cm, 3.6 * cm, 2.4 * cm], repeatRows=1) | |
| t.setStyle(TableStyle([("FONT", (0, 0), (-1, -1), "DejaVu", 8.2), ("FONT", (0, 0), (-1, 0), "DejaVu-Bold", 8.2), | |
| ("FONT", (0, -1), (-1, -1), "DejaVu-Bold", 8.2), | |
| ("GRID", (0, 0), (-1, -1), 0.5, colors.black), ("ALIGN", (1, 0), (-1, -1), "RIGHT"), | |
| ("BACKGROUND", (0, 0), (-1, 0), colors.HexColor("#e8eef6"))])) | |
| el += [t, P("Kaynak: TÜİK ADNKS verileri esas alınarak Belediye Planlama Müdürlüğünce derlenmiştir (kurgusal).", "note")] | |
| doc.build(el, onFirstPage=footer, onLaterPages=footer) | |
| # ================================================================== D2: KAP tarzı finansal tablolar | |
| def d2_data(): | |
| r = lambda a, b_: float(round(rng.uniform(a, b_), -3)) # noqa: E731 | |
| cur, prev = {}, {} | |
| for k, lo, hi in [("nakit", 40e6, 120e6), ("ticari_alacak", 150e6, 320e6), ("diger_alacak", 3e6, 12e6), | |
| ("stok", 180e6, 260e6), ("pesin", 4e6, 9e6), ("mdv", 600e6, 900e6), ("mod", 20e6, 45e6), | |
| ("ert_vergi", 5e6, 15e6), ("kv_borc", 120e6, 220e6), ("ticari_borc", 140e6, 250e6), | |
| ("uv_borc", 180e6, 300e6)]: | |
| cur[k] = r(lo, hi) | |
| prev[k] = float(round(cur[k] * rng.uniform(0.78, 1.12), -3)) | |
| prev["stok"] = float(round(cur["stok"] / 1.237, -3)) # stoklar ~%23,7 artış | |
| inc = {} | |
| for d, scale in ((cur, 1.0), (prev, 0.81)): | |
| h = float(round(2_450e6 * scale * rng.uniform(0.97, 1.03), -3)) | |
| smm = -float(round(h * rng.uniform(0.71, 0.75), -3)) | |
| gyg = -float(round(h * 0.041, -3)) | |
| pzg = -float(round(h * 0.063, -3)) | |
| dg = float(round(h * 0.012, -3)) | |
| dgid = -float(round(h * 0.007, -3)) | |
| bk = h + smm | |
| efk = bk + gyg + pzg + dg + dgid | |
| fin = -float(round(h * 0.052, -3)) | |
| vok = efk + fin | |
| vg = -float(round(vok * 0.25, -3)) | |
| dk = vok + vg | |
| inc[id(d)] = dict(hasilat=h, smm=smm, bk=bk, gyg=gyg, pzg=pzg, dg=dg, dgid=dgid, efk=efk, fin=fin, vok=vok, | |
| vg=vg, dk=dk, pbk=round(dk / 250e6, 4)) | |
| for d in (cur, prev): | |
| i = inc[id(d)] | |
| d.update(i) | |
| d["sermaye"] = 250e6 | |
| d["top_donen"] = d["nakit"] + d["ticari_alacak"] + d["diger_alacak"] + d["stok"] + d["pesin"] | |
| d["top_duran"] = d["mdv"] + d["mod"] + d["ert_vergi"] | |
| d["top_varlik"] = d["top_donen"] + d["top_duran"] | |
| d["top_kv"] = d["kv_borc"] + d["ticari_borc"] | |
| d["top_uv"] = d["uv_borc"] | |
| d["net_kar"] = d["dk"] | |
| d["gecmis"] = d["top_varlik"] - d["top_kv"] - d["top_uv"] - d["sermaye"] - d["net_kar"] | |
| d["top_oz"] = d["sermaye"] + d["gecmis"] + d["net_kar"] | |
| d["top_kaynak"] = d["top_kv"] + d["top_uv"] + d["top_oz"] | |
| return cur, prev | |
| BILANCO = [("VARLIKLAR", None, None, 0), ("Dönen Varlıklar", None, None, 0), | |
| ("Nakit ve Nakit Benzerleri", "5", "nakit", 1), ("Ticari Alacaklar", "7", "ticari_alacak", 1), | |
| ("Diğer Alacaklar", "8", "diger_alacak", 1), ("Stoklar", "9", "stok", 1), | |
| ("Peşin Ödenmiş Giderler", "10", "pesin", 1), ("TOPLAM DÖNEN VARLIKLAR", None, "top_donen", 0), | |
| ("Duran Varlıklar", None, None, 0), ("Maddi Duran Varlıklar", "11", "mdv", 1), | |
| ("Maddi Olmayan Duran Varlıklar", "12", "mod", 1), ("Ertelenmiş Vergi Varlığı", "24", "ert_vergi", 1), | |
| ("TOPLAM DURAN VARLIKLAR", None, "top_duran", 0), ("TOPLAM VARLIKLAR", None, "top_varlik", 0), | |
| ("KAYNAKLAR", None, None, 0), ("Kısa Vadeli Yükümlülükler", None, None, 0), | |
| ("Kısa Vadeli Borçlanmalar", "6", "kv_borc", 1), ("Ticari Borçlar", "7", "ticari_borc", 1), | |
| ("TOPLAM KISA VADELİ YÜKÜMLÜLÜKLER", None, "top_kv", 0), ("Uzun Vadeli Yükümlülükler", None, None, 0), | |
| ("Uzun Vadeli Borçlanmalar", "6", "uv_borc", 1), ("TOPLAM UZUN VADELİ YÜKÜMLÜLÜKLER", None, "top_uv", 0), | |
| ("Özkaynaklar", None, None, 0), ("Ödenmiş Sermaye", "16", "sermaye", 1), | |
| ("Geçmiş Yıllar Karları", None, "gecmis", 1), ("Net Dönem Karı", None, "net_kar", 1), | |
| ("TOPLAM ÖZKAYNAKLAR", None, "top_oz", 0), ("TOPLAM KAYNAKLAR", None, "top_kaynak", 0)] | |
| GELIR = [("Hasılat", "18", "hasilat"), ("Satışların Maliyeti (-)", "18", "smm"), ("BRÜT KAR", None, "bk"), | |
| ("Genel Yönetim Giderleri (-)", "19", "gyg"), ("Pazarlama Giderleri (-)", "19", "pzg"), | |
| ("Esas Faaliyetlerden Diğer Gelirler", "20", "dg"), ("Esas Faaliyetlerden Diğer Giderler (-)", "20", "dgid"), | |
| ("ESAS FAALİYET KARI", None, "efk"), ("Finansman Giderleri (-)", "21", "fin"), | |
| ("SÜRDÜRÜLEN FAALİYETLER VERGİ ÖNCESİ KARI", None, "vok"), ("Dönem Vergi Gideri (-)", "24", "vg"), | |
| ("DÖNEM KARI", None, "dk"), ("Pay Başına Kazanç (TL)", "25", "pbk")] | |
| def _fin_table(spec, cur, prev, with_indent=True, pbk_key="pbk"): | |
| H = lambda t: Paragraph(t, ParagraphStyle("fh", fontName="DejaVu-Bold", fontSize=7.2, leading=8.6, alignment=2)) # noqa: E731 | |
| hdr1 = ["", H("Dipnot"), H("Bağımsız Denetimden Geçmiş"), H("Bağımsız Denetimden Geçmiş")] | |
| hdr2 = ["", H("Referansları"), H("Cari Dönem"), H("Önceki Dönem")] | |
| hdr3 = ["", "", "31.12.2025", "31.12.2024"] | |
| rows = [hdr1, hdr2, hdr3] | |
| bold_rows = [] | |
| for item in spec: | |
| lab, dip, key = item[0], item[1], item[2] | |
| ind = item[3] if len(item) > 3 else (0 if lab.isupper() else 1) | |
| if key is None: | |
| rows.append([lab, "", "", ""]) | |
| elif key == pbk_key: | |
| rows.append([(" " * ind) + lab, dip or "", tr(cur[key], 4), tr(prev[key], 4)]) | |
| else: | |
| rows.append([(" " * ind) + lab, dip or "", paren(cur[key]), paren(prev[key])]) | |
| if lab.isupper() or key is None: | |
| bold_rows.append(len(rows) - 1) | |
| t = Table(rows, colWidths=[7.4 * cm, 2.0 * cm, 3.9 * cm, 3.9 * cm], repeatRows=3) | |
| style = [("FONT", (0, 0), (-1, -1), "DejaVu", 7.8), ("FONT", (0, 0), (-1, 2), "DejaVu-Bold", 7.4), | |
| ("ALIGN", (1, 0), (-1, -1), "RIGHT"), ("ALIGN", (1, 0), (1, -1), "CENTER"), | |
| ("LINEBELOW", (0, 2), (-1, 2), 0.8, colors.black), ("LINEABOVE", (0, 0), (-1, 0), 0.8, colors.black), | |
| ("TOPPADDING", (0, 0), (-1, -1), 1.6), ("BOTTOMPADDING", (0, 0), (-1, -1), 1.6)] | |
| for r in bold_rows: | |
| style.append(("FONT", (0, r), (-1, r), "DejaVu-Bold", 7.8)) | |
| if rows[r][0].startswith("TOPLAM") or rows[r][0] in ("BRÜT KAR", "DÖNEM KARI", "ESAS FAALİYET KARI"): | |
| style.append(("LINEABOVE", (2, r), (-1, r), 0.5, colors.black)) | |
| t.setStyle(TableStyle(style)) | |
| return t | |
| def d2_pdf(cur, prev, path): | |
| doc = SimpleDocTemplate(str(path), pagesize=A4, leftMargin=1.8 * cm, rightMargin=1.8 * cm, topMargin=1.8 * cm, | |
| bottomMargin=2 * cm, title="Kuzeyçınar Gıda 31.12.2025 Konsolide Finansal Tablolar") | |
| el = [P("KUZEYÇINAR GIDA SANAYİ VE TİCARET A.Ş.<br/>VE BAĞLI ORTAKLIKLARI", "h1"), | |
| P("31 ARALIK 2025 TARİHİ İTİBARIYLA HAZIRLANAN KONSOLİDE FİNANSAL TABLOLAR VE BAĞIMSIZ DENETÇİ RAPORU", "h2"), | |
| P("Konsolide finansal tablolar, Sermaye Piyasası Kurulu'nun II-14.1 sayılı Tebliği hükümleri uyarınca Türkiye " | |
| "Finansal Raporlama Standartları'na (TFRS) uygun olarak hazırlanmıştır."), | |
| P("31 Aralık 2025 Tarihli Konsolide Finansal Durum Tablosu (Bilanço)", "cap"), | |
| P("(Tutarlar aksi belirtilmedikçe Türk Lirası (\"TL\") olarak ifade edilmiştir.)", "note"), | |
| _fin_table(BILANCO, cur, prev), PageBreak(), | |
| P("1 Ocak - 31 Aralık 2025 Hesap Dönemine Ait Konsolide Kar veya Zarar Tablosu", "cap"), | |
| P("(Tutarlar aksi belirtilmedikçe Türk Lirası (\"TL\") olarak ifade edilmiştir.)", "note"), | |
| _fin_table([(a, b_, c) for a, b_, c in GELIR], cur, prev), | |
| Spacer(1, 8), | |
| P("İlişikteki dipnotlar bu konsolide finansal tabloların tamamlayıcı parçasıdır.", "note")] | |
| doc.build(el, onFirstPage=footer, onLaterPages=footer) | |
| # ================================================================== D3: il istatistik bülteni (HTML) | |
| ILCE = ["Merkez", "Yukarıova", "Kızılçam", "Taşlıdere", "Akpınar", "Sarıyurt", "Çaltepe", "Karaağıl"] | |
| AYLAR = ["Ocak", "Şubat", "Mart", "Nisan", "Mayıs", "Haziran", "Temmuz", "Ağustos", "Eylül", "Ekim", "Kasım", "Aralık"] | |
| def d3_data(): | |
| tur = {} | |
| for i in ILCE: | |
| base = rng.randint(4_000, 60_000) * (4 if i == "Merkez" else 1) | |
| q = [int(base * f * rng.uniform(0.9, 1.1)) for f in (0.6, 1.1, 1.6, 0.7)] | |
| prev = int(sum(q) * rng.uniform(0.85, 1.12)) | |
| tur[i] = dict(q=q, top=sum(q), prev=prev, deg=round(100 * (sum(q) - prev) / prev, 1)) | |
| konut = {} | |
| for a in AYLAR: | |
| ip = rng.randint(180, 520) | |
| dg = rng.randint(700, 1500) | |
| prev = int((ip + dg) * rng.uniform(0.82, 1.18)) | |
| konut[a] = dict(ip=ip, dg=dg, top=ip + dg, prev=prev, deg=round(100 * (ip + dg - prev) / prev, 1)) | |
| return tur, konut | |
| def d3_html(tur, konut, path): | |
| def fmt(x): | |
| return tr(x, 0) | |
| il_q = [sum(v["q"][k] for v in tur.values()) for k in range(4)] | |
| il_top, il_prev = sum(il_q), sum(v["prev"] for v in tur.values()) | |
| rows1 = "".join( | |
| f"<tr><td>{i}</td>" + "".join(f"<td>{fmt(x)}</td>" for x in v["q"]) + | |
| f"<td>{fmt(v['top'])}</td><td>{fmt(v['prev'])}</td><td>{tr(v['deg'], 1)}</td></tr>\n" for i, v in tur.items()) | |
| rows1 += (f"<tr class='toplam'><td>İl Toplamı</td>" + "".join(f"<td>{fmt(x)}</td>" for x in il_q) + | |
| f"<td>{fmt(il_top)}</td><td>{fmt(il_prev)}</td><td>{tr(round(100 * (il_top - il_prev) / il_prev, 1), 1)}</td></tr>") | |
| rows2 = "".join(f"<tr><td>{a} 2025</td><td>{fmt(v['ip'])}</td><td>{fmt(v['dg'])}</td><td>{fmt(v['top'])}</td>" | |
| f"<td>{fmt(v['prev'])}</td><td>{tr(v['deg'], 1)}</td></tr>\n" for a, v in konut.items()) | |
| html = f"""<!doctype html> | |
| <html lang="tr"><head><meta charset="utf-8"><title>Ardıçlı İli 2025 Yılı İstatistik Bülteni</title> | |
| <style>body{{font-family:DejaVu Sans,Arial,sans-serif;max-width:900px;margin:24px auto;color:#222}} | |
| table{{border-collapse:collapse;margin:8px 0 4px}}td,th{{border:1px solid #888;padding:3px 8px;font-size:13px}} | |
| td:not(:first-child){{text-align:right}}th{{background:#e8eef6}}.toplam td{{font-weight:bold}} | |
| tfoot td{{border:none;font-size:11px;color:#555;text-align:left!important}}.uyari{{color:#9a3412;font-size:12px}}</style></head> | |
| <body> | |
| <p class="uyari">{UYARI}</p> | |
| <h1>Ardıçlı İli 2025 Yılı İstatistik Bülteni</h1> | |
| <p>Bu bülten, Ardıçlı İl Planlama ve Koordinasyon Müdürlüğü tarafından derlenen turizm ve konut istatistiklerini içermektedir. | |
| Veriler geçicidir ve sonraki yayımlarda güncellenebilir.</p> | |
| <h2>1. Turizm</h2> | |
| <table> | |
| <caption>Tablo 1: İlçelere Göre Konaklama Tesislerine Geliş Sayısı (Kişi)</caption> | |
| <thead> | |
| <tr><th rowspan="2">İlçe</th><th colspan="4">2025</th><th rowspan="2">2025 Toplam</th><th rowspan="2">2024 Toplam</th><th rowspan="2">Değişim (%)</th></tr> | |
| <tr><th>Ç1</th><th>Ç2</th><th>Ç3</th><th>Ç4</th></tr> | |
| </thead> | |
| <tbody> | |
| {rows1} | |
| </tbody> | |
| <tfoot><tr><td colspan="8">Kaynak: Ardıçlı İl Kültür ve Turizm Müdürlüğü, belediye ve bakanlık belgeli tesis kayıtları. Ç: çeyrek.</td></tr></tfoot> | |
| </table> | |
| <h2>2. Konut</h2> | |
| <table> | |
| <caption>Tablo 2: Aylara Göre Konut Satışları (Adet)</caption> | |
| <thead><tr><th>Ay</th><th>İpotekli Satış</th><th>Diğer Satış</th><th>Toplam Satış</th><th>Önceki Yılın Aynı Ayı</th><th>Yıllık Değişim (%)</th></tr></thead> | |
| <tbody> | |
| {rows2} | |
| </tbody> | |
| <tfoot><tr><td colspan="6">Kaynak: Ardıçlı Tapu Müdürlüğü kayıtları. Aralık ayı verileri geçicidir.</td></tr></tfoot> | |
| </table> | |
| </body></html>""" | |
| path.write_text(html, encoding="utf-8") | |
| return il_q, il_top, il_prev | |
| # ================================================================== sorular ve altın cevaplar | |
| def questions(b, tot, pers, mah, cur, prev, tur, konut, il_top): | |
| Q = [] | |
| def q(belge, soru, cevap, tip="sayi", ozellik="", zorluk="orta", birim=None, **kw): | |
| Q.append(dict(id=f"P{len(Q) + 1:02d}", belge=belge, soru=soru, tip=tip, cevap=cevap, birim=birim, | |
| ozellik=ozellik, zorluk=zorluk, **kw)) | |
| D1, D2, D3 = "yesilvadi_belediyesi_2025_faaliyet_raporu.pdf", "kuzeycinar_gida_2025_finansal_tablolar.pdf", \ | |
| "ardicli_ili_2025_istatistik_bulteni.html" | |
| num = {k: v for k, v in b.items() if v["oran"] is not None} | |
| # --- D1 bütçe | |
| q(D1, "Yeşilvadi Belediyesinin 2025 yılında personel giderleri gerçekleşmesi ne kadardır?", b["01"]["gerc"], | |
| ozellik="iki satırlı başlık; ekonomik kod sütunu", zorluk="kolay", birim="TL") | |
| q(D1, "Mal ve hizmet alım giderleri için toplam ödenek kaç TL'dir?", b["03"]["top"], | |
| ozellik="birleşik 'Ödenek' başlığı altındaki alt sütun", birim="TL") | |
| q(D1, "Sermaye giderlerinin gerçekleşme oranı yüzde kaçtır?", b["06"]["oran"], | |
| ozellik="yüzde birimi yalnızca başlıkta (%)", zorluk="kolay") | |
| q(D1, "Gerçekleşme oranı en düşük olan gider türü hangisidir?", min(num.values(), key=lambda v: v["oran"])["ad"], | |
| tip="metin", ozellik="en düşük; '-' değerli satır ve TOPLAM satırı dışlanmalı", zorluk="zor") | |
| q(D1, "Belediyenin 2025 yılı toplam bütçe gerçekleşmesi kaç TL'dir?", tot["gerc"], | |
| ozellik="belgenin TOPLAM satırı; çift sayım tuzağı", birim="TL") | |
| q(D1, "Faiz giderlerine yıl içinde eklenen ödenek ne kadardır?", b["04"]["ekl"], ozellik="alt sütun 'Eklenen'", | |
| birim="TL") | |
| q(D1, "Gerçekleşmesi 50 milyon TL'yi aşan gider türleri hangileridir?", | |
| sorted(v["ad"] for v in b.values() if v["gerc"] > 50e6), tip="liste", | |
| ozellik="eşik + birim dönüşümü (milyon TL)", zorluk="zor") | |
| q(D1, "Personel giderleri gerçekleşmesi kaç milyon TL'dir?", round(b["01"]["gerc"] / 1e6, 2), | |
| ozellik="birim dönüşümü TL → milyon TL", zorluk="zor", birim="milyon TL") | |
| q(D1, "Cari transferlerin toplam bütçe gerçekleşmesi içindeki payı yüzde kaçtır?", | |
| round(100 * b["05"]["gerc"] / tot["gerc"], 2), ozellik="pay; toplam satırı dışlanmalı", zorluk="zor") | |
| q(D1, "Yeşilvadi Belediyesinin 2024 yılı personel gideri ne kadardı?", None, tip="cevapsiz", | |
| ozellik="tabloda olmayan yıl") | |
| # --- D1 personel | |
| q(D1, "Belediyede kaç memur kadrosu doludur?", pers["Memur"][0], ozellik="basit seçim", zorluk="kolay") | |
| q(D1, "Belediyede toplam kaç boş kadro bulunmaktadır?", sum(v[1] or 0 for v in pers.values()), | |
| ozellik="TOPLAM satırı; '-' değerli satır") | |
| q(D1, "Sözleşmeli personel için toplam kadro sayısı kaçtır?", sum(x or 0 for x in pers["Sözleşmeli Personel"]), | |
| ozellik="sütun adı 'Toplam' (toplam sözcüğü çok anlamlı)", zorluk="zor") | |
| q(D1, "Belediyede hizmet alımıyla çalışan şirket personeli sayısı kaçtır?", pers["Şirket Personeli (*)"][0], | |
| ozellik="dipnot işaretli satır adı '(*)'", zorluk="zor") | |
| q(D1, "Belediyede kaç itfaiye eri kadrosu vardır?", None, tip="cevapsiz", ozellik="tabloda olmayan unvan") | |
| # --- D1 mahalle (çok sayfalı) | |
| m_list = list(mah.items()) | |
| q(D1, "Cumhuriyet Mahallesinin 2025 nüfusu kaçtır?", mah["Cumhuriyet"]["n25"], ozellik="çok sayfalı tablonun ilk sayfası", | |
| zorluk="kolay") | |
| q(D1, "Işıklar Mahallesinin 2025 nüfusu kaçtır?", mah["Işıklar"]["n25"], | |
| ozellik="çok sayfalı tablonun son sayfası; I/ı", zorluk="zor") | |
| q(D1, "Belediye sınırları içinde kaç mahalle vardır?", len(mah), | |
| ozellik="sayım; tablo sayfalara bölünmüş; Genel Toplam satırı dışlanmalı", zorluk="zor") | |
| q(D1, "2025 nüfusu en yüksek olan mahalle hangisidir?", max(m_list, key=lambda kv: kv[1]["n25"])[0], tip="metin", | |
| ozellik="en yüksek; tüm sayfalar", zorluk="zor") | |
| q(D1, "Nüfusu 2024'ten 2025'e azalan kaç mahalle vardır?", sum(1 for _, v in m_list if v["n25"] < v["n24"]), | |
| ozellik="negatif değişim sayımı", zorluk="zor") | |
| q(D1, "Mahallelerin 2025 yılı toplam nüfusu kaçtır?", sum(v["n25"] for v in mah.values()), | |
| ozellik="Genel Toplam satırı", zorluk="orta") | |
| q(D1, "Kurtuluş Mahallesinde 2025 yılında hane başına ortalama kaç kişi düşmektedir?", | |
| round(mah["Kurtuluş"]["n25"] / mah["Kurtuluş"]["hane"], 2), ozellik="iki sütun oranı", zorluk="zor") | |
| # --- D2 bilanço | |
| q(D2, "Kuzeyçınar Gıda'nın 31.12.2025 itibarıyla nakit ve nakit benzerleri ne kadardır?", cur["nakit"], | |
| ozellik="dikey çizgisiz tablo; tarihli dönem başlığı", zorluk="orta", birim="TL") | |
| q(D2, "Stoklar önceki döneme göre yüzde kaç artmıştır?", round(100 * (cur["stok"] - prev["stok"]) / prev["stok"], 2), | |
| ozellik="cari/önceki dönem yüzde değişim", zorluk="zor") | |
| q(D2, "Şirketin 2025 yılı sonu toplam varlıkları kaç TL'dir?", cur["top_varlik"], | |
| ozellik="ara toplam satırı (büyük harf)", birim="TL") | |
| q(D2, "Kısa vadeli borçlanmalar 31.12.2024 tarihinde ne kadardı?", prev["kv_borc"], | |
| ozellik="önceki dönem sütunu; aynı kalem adı iki kez değil", birim="TL") | |
| q(D2, "Cari dönemde toplam özkaynaklar ne kadardır?", cur["top_oz"], ozellik="ara toplam", birim="TL") | |
| q(D2, "Şirketin ödenmiş sermayesi kaç TL'dir?", cur["sermaye"], ozellik="dipnot sütunu bitişik", zorluk="kolay", | |
| birim="TL") | |
| # --- D2 gelir tablosu | |
| q(D2, "Kuzeyçınar Gıda'nın 2025 yılı hasılatı ne kadardır?", cur["hasilat"], ozellik="ikinci sayfadaki tablo", | |
| zorluk="kolay", birim="TL") | |
| q(D2, "2025 yılında brüt kâr ne kadar gerçekleşmiştir?", cur["bk"], ozellik="'kâr' / 'KAR' yazımı", birim="TL") | |
| q(D2, "2025 yılında satışların maliyeti ne kadardır?", abs(cur["smm"]), | |
| ozellik="parantezli negatif; '(-)' etiketi", birim="TL", isaret_serbest=True) | |
| q(D2, "Dönem kârı önceki yıla göre yüzde kaç değişmiştir?", round(100 * (cur["dk"] - prev["dk"]) / prev["dk"], 2), | |
| ozellik="yüzde değişim", zorluk="zor") | |
| q(D2, "2025 yılı pay başına kazanç kaç TL'dir?", cur["pbk"], ozellik="4 ondalıklı küçük sayı", zorluk="orta") | |
| q(D2, "2025 yılı brüt kâr marjı yüzde kaçtır?", round(100 * cur["bk"] / cur["hasilat"], 2), | |
| ozellik="alan formülü (brüt kâr / hasılat)", zorluk="zor") | |
| q(D2, "Kuzeyçınar Gıda'nın 2025 yılında kaç çalışanı vardır?", None, tip="cevapsiz", ozellik="tabloda olmayan bilgi") | |
| q(D2, "Şirketin 2026 yılı ilk çeyrek hasılatı ne kadardır?", None, tip="cevapsiz", ozellik="kapsam dışı dönem") | |
| # --- D3 turizm ve konut | |
| q(D3, "Merkez ilçesine 2025 yılının üçüncü çeyreğinde kaç kişi gelmiştir?", tur["Merkez"]["q"][2], | |
| ozellik="colspan başlık altında Ç3 sütunu", zorluk="orta") | |
| q(D3, "2025 yılında il genelinde konaklama tesislerine toplam kaç kişi gelmiştir?", il_top, | |
| ozellik="İl Toplamı satırı", zorluk="orta") | |
| q(D3, "Geliş sayısı 2024'e göre azalan ilçeler hangileridir?", sorted(i for i, v in tur.items() if v["deg"] < 0), | |
| tip="liste", ozellik="negatif değişim filtresi; toplam satırı dışlanmalı", zorluk="zor") | |
| q(D3, "Mart 2025'te toplam kaç konut satılmıştır?", konut["Mart"]["top"], ozellik="'Ay yyyy' satır etiketi", | |
| zorluk="orta") | |
| q(D3, "2025 yılında toplam kaç ipotekli konut satışı yapılmıştır?", sum(v["ip"] for v in konut.values()), | |
| ozellik="toplam satırı olmayan tabloda SUM", zorluk="orta") | |
| q(D3, "Konut satışlarının bir önceki yılın aynı ayına göre en çok düştüğü ay hangisidir?", | |
| min(konut.items(), key=lambda kv: kv[1]["deg"])[0] + " 2025", tip="metin", ozellik="en düşük negatif değişim", | |
| zorluk="zor") | |
| q(D3, "Ocak 2026'da kaç konut satılmıştır?", None, tip="cevapsiz", ozellik="kapsam dışı ay") | |
| q(D3, "Hangi ilçede en çok konut satılmıştır?", None, tip="cevapsiz", ozellik="tablo ilçe kırılımı içermiyor") | |
| return Q | |
| def main(): | |
| OUT.mkdir(parents=True, exist_ok=True) | |
| b, tot, pers, mah = d1_data() | |
| cur, prev = d2_data() | |
| tur, konut = d3_data() | |
| d1_pdf(b, tot, pers, mah, OUT / "yesilvadi_belediyesi_2025_faaliyet_raporu.pdf") | |
| d2_pdf(cur, prev, OUT / "kuzeycinar_gida_2025_finansal_tablolar.pdf") | |
| il_q, il_top, il_prev = d3_html(tur, konut, OUT / "ardicli_ili_2025_istatistik_bulteni.html") | |
| Q = questions(b, tot, pers, mah, cur, prev, tur, konut, il_top) | |
| meta = {"aciklama": "Kurgusal pilot belgeler için sorular ve ham veriden hesaplanan altın cevaplar.", | |
| "tohum": 31, "sorular": Q} | |
| (ROOT / "pilot" / "sorular.json").write_text(json.dumps(meta, ensure_ascii=False, indent=1), encoding="utf-8") | |
| # ham değerler (değer geri çağırma ölçümü için) | |
| ham = {"yesilvadi_belediyesi_2025_faaliyet_raporu.pdf": | |
| [x for v in b.values() for x in (v["butce"], v["ekl"], v["dus"], v["top"], v["gerc"]) ] + | |
| [x for v in b.values() if v["oran"] is not None for x in [v["oran"]]] + | |
| [x for d, bo in pers.values() for x in [d] + ([bo] if bo is not None else [])] + | |
| [x for v in mah.values() for x in (v["n24"], v["n25"], v["hane"], v["deg"])], | |
| "kuzeycinar_gida_2025_finansal_tablolar.pdf": | |
| [d[k] for d in (cur, prev) for _, _, k, *_ in BILANCO if k] + [d[k] for d in (cur, prev) for _, _, k in GELIR], | |
| "ardicli_ili_2025_istatistik_bulteni.html": | |
| [x for v in tur.values() for x in v["q"] + [v["top"], v["prev"], v["deg"]]] + | |
| [x for v in konut.values() for x in (v["ip"], v["dg"], v["top"], v["prev"], v["deg"])]} | |
| (ROOT / "pilot" / "ham_degerler.json").write_text(json.dumps(ham, ensure_ascii=False), encoding="utf-8") | |
| print("Belgeler:", sorted(p.name for p in OUT.iterdir())) | |
| print("Soru:", len(Q), "| cevapsız:", sum(1 for x in Q if x["tip"] == "cevapsiz")) | |
| if __name__ == "__main__": | |
| main() | |