from django.shortcuts import render, get_object_or_404, redirect from django.db.models import Sum, Count, Avg, Q from django.db import transaction from django.core.files.storage import default_storage from django.contrib import messages from .models import Firma, Fatura, FaturaKalemi from .forms import FirmaForm, FaturaForm from .utils import extract_text_from_pdf, analyze_invoice_text import os 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().order_by('-olusturulma_tarihi')[:10] context = { "toplam_firma": toplam_firma, "toplam_fatura": toplam_fatura, "toplam_harcama": toplam_harcama, "son_faturalar": son_faturalar, "active_menu": "dashboard" } 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('fatura_detay', pk=fatura.pk) else: form = FaturaForm(initial=initial) return render(request, 'core/fatura_form.html', {'form': form, 'title': 'Yeni Fatura Yükle'}) def fatura_otomatik_yukle(request): if request.method == 'POST' and request.FILES.get('pdf_dosyasi'): pdf_file = request.FILES['pdf_dosyasi'] # Save temporary file to extract text temp_name = 'temp_' + pdf_file.name path = default_storage.save('temp/' + temp_name, pdf_file) full_path = default_storage.path(path) try: text = extract_text_from_pdf(full_path) if not text: messages.error(request, "PDF dosyasından metin okunamadı. Dosya taranmış bir resim olabilir veya şifreli olabilir.") else: data = analyze_invoice_text(text) if not data: messages.error(request, "Yapay zeka faturayı analiz edemedi. Lütfen dosyanın geçerli bir fatura olduğundan emin olun.") else: with transaction.atomic(): # Smarter Firma matching vergi_no = str(data.get('vergi_no', '')).strip() mersis_no = str(data.get('mersis_no', '')).strip() firma_adi = data.get('firma_adi', '').strip() or 'Bilinmeyen Firma' firma = None # 1. Try by Vergi No / TCKN if vergi_no and vergi_no != 'None' and vergi_no != 'null': firma = Firma.objects.filter(vergi_no=vergi_no).first() # 2. Try by Mersis No if not firma and mersis_no and mersis_no != 'None' and mersis_no != 'null': firma = Firma.objects.filter(mersis_no=mersis_no).first() # 3. Try by Name (Exact) if not firma and firma_adi != 'Bilinmeyen Firma': firma = Firma.objects.filter(ad__iexact=firma_adi).first() # 4. Create if not found if not firma: # Ensure we have a unique vergi_no even if AI failed if not vergi_no or vergi_no == 'None' or vergi_no == 'null': vergi_no = f"AUTO-{os.urandom(4).hex()}" firma = Firma.objects.create( ad=firma_adi, vergi_no=vergi_no, mersis_no=mersis_no if (mersis_no != 'None' and mersis_no != 'null') else None, adres=data.get('adres', '') ) else: # Update missing info if found existing firma updated = False if not firma.mersis_no and mersis_no and mersis_no != 'None' and mersis_no != 'null': firma.mersis_no = mersis_no updated = True if not firma.adres and data.get('adres'): firma.adres = data.get('adres') updated = True if updated: firma.save() # Create Fatura fatura_no = data.get('fatura_no') or f"AUTO-{os.urandom(4).hex()}" # Check if this invoice already exists for this firm fatura = Fatura.objects.filter(fatura_no=fatura_no, firma=firma).first() if not fatura: fatura = Fatura.objects.create( firma=firma, fatura_no=fatura_no, tarih=data.get('tarih') or '2026-01-01', ara_toplam=data.get('ara_toplam') or 0, kdv_toplam=data.get('kdv_toplam') or 0, genel_toplam=data.get('genel_toplam') or 0, pdf_dosyasi=pdf_file, islenmis=True ) # Add Items kalemler = data.get('kalemler', []) if isinstance(kalemler, list): for k in kalemler: FaturaKalemi.objects.create( fatura=fatura, urun_adi=k.get('urun_adi') or 'Ürün', adet=k.get('adet') or 1, birim_fiyat=k.get('birim_fiyat') or 0, kdv_orani=k.get('kdv_orani') or 20, kdv_tutari=k.get('kdv_tutari') or 0, toplam_tutar=k.get('toplam_tutar') or 0 ) # Clean up temp file if default_storage.exists(path): default_storage.delete(path) messages.success(request, f"Fatura başarıyla analiz edildi ve {firma.ad} firmasına eklendi.") return redirect('fatura_detay', pk=fatura.pk) except Exception as e: messages.error(request, f"Fatura işlenirken bir hata oluştu: {str(e)}") print(f"Error processing automatic invoice: {e}") finally: # Clean up temp file if default_storage.exists(path): default_storage.delete(path) return render(request, 'core/fatura_form_otomatik.html', {'title': 'Otomatik Fatura Yükle', 'active_menu': 'dashboard'}) 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'})