import arrow from decimal import Decimal from typing import Literal from datetime import date from dataclasses import dataclass @dataclass class GecikmeFaizSonucu: faiz_turu: str gecikme_gunu: int gunluk_oran: float faiz: float bsmv: float kkdf: float toplam: float # Faiz türüne göre aylık faiz oranı (%) GLOBAL_FAIZ_ORANLARI = {"akdi": 5.0, "gecikme": 5.3} # Vergi oranları (%) GLOBAL_BSMV_ORANI = 15.0 GLOBAL_KKDF_ORANI = 15.0 def hesapla_komisyon(vade_tarihi: date, islem_tarihi: date, tutar: float, oran: float) -> float: gecikme = (islem_tarihi - vade_tarihi).days if gecikme <= 0: return 0.0 komisyon = tutar * oran * gecikme return round(komisyon, 2) def hesapla_gunluk_oran( faiz_orani: float, tip: Literal["MIR", "YIR"], gun: int = 0 ) -> float: """ orijinal_oran: Yıllık ya da aylık faiz oranı (örneğin %12 için 0.12) tip: 'MIR' (Monthly Interest Rate) ya da 'YIR' (Yearly Interest Rate) """ faiz_orani = faiz_orani / 100 if tip.upper() == "MIR": if gun < 1: gun = 30 return faiz_orani / gun # varsayılan aylık 30 gün elif tip.upper() == "YIR": if gun < 1: gun = 360 return faiz_orani / gun # varsayılan yıl 365 gün else: raise ValueError("Faiz tipi yalnızca 'MIR' ya da 'YIR' olabilir.") def hesapla_gecikme_faizi( borc: float, vade_tarihi: date, islem_tarihi: date | None = None, faiz_orani: float = None, faiz_turu: str = "akdi", bsmv_orani: float = None, kkdf_orani: float = None, ) -> GecikmeFaizSonucu: if islem_tarihi is None: islem_tarihi = date.today() gecikme_gun = (arrow.get(islem_tarihi) - arrow.get(vade_tarihi)).days if gecikme_gun <= 0: return GecikmeFaizSonucu(faiz_turu, 0, 0, 0, 0, 0, 0) # Varsayılan oranları içerden bağla if faiz_orani is None: faiz_orani = GLOBAL_FAIZ_ORANLARI.get(faiz_turu, 5.0) if bsmv_orani is None: bsmv_orani = GLOBAL_BSMV_ORANI if kkdf_orani is None: kkdf_orani = GLOBAL_KKDF_ORANI faiz_tipi = "MIR" if faiz_turu == "akdi" else "YIR" gunluk_oran = hesapla_gunluk_oran(faiz_orani, faiz_tipi) faiz_tutari = Decimal(borc) * Decimal(gunluk_oran) * Decimal(gecikme_gun) bsmv = Decimal(faiz_tutari) * Decimal(bsmv_orani / 100) kkdf = Decimal(faiz_tutari) * Decimal(kkdf_orani / 100) toplam_faiz = Decimal(faiz_tutari) + Decimal(bsmv) + Decimal(kkdf) return GecikmeFaizSonucu( faiz_turu=faiz_turu, gecikme_gunu=gecikme_gun, gunluk_oran=round(gunluk_oran, 6), faiz=round(faiz_tutari, 2), bsmv=round(bsmv, 2), kkdf=round(kkdf, 2), toplam=round(toplam_faiz, 4), ) """ 2025 Güncel Oranlar (TCMB verilerine göre) tip: 'MIR' (Monthly Interest Rate) ya da 'YIR' (Yearly Interest Rate) Faiz Türü Aylık Oran Günlük Yaklaşık Açıklama Akdi Faiz %5,00 %0,1667 Asgari üzerindeki borca uygulanır Gecikme Faizi %5,30 %0,1767 Asgari tutarın ödenmeyen kısmına uygulanır CREATE TABLE public.account_delay_interest ( account_records_id int4 NOT NULL, build_decision_book_payment_id int4 NOT NULL, build_decision_book_payment_refid varchar(100) NOT NULL, interest_turn varchar(10) NOT NULL, interest_rate numeric(10, 2) NOT NULL, delay_day int2 NOT NULL, daily_rate numeric(20, 6) NOT NULL, interest numeric(20, 6) NOT NULL, bsmv numeric(20, 6) NOT NULL, kkdf numeric(20, 6) NOT NULL, total numeric(20, 6) NOT NULL, new_build_decision_book_payment_id int4 NULL, approved_record bool false NOT NULL, approving_person int4 NOT NULL, approving_at timestamptz NULL, id serial4 NOT NULL, uu_id uuid DEFAULT gen_random_uuid() NOT NULL, expiry_starts timestamptz DEFAULT now() NOT NULL, expiry_ends timestamptz DEFAULT now() NOT NULL, created_at timestamptz DEFAULT now() NOT NULL, updated_at timestamptz DEFAULT now() NOT NULL, CONSTRAINT account_delay_interest_pkey PRIMARY KEY (id)) CREATE UNIQUE INDEX _account_delay_interest_ndx_01 ON public.account_delay_interest USING btree (account_records_id, build_decision_book_payment_id); CREATE INDEX _account_delay_interest_ndx_02 ON public.account_delay_interest USING btree (build_decision_book_payment_id); CREATE UNIQUE INDEX _account_delay_interest_ndx_03 ON public.account_delay_interest USING btree (build_decision_book_payment_refid); CREATE UNIQUE INDEX _account_delay_interest_ndx_04 ON public.account_delay_interest USING btree (uu_id); -- Column comments COMMENT ON COLUMN public.account_delay_interest.build_decision_book_payment_refid IS 'ref id'; COMMENT ON COLUMN public.account_delay_interest.interest_turn IS 'faiz turu'; COMMENT ON COLUMN public.account_delay_interest.interest_rate IS 'uygulanan faiz'; COMMENT ON COLUMN public.account_delay_interest.delay_day IS 'gecikme_gunu'; COMMENT ON COLUMN public.account_delay_interest.daily_rate IS 'gunluk_oran'; COMMENT ON COLUMN public.account_delay_interest.interest IS 'faiz'; COMMENT ON COLUMN public.account_delay_interest.bsmv IS 'bsmv'; COMMENT ON COLUMN public.account_delay_interest.kkdf IS 'kkdf'; COMMENT ON COLUMN public.account_delay_interest.total IS 'toplam'; COMMENT ON COLUMN public.account_delay_interest.approved_record IS 'onaylandı'; COMMENT ON COLUMN public.account_delay_interest.approving_person IS 'onaylayan'; COMMENT ON COLUMN public.account_delay_interest.approving_at IS 'onay zamani'; """