KabaLang örnekleri: konsol, masaüstü ve web için dokuz proje

Konsol: fraktal (paralel şeritli 24-bit Mandelbrot/Julia + yakınlaşma),
sudoku (geri izlemeli, canlı animasyon), fatura (JSON → terminal tablosu,
PDF ve Excel).
Masaüstü: hesap makinesi (işlem önceliği, canlı bağlama), odak (Pomodoro),
parola atölyesi (entropi ölçer, SHA-256).
Web: pano (Kanban REST API + SQLite), kisalt (302 yönlendirme, SVG
istatistik), anket (adres başına tek oy, sunucuda çizilen grafik).

Hepsi `kabalang calistir` ile derlenip çalışır; web uygulamaları yalnız
127.0.0.1'i dinler, SQL parametre bağlamalı, HTML çıktısı kaçırılır.
This commit is contained in:
2026-10-03 08:37:47 +03:00
commit e0e4a0d6c7
40 changed files with 2652 additions and 0 deletions
+39
View File
@@ -0,0 +1,39 @@
# Fatura — JSON siparişten terminal tablosu, PDF ve Excel
![Fatura](../../medya/fatura.png)
`siparis.json`'u okur; her kalem için indirim ve KDV hesaplar, KDV'yi
oranlara göre döker ve sonucu üç biçimde verir:
1. Terminalde kutu çizgili, renkli bir fatura tablosu
2. `fatura.pdf` — Türkçe karakterleri ve `₺` işaretini taşıyan, sayfa
numaralı PDF
3. `fatura.xlsx` — tablolar ayrı çalışma sayfalarında
```bash
kabalang calistir fatura.kbl # siparis.json → ./fatura.pdf + ./fatura.xlsx
kabalang calistir fatura.kbl -- baska.json --cikti ~/Belgeler
```
## KabaLang'ın gösterdikleri
| Özellik | Nerede |
|---|---|
| `yapi` + metotlar | `Kalem.brut()`, `matrah()`, `kdv_tutari()` — hesap verinin yanında |
| `sonuc<T, Hata>` | `siparis_oku` dosya yokken ya da JSON bozukken **değerle** hata döner; yok sayılamaz |
| `dene / yakala` | JSON dizisini sonuna kadar gezmek |
| `json` | İç içe erişim: `v["satici"]["ad"]`, `v["kalemler"][i]["adet"]` |
| `kaba.belge` | Aynı belge nesnesinden `pdf_yaz` ve `xlsx_yaz` |
| f-string biçimi | `{ad:<32}`, `{tutar:>15}`, `{k % 100:02d}` — hizalı tablo ve kuruş |
## Para nasıl tutuluyor
Her ara sonuç **kuruşa yuvarlanır** (`kurus()`); `0.1 + 0.2` gibi ikili kesir
artıkları faturaya taşınmaz. `para()` sayıyı Türkçe biçime çevirir:
`1249.9 → 1.249,90 ₺`.
Örnek siparişin toplamları elle de hesaplanıp karşılaştırıldı:
ara toplam 65.439,80 ₺ · indirim 1.879,99 ₺ · KDV 11.748,96 ₺ ·
**genel toplam 75.308,77 ₺**.
> Satıcı ve alıcı bilgileri örnek amaçlı, hayalidir.
+179
View File
@@ -0,0 +1,179 @@
# ╔══════════════════════════════════════════════════════════════════╗
# ║ FATURA — JSON siparişten KDV'li fatura: terminal + PDF + Excel ║
# ║ ║
# ║ siparis.json'u okur, satır satır indirim ve KDV hesaplar, ║
# ║ oranlara göre KDV dökümü çıkarır; sonucu terminalde kutu ║
# ║ çizgili bir tablo olarak basar ve aynı veriden fatura.pdf ile ║
# ║ fatura.xlsx üretir. Para kuruşa yuvarlanarak tutulur. ║
# ║ ║
# ║ kabalang calistir fatura.kbl ║
# ║ kabalang calistir fatura.kbl -- baska.json --cikti ~/Belgeler ║
# ╚══════════════════════════════════════════════════════════════════╝
kullan kaba.sistem
kullan kaba.belge
yapi Kalem:
ad = ""
adet = 0
birim_fiyat = 0.0
indirim = 0 # yüzde
kdv = 0 # yüzde
fonksiyon brut() -> ondalik:
don kurus(birim_fiyat * ondalik(adet))
fonksiyon matrah() -> ondalik:
don kurus(brut() * (1.0 - ondalik(indirim) / 100.0))
fonksiyon kdv_tutari() -> ondalik:
don kurus(matrah() * ondalik(kdv) / 100.0)
# Kuruşa yuvarla: 0.1 + 0.2 gibi ikili kesir artıklarını faturaya taşıma.
fonksiyon kurus(x: ondalik) -> ondalik:
don matematik.yuvarla(x * 100.0) / 100.0
# 1249.9 → "1.249,90 ₺" — Türkçe binlik ve ondalık ayıracı.
fonksiyon para(x: ondalik) -> metin:
k = sayi(matematik.yuvarla(x * 100.0))
tam = metin(k // 100)
gruplu = ""
i = tam.uzunluk()
iken i > 3:
gruplu = "." + tam.dilim(i - 3, 3) + gruplu
i = i - 3
gruplu = tam.dilim(0, i) + gruplu
don f"{gruplu},{k % 100:02d} ₺"
# ── Siparişi oku ─────────────────────────────────────────────────────
# Beklenen hata (dosya yok, bozuk JSON) dönüş değeriyle bildirilir.
fonksiyon siparis_oku(yol: metin) -> sonuc<metin, Hata>:
eger degil dosya.var_mi(yol):
don hata(f"sipariş dosyası bulunamadı: {yol}")
ham = dosya.oku(yol)
eger degil json.gecerli_mi(ham):
don hata(f"{yol} geçerli bir JSON değil")
don tamam(ham)
# ── Terminal tablosu ─────────────────────────────────────────────────
fonksiyon boya(yazi: metin, rgb: metin) -> metin:
don "\033[38;2;" + rgb + "m" + yazi + "\033[0m"
fonksiyon cizgi(sol: metin, orta: metin, sag: metin) -> metin:
don boya(" " + sol + "━".tekrarla(4) + orta + "━".tekrarla(34) + orta + "━".tekrarla(6) + orta + "━".tekrarla(15) + orta + "━".tekrarla(6) + orta + "━".tekrarla(5) + orta + "━".tekrarla(16) + sag, "70;80;110")
fonksiyon satir(no: metin, ad: metin, adet: metin, birim: metin, ind: metin, kdv: metin, tutar: metin) -> metin:
c = boya("┃", "70;80;110")
don f" {c}{no:>3} {c} {ad:<32} {c}{adet:>5} {c}{birim:>14} {c}{ind:>5} {c}{kdv:>4} {c}{tutar:>15} {c}"
# ── Program ──────────────────────────────────────────────────────────
ks = KomutSatiri("fatura", "JSON siparişten KDV'li fatura üretir")
ks.konumsal("siparis", "Sipariş dosyası (varsayılan: siparis.json)")
ks.secenek("cikti", "c", "PDF ve XLSX'in yazılacağı klasör")
c = ks.coz()
eger c.yardim_mi():
c.yardim_yaz()
cikis(0)
eger c.hatali_mi():
c.hata_yaz_ve_cik()
okunan = siparis_oku(c.konumsal("siparis").deger_veya("siparis.json"))
eger okunan.hatali_mi():
konsol.hata_yaz("✗ " + okunan.hata().mesaj() + "\n")
cikis(1)
v = json.coz(okunan.deger())
# JSON dizisinin uzunluğu sorulamıyor; sınırın dışına çıkınca biter.
kalemler = [Kalem()] # boş yapı listesi: bir öğeyle kurup sil
kalemler.sil(0)
i = 0
bitti = yanlis
iken degil bitti:
dene:
j = v["kalemler"][i]
kalemler.ekle(Kalem(metin(j["ad"]), sayi(j["adet"]), ondalik(j["birim_fiyat"]), sayi(j["indirim"]), sayi(j["kdv"])))
i = i + 1
yakala:
bitti = dogru
# ── Hesap ────────────────────────────────────────────────────────────
ara_toplam = 0.0
indirim_toplam = 0.0
kdv_toplam = 0.0
dongu k icinde kalemler:
ara_toplam = ara_toplam + k.brut()
indirim_toplam = indirim_toplam + k.brut() - k.matrah()
kdv_toplam = kdv_toplam + k.kdv_tutari()
matrah_toplam = ara_toplam - indirim_toplam
genel_toplam = kurus(matrah_toplam + kdv_toplam)
# ── Terminal ─────────────────────────────────────────────────────────
no = metin(v["fatura_no"])
tarih = metin(v["tarih"])
satici = metin(v["satici"]["ad"])
alici = metin(v["alici"]["ad"])
yazdir("")
yazdir(boya(f" ◆ FATURA {no}", "125;170;255") + boya(f" {tarih}", "110;120;150"))
yazdir(boya(f" {satici} → {alici}", "200;208;224"))
yazdir(cizgi("┏", "┳", "┓"))
yazdir(satir("#", "Ürün / hizmet", "Adet", "Birim fiyat", "İnd.", "KDV", "Tutar"))
yazdir(cizgi("┣", "╋", "┫"))
s = 1
dongu k icinde kalemler:
ind = "—"
eger k.indirim > 0:
ind = f"%{k.indirim}"
yazdir(satir(metin(s), k.ad, metin(k.adet), para(k.birim_fiyat), ind, f"%{k.kdv}", para(k.matrah())))
s = s + 1
yazdir(cizgi("┗", "┻", "┛"))
fonksiyon toplam_satiri(ad: metin, deger: metin, rgb: metin) -> metin:
don boya(f"{ad:>78}", "150;160;185") + boya(f"{deger:>17}", rgb)
yazdir(toplam_satiri("Ara toplam", para(ara_toplam), "200;208;224"))
yazdir(toplam_satiri("İndirim", "−" + para(indirim_toplam), "248;113;113"))
yazdir(toplam_satiri("KDV matrahı", para(matrah_toplam), "200;208;224"))
dongu oran icinde [20, 10, 1]:
o_matrah = 0.0
o_kdv = 0.0
dongu k icinde kalemler:
eger k.kdv == oran:
o_matrah = o_matrah + k.matrah()
o_kdv = o_kdv + k.kdv_tutari()
eger o_kdv > 0.0:
yazdir(toplam_satiri(f"KDV %{oran} ({para(o_matrah)} üzerinden)", para(o_kdv), "200;208;224"))
yazdir(toplam_satiri("GENEL TOPLAM", para(genel_toplam), "74;222;128"))
# ── Belge: aynı veriden PDF + Excel ──────────────────────────────────
klasor = c.secenek("cikti").deger_veya(".")
b = belge.yeni(f"Fatura {no}")
belge.altbilgi(b, f"{satici} · {no}")
belge.baslik(b, "FATURA", 1)
belge.paragraf(b, f"Fatura no: {no} Tarih: {tarih}")
belge.baslik(b, "Satıcı", 3)
belge.paragraf(b, satici + " — " + metin(v["satici"]["adres"]) + " — " + metin(v["satici"]["vergi"]))
belge.baslik(b, "Alıcı", 3)
belge.paragraf(b, alici + " — " + metin(v["alici"]["adres"]) + " — " + metin(v["alici"]["vergi"]))
belge.baslik(b, "Kalemler", 2)
belge.tablo_basligi(b, ["#", "Ürün / hizmet", "Miktar × fiyat", "İnd. / KDV", "Tutar"])
s = 1
dongu k icinde kalemler:
ind = "—"
eger k.indirim > 0:
ind = f"%{k.indirim}"
belge.tablo_satiri(b, [metin(s), metin(k.ad), f"{k.adet} × {para(k.birim_fiyat)}", f"{ind} / %{k.kdv}", para(k.matrah())])
s = s + 1
belge.baslik(b, "Özet", 2)
belge.tablo_basligi(b, ["Kalem", "Tutar"])
belge.tablo_satiri(b, ["Ara toplam", para(ara_toplam)])
belge.tablo_satiri(b, ["İndirim", "-" + para(indirim_toplam)])
belge.tablo_satiri(b, ["KDV matrahı", para(matrah_toplam)])
belge.tablo_satiri(b, ["KDV toplamı", para(kdv_toplam)])
belge.tablo_satiri(b, ["GENEL TOPLAM", para(genel_toplam)])
belge.vurgu(b, f"Ödenecek tutar: {para(genel_toplam)}")
yazdir("")
eger belge.pdf_yaz(b, klasor + "/fatura.pdf"):
yazdir(boya(f" ✓ {klasor}/fatura.pdf yazıldı", "74;222;128"))
degilse:
yazdir(boya(" ✗ PDF yazılamadı", "248;113;113"))
eger belge.xlsx_yaz(b, klasor + "/fatura.xlsx"):
yazdir(boya(f" ✓ {klasor}/fatura.xlsx yazıldı", "74;222;128"))
belge.kapat(b)
+22
View File
@@ -0,0 +1,22 @@
{
"fatura_no": "A37-2026-000142",
"tarih": "2026-10-02",
"satici": {
"ad": "Atölye 37 Bilişim Ltd. Şti.",
"adres": "Yıldız Teknopark, B Blok No:7, İstanbul",
"vergi": "Boğaziçi VD · 1234567890"
},
"alici": {
"ad": "Mavi Deniz Kafe ve Ortak Çalışma Alanı",
"adres": "Kordon Boyu Cad. No:12, Konak / İzmir",
"vergi": "Konak VD · 9876543210"
},
"kalemler": [
{ "ad": "Mekanik klavye (Türkçe Q)", "adet": 4, "birim_fiyat": 2450.00, "indirim": 10, "kdv": 20 },
{ "ad": "27\" IPS monitör", "adet": 2, "birim_fiyat": 8999.90, "indirim": 5, "kdv": 20 },
{ "ad": "Ergonomik çalışma sandalyesi", "adet": 3, "birim_fiyat": 6340.00, "indirim": 0, "kdv": 20 },
{ "ad": "Yazılım bakım hizmeti (aylık)", "adet": 1, "birim_fiyat": 12500.00, "indirim": 0, "kdv": 20 },
{ "ad": "Toplantı ikramı (kişi başı)", "adet": 12, "birim_fiyat": 185.00, "indirim": 0, "kdv": 10 },
{ "ad": "Kahve çekirdeği 1 kg", "adet": 5, "birim_fiyat": 780.00, "indirim": 0, "kdv": 1 }
]
}