diff --git a/assets/pasted-20260206-000101-e0693223.png b/assets/pasted-20260206-000101-e0693223.png new file mode 100644 index 0000000..fdda5e3 Binary files /dev/null and b/assets/pasted-20260206-000101-e0693223.png differ diff --git a/config/__pycache__/settings.cpython-311.pyc b/config/__pycache__/settings.cpython-311.pyc index 96bce55..4495e11 100644 Binary files a/config/__pycache__/settings.cpython-311.pyc and b/config/__pycache__/settings.cpython-311.pyc differ diff --git a/config/__pycache__/urls.cpython-311.pyc b/config/__pycache__/urls.cpython-311.pyc index 0b85e94..894e171 100644 Binary files a/config/__pycache__/urls.cpython-311.pyc and b/config/__pycache__/urls.cpython-311.pyc differ diff --git a/config/settings.py b/config/settings.py index 291d043..37b9783 100644 --- a/config/settings.py +++ b/config/settings.py @@ -43,14 +43,9 @@ CSRF_COOKIE_SECURE = True SESSION_COOKIE_SAMESITE = "None" CSRF_COOKIE_SAMESITE = "None" -# Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/ - # Application definition INSTALLED_APPS = [ - 'django.contrib.admin', - 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', @@ -63,10 +58,7 @@ MIDDLEWARE = [ 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', - # Disable X-Frame-Options middleware to allow Flatlogic preview iframes. - # 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] X_FRAME_OPTIONS = 'ALLOWALL' @@ -81,7 +73,6 @@ TEMPLATES = [ 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.request', - 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', # IMPORTANT: do not remove – injects PROJECT_DESCRIPTION/PROJECT_IMAGE_URL and cache-busting timestamp 'core.context_processors.project_context', @@ -110,26 +101,6 @@ DATABASES = { }, } - -# Password validation -# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators - -AUTH_PASSWORD_VALIDATORS = [ - { - 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', - }, -] - - # Internationalization # https://docs.djangoproject.com/en/5.2/topics/i18n/ diff --git a/config/urls.py b/config/urls.py index bcfc074..be886bc 100644 --- a/config/urls.py +++ b/config/urls.py @@ -14,13 +14,11 @@ Including another URLconf 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ -from django.contrib import admin from django.urls import include, path from django.conf import settings from django.conf.urls.static import static urlpatterns = [ - path("admin/", admin.site.urls), path("", include("core.urls")), ] diff --git a/core/__pycache__/forms.cpython-311.pyc b/core/__pycache__/forms.cpython-311.pyc new file mode 100644 index 0000000..143708c Binary files /dev/null and b/core/__pycache__/forms.cpython-311.pyc differ diff --git a/core/__pycache__/urls.cpython-311.pyc b/core/__pycache__/urls.cpython-311.pyc index 5a69659..6159c03 100644 Binary files a/core/__pycache__/urls.cpython-311.pyc and b/core/__pycache__/urls.cpython-311.pyc differ diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index 37a3157..cac8e17 100644 Binary files a/core/__pycache__/views.cpython-311.pyc and b/core/__pycache__/views.cpython-311.pyc differ diff --git a/core/forms.py b/core/forms.py new file mode 100644 index 0000000..9df1830 --- /dev/null +++ b/core/forms.py @@ -0,0 +1,27 @@ +from django import forms +from .models import Firma, Fatura, FaturaKalemi + +class FirmaForm(forms.ModelForm): + class Meta: + model = Firma + fields = ['ad', 'vergi_no', 'mersis_no', 'adres'] + widgets = { + 'ad': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Firma Tam Adı'}), + 'vergi_no': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Vergi No / TC Kimlik No'}), + 'mersis_no': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'MERSİS No (Opsiyonel)'}), + 'adres': forms.Textarea(attrs={'class': 'form-control', 'rows': 3, 'placeholder': 'Firma Adresi'}), + } + +class FaturaForm(forms.ModelForm): + class Meta: + model = Fatura + fields = ['firma', 'fatura_no', 'tarih', 'ara_toplam', 'kdv_toplam', 'genel_toplam', 'pdf_dosyasi'] + widgets = { + 'firma': forms.Select(attrs={'class': 'form-select'}), + 'fatura_no': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Fatura No'}), + 'tarih': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}), + 'ara_toplam': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}), + 'kdv_toplam': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}), + 'genel_toplam': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}), + 'pdf_dosyasi': forms.FileInput(attrs={'class': 'form-control'}), + } diff --git a/core/templates/base.html b/core/templates/base.html index 43c2f26..f530a5f 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -3,7 +3,7 @@ - {% block title %}Fatura Yönetim Sistemi{% endblock %} + {% block title %}FaturaYol - Akıllı Fatura Yönetimi{% endblock %} @@ -13,9 +13,10 @@ {% block extra_css %}{% endblock %} @@ -121,49 +133,68 @@
- - {% block content %}{% endblock %} + {% block content %}{% endblock %} +
diff --git a/core/templates/core/confirm_delete.html b/core/templates/core/confirm_delete.html new file mode 100644 index 0000000..45ba219 --- /dev/null +++ b/core/templates/core/confirm_delete.html @@ -0,0 +1,30 @@ +{% extends "base.html" %} + +{% block title %}Silmeyi Onayla - FaturaYol{% endblock %} +{% block page_title %}{{ type }} Silme İşlemi{% endblock %} + +{% block content %} +
+
+
+
+
+ +
+

Emin misiniz?

+

+ {{ object }} isimli {{ type|lower }} kaydını silmek üzeresiniz. + Bu işlem geri alınamaz ve bu kayda bağlı tüm veriler silinecektir. +

+
+ {% csrf_token %} +
+ + İptal +
+
+
+
+
+
+{% endblock %} diff --git a/core/templates/core/fatura_arsivi.html b/core/templates/core/fatura_arsivi.html new file mode 100644 index 0000000..c32d2ec --- /dev/null +++ b/core/templates/core/fatura_arsivi.html @@ -0,0 +1,57 @@ +{% extends "base.html" %} + +{% block title %}Fatura Arşivi - FaturaYol{% endblock %} +{% block page_title %}Fatura Arşivi{% endblock %} + +{% block content %} +
+
+

Firmalara göre gruplanmış fatura listesi. Detaylı görüntülemek için bir firmaya tıklayın.

+
+
+ + Yeni Firma Ekle + +
+
+ +
+ {% for firma in firmalar %} +
+
+
+
+ +
+
+ +
+
{{ firma.ad }}
+

VN: {{ firma.vergi_no }}

+ +
+
+ Fatura + {{ firma.fatura_sayisi }} Adet +
+
+ Toplam + {{ firma.toplam_tutar|default:0|floatformat:2 }} ₺ +
+
+ + + Dosyaları Görüntüle + +
+
+
+ {% empty %} +
+ +

Henüz kayıtlı bir firma veya fatura bulunamadı.

+ İlk Firmayı Ekle +
+ {% endfor %} +
+{% endblock %} diff --git a/core/templates/core/fatura_detay.html b/core/templates/core/fatura_detay.html new file mode 100644 index 0000000..87d5699 --- /dev/null +++ b/core/templates/core/fatura_detay.html @@ -0,0 +1,105 @@ +{% extends "base.html" %} + +{% block title %}Fatura Detayı - {{ fatura.fatura_no }}{% endblock %} +{% block page_title %}Fatura Detayı{% endblock %} + +{% block content %} + + +
+
+ +
+
+
PDF Önizleme
+ + Tam Ekran + +
+
+ {% if fatura.pdf_dosyasi %} + + {% else %} +
+ +

PDF dosyası bulunamadı.

+
+ {% endif %} +
+
+
+ +
+ +
+
+
Fatura Bilgileri
+ +
+ +

{{ fatura.firma.ad }}

+
+ +
+
+ +

{{ fatura.tarih|date:"d.m.Y" }}

+
+
+ +

{{ fatura.fatura_no }}

+
+
+ +
+ +
+ Ara Toplam + {{ fatura.ara_toplam }} ₺ +
+
+ KDV Toplam + {{ fatura.kdv_toplam }} ₺ +
+
+ Genel Toplam + {{ fatura.genel_toplam }} ₺ +
+
+
+ + +
+
+
+
Ürün / Hizmet Kalemleri
+
+
+ {% for kalem in kalemler %} +
+
+
{{ kalem.urun_adi }}
+ {{ kalem.adet }} Adet +
+
+ Birim: {{ kalem.birim_fiyat }} ₺ + Toplam: {{ kalem.toplam_tutar }} ₺ +
+
+ {% empty %} +
+ Kalem verisi bulunamadı. +
+ {% endfor %} +
+
+
+
+
+{% endblock %} diff --git a/core/templates/core/fatura_form.html b/core/templates/core/fatura_form.html new file mode 100644 index 0000000..7a5fcf8 --- /dev/null +++ b/core/templates/core/fatura_form.html @@ -0,0 +1,37 @@ +{% extends "base.html" %} + +{% block title %}{{ title }} - FaturaYol{% endblock %} +{% block page_title %}{{ title }}{% endblock %} + +{% block content %} +
+
+
+
+
+ {% csrf_token %} +
+
Fatura Detayları
+ {% for field in form %} +
+ + {{ field }} + {% if field.help_text %} +
{{ field.help_text }}
+ {% endif %} + {% for error in field.errors %} +
{{ error }}
+ {% endfor %} +
+ {% endfor %} +
+
+ İptal + +
+
+
+
+
+
+{% endblock %} diff --git a/core/templates/core/firma_detay.html b/core/templates/core/firma_detay.html new file mode 100644 index 0000000..daee070 --- /dev/null +++ b/core/templates/core/firma_detay.html @@ -0,0 +1,76 @@ +{% extends "base.html" %} + +{% block title %}Fatura Arşivi - FaturaYol{% endblock %} +{% block page_title %}{{ firma.ad }}{% endblock %} + +{% block content %} + + +
+
+
+
Tüm Faturalar
+ +
+
+
+ + + + + + + + + + + + + + {% for fatura in faturalar %} + + + + + + + + + + {% empty %} + + + + {% endfor %} + +
Fatura NoTarihAra ToplamKDVGenel ToplamDurumİşlemler
{{ fatura.fatura_no }}{{ fatura.tarih|date:"d.m.Y" }}{{ fatura.ara_toplam }} ₺{{ fatura.kdv_toplam }} ₺{{ fatura.genel_toplam }} ₺ + {% if fatura.islenmis %} + İşlendi + {% else %} + Bekliyor + {% endif %} + + + + + {% if fatura.pdf_dosyasi %} + + + + {% endif %} + + + +
+

Bu firmaya ait henüz fatura bulunamadı.

+
+
+
+{% endblock %} diff --git a/core/templates/core/firma_form.html b/core/templates/core/firma_form.html new file mode 100644 index 0000000..1702ac2 --- /dev/null +++ b/core/templates/core/firma_form.html @@ -0,0 +1,37 @@ +{% extends "base.html" %} + +{% block title %}{{ title }} - FaturaYol{% endblock %} +{% block page_title %}{{ title }}{% endblock %} + +{% block content %} +
+
+
+
+
+ {% csrf_token %} +
+
Firma Bilgileri
+ {% for field in form %} +
+ + {{ field }} + {% if field.help_text %} +
{{ field.help_text }}
+ {% endif %} + {% for error in field.errors %} +
{{ error }}
+ {% endfor %} +
+ {% endfor %} +
+
+ İptal + +
+
+
+
+
+
+{% endblock %} diff --git a/core/templates/core/index.html b/core/templates/core/index.html index 6a573d6..d8cbf0d 100644 --- a/core/templates/core/index.html +++ b/core/templates/core/index.html @@ -3,132 +3,140 @@ {% block title %}Gösterge Paneli | FaturaYol{% endblock %} {% block content %} -
-
-
-

Gösterge Paneli

-

Fatura yönetim sistemine genel bakış.

+
+
+

Gösterge Paneli

+

Fatura yönetim sistemine genel bakış ve hızlı istatistikler.

+
+
+ + +
+
+
+
+
+ +
+
+
Toplam Firma
+

{{ toplam_firma }}

+
+
+
+
+
+
+ +
+
+
Toplam Fatura
+

{{ toplam_fatura }}

+
+
+
+
+
+
+
+
+ +
+
+
Toplam Harcama
+

₺{{ toplam_harcama|floatformat:2 }}

+
+
+
+
+
- -
-
-
-
- -
-
-
Toplam Firma
-

{{ toplam_firma }}

-
+
+ +
+
+
+
Son Eklenen Faturalar
+ Tümünü Gör
-
-
-
-
- -
-
-
Toplam Fatura
-

{{ toplam_fatura }}

-
-
-
-
-
-
- -
-
-
Toplam Harcama
-

₺{{ toplam_harcama|floatformat:2 }}

+
+
+ + + + + + + + + + + + {% for fatura in son_faturalar %} + + + + + + + + {% empty %} + + + + {% endfor %} + +
Fatura NoFirmaTarihToplamİşlem
{{ fatura.fatura_no }} + {{ fatura.firma.ad }} + {{ fatura.tarih|date:"d.m.Y" }}₺{{ fatura.genel_toplam }} + + İncele + +
+
+ +
+

Henüz fatura eklenmemiş.

+
-
- -
-
-
-
Son Eklenen Faturalar
- Tümünü Gör -
-
-
- - - - - - - - - - - - - {% for fatura in son_faturalar %} - - - - - - - - - {% empty %} - - - - {% endfor %} - -
Fatura NoFirmaTarihToplamDurumİşlem
{{ fatura.fatura_no }}{{ fatura.firma.ad }}{{ fatura.tarih|date:"d.m.Y" }}₺{{ fatura.genel_toplam }} - {% if fatura.islenmis %} - İşlendi - {% else %} - Bekliyor - {% endif %} - - -
Henüz fatura eklenmemiş.
-
-
+ +
+
+
+
Hızlı İşlemler
-
- - -
-
-
-
Hızlı İşlemler
+
+ -
-
- - - -
+ +
+
Biliyor muydunuz?
+

Sistemimiz OCR teknolojisi sayesinde faturadaki tüm kalemleri otomatik olarak ayrıştırabilir.

diff --git a/core/templates/core/raporlar.html b/core/templates/core/raporlar.html new file mode 100644 index 0000000..b09efb9 --- /dev/null +++ b/core/templates/core/raporlar.html @@ -0,0 +1,68 @@ +{% extends "base.html" %} + +{% block title %}İstatistik & Raporlar - FaturaYol{% endblock %} +{% block page_title %}İstatistik & Raporlar{% endblock %} + +{% block content %} +
+
+
+
+
Aylık Harcama Trendi
+
+ + + + + + + + + + {% for harcama in aylik_harcama %} + + + + + + {% empty %} + + + + {% endfor %} + +
AyFatura AdediToplam Tutar
{{ harcama.tarih__month }}. Ay{{ harcama.adet }}{{ harcama.toplam }} ₺
Veri bulunamadı
+
+
+
+
+ +
+
+
+
KDV Özeti
+
+ Toplam Ödenen KDV +

{{ kdv_ozet.toplam_kdv|default:0 }} ₺

+
+
+ Fatura Başı Ortalama KDV +

{{ kdv_ozet.ortalama_kdv|default:0|floatformat:2 }} ₺

+
+
+
+
+
+ +
+
+
+
+ +

Gelişmiş Raporlama Yakında

+

Grafikler, Excel dışa aktarma ve kategori bazlı analizler bir sonraki güncellemede eklenecektir.

+
+
+
+
+{% endblock %} diff --git a/core/templates/core/search_results.html b/core/templates/core/search_results.html new file mode 100644 index 0000000..02f36c2 --- /dev/null +++ b/core/templates/core/search_results.html @@ -0,0 +1,61 @@ +{% extends "base.html" %} + +{% block title %}Arama Sonuçları - FaturaYol{% endblock %} +{% block page_title %}"{{ query }}" için Arama Sonuçları{% endblock %} + +{% block content %} +
+
Firmalar ({{ firmalar|length }})
+
+ {% for firma in firmalar %} +
+
+
+
{{ firma.ad }}
+

VN: {{ firma.vergi_no }}

+ Detaya Git +
+
+
+ {% empty %} +
Eşleşen firma bulunamadı.
+ {% endfor %} +
+
+ +
+
Faturalar ({{ faturalar|length }})
+
+
+ + + + + + + + + + + + {% for fatura in faturalar %} + + + + + + + + {% empty %} + + + + {% endfor %} + +
Fatura NoFirmaTarihGenel Toplamİşlem
{{ fatura.fatura_no }}{{ fatura.firma.ad }}{{ fatura.tarih|date:"d.m.Y" }}₺{{ fatura.genel_toplam }} + İncele +
Eşleşen fatura bulunamadı.
+
+
+
+{% endblock %} diff --git a/core/urls.py b/core/urls.py index 6299e3d..8421686 100644 --- a/core/urls.py +++ b/core/urls.py @@ -1,7 +1,18 @@ from django.urls import path - -from .views import home +from .views import ( + home, fatura_arsivi, firma_detay, fatura_detay, raporlar, + firma_ekle, fatura_ekle, search, firma_sil, fatura_sil +) urlpatterns = [ path("", home, name="home"), -] + path("arsiv/", fatura_arsivi, name="fatura_arsivi"), + path("firma//", firma_detay, name="firma_detay"), + path("fatura//", fatura_detay, name="fatura_detay"), + path("raporlar/", raporlar, name="raporlar"), + path("firma/ekle/", firma_ekle, name="firma_ekle"), + path("fatura/ekle/", fatura_ekle, name="fatura_ekle"), + path("arama/", search, name="search"), + path("firma//sil/", firma_sil, name="firma_sil"), + path("fatura//sil/", fatura_sil, name="fatura_sil"), +] \ No newline at end of file diff --git a/core/views.py b/core/views.py index 5057928..54fe897 100644 --- a/core/views.py +++ b/core/views.py @@ -1,13 +1,14 @@ -from django.shortcuts import render -from django.db.models import Sum, Count -from .models import Firma, Fatura +from django.shortcuts import render, get_object_or_404, redirect +from django.db.models import Sum, Count, Avg, Q +from .models import Firma, Fatura, FaturaKalemi +from .forms import FirmaForm, FaturaForm def home(request): """Fatura Yönetimi Gösterge Paneli.""" toplam_firma = Firma.objects.count() toplam_fatura = Fatura.objects.count() toplam_harcama = Fatura.objects.aggregate(Sum('genel_toplam'))['genel_toplam__sum'] or 0 - son_faturalar = Fatura.objects.select_related('firma').all()[:10] + son_faturalar = Fatura.objects.select_related('firma').all().order_by('-olusturulma_tarihi')[:10] context = { "toplam_firma": toplam_firma, @@ -16,4 +17,123 @@ def home(request): "son_faturalar": son_faturalar, "active_menu": "dashboard" } - return render(request, "core/index.html", context) \ No newline at end of file + return render(request, "core/index.html", context) + +def fatura_arsivi(request): + """Firmalara göre gruplanmış fatura arşivi.""" + firmalar = Firma.objects.annotate( + fatura_sayisi=Count('faturalar'), + toplam_tutar=Sum('faturalar__genel_toplam') + ).order_by('ad') + + context = { + "firmalar": firmalar, + "active_menu": "archive" + } + return render(request, "core/fatura_arsivi.html", context) + +def firma_detay(request, pk): + """Belirli bir firmanın fatura listesi.""" + firma = get_object_or_404(Firma, pk=pk) + faturalar = firma.faturalar.all().order_by('-tarih') + + context = { + "firma": firma, + "faturalar": faturalar, + "active_menu": "archive" + } + return render(request, "core/firma_detay.html", context) + +def fatura_detay(request, pk): + """Fatura detay önizleme ve kalemleri.""" + fatura = get_object_or_404(Fatura.objects.select_related('firma'), pk=pk) + kalemler = fatura.kalemler.all() + + context = { + "fatura": fatura, + "kalemler": kalemler, + "active_menu": "archive" + } + return render(request, "core/fatura_detay.html", context) + +def raporlar(request): + """İstatistik ve Raporlar.""" + # Aylık harcama trendi + aylik_harcama = Fatura.objects.values('tarih__month').annotate( + toplam=Sum('genel_toplam'), + adet=Count('id') + ).order_by('tarih__month') + + # KDV dağılımı + kdv_ozet = Fatura.objects.aggregate( + toplam_kdv=Sum('kdv_toplam'), + ortalama_kdv=Avg('kdv_toplam') + ) + + context = { + "aylik_harcama": aylik_harcama, + "kdv_ozet": kdv_ozet, + "active_menu": "reports" + } + return render(request, "core/raporlar.html", context) + +def firma_ekle(request): + if request.method == 'POST': + form = FirmaForm(request.POST) + if form.is_valid(): + form.save() + return redirect('fatura_arsivi') + else: + form = FirmaForm() + return render(request, 'core/firma_form.html', {'form': form, 'title': 'Yeni Firma Ekle'}) + +def fatura_ekle(request): + firma_id = request.GET.get('firma') + initial = {} + if firma_id: + initial['firma'] = firma_id + + if request.method == 'POST': + form = FaturaForm(request.POST, request.FILES) + if form.is_valid(): + fatura = form.save() + return redirect('firma_detay', pk=fatura.firma.pk) + else: + form = FaturaForm(initial=initial) + return render(request, 'core/fatura_form.html', {'form': form, 'title': 'Yeni Fatura Yükle'}) + +def search(request): + query = request.GET.get('q', '') + faturalar = [] + firmalar = [] + if query: + faturalar = Fatura.objects.filter( + Q(fatura_no__icontains=query) | + Q(firma__ad__icontains=query) + ).select_related('firma') + firmalar = Firma.objects.filter( + Q(ad__icontains=query) | + Q(vergi_no__icontains=query) + ) + + context = { + 'query': query, + 'faturalar': faturalar, + 'firmalar': firmalar, + } + return render(request, 'core/search_results.html', context) + +def firma_sil(request, pk): + firma = get_object_or_404(Firma, pk=pk) + if request.method == 'POST': + firma.delete() + return redirect('fatura_arsivi') + return render(request, 'core/confirm_delete.html', {'object': firma, 'type': 'Firma'}) + +def fatura_sil(request, pk): + fatura = get_object_or_404(Fatura, pk=pk) + firma_pk = fatura.firma.pk + if request.method == 'POST': + fatura.delete() + return redirect('firma_detay', pk=firma_pk) + return render(request, 'core/confirm_delete.html', {'object': fatura, 'type': 'Fatura'}) \ No newline at end of file