import React, { useState } from 'react' import { FaPlus, FaSearch, FaCalendar, FaClock, FaExclamationTriangle, FaFileAlt, FaEdit, FaSave, } from 'react-icons/fa' import { FiInvoice, InvoiceTypeEnum, InvoiceStatusEnum, PaymentStatusEnum } from '../../../types/fi' import DataTable, { Column } from '../../../components/common/DataTable' import Widget from '../../../components/common/Widget' import { getInvoiceTypeColor, getInvoiceTypeText, getInvoiceStatusColor, getInvoiceStatusText, getPaymentStatusColor, getPaymentStatusText, } from '../../../utils/erp' interface InvoiceManagementProps { invoices: FiInvoice[] onAdd: () => void onEdit: (invoice: FiInvoice) => void onConvertFromWaybill: () => void onCreatePayment: (invoice: FiInvoice) => void onViewDetails: (invoice: FiInvoice) => void } const InvoiceManagement: React.FC = ({ invoices, onAdd, onEdit, onConvertFromWaybill, onCreatePayment, onViewDetails, }) => { const [searchTerm, setSearchTerm] = useState('') const [selectedType, setSelectedType] = useState('all') const [selectedStatus, setSelectedStatus] = useState('all') const [selectedPaymentStatus, setSelectedPaymentStatus] = useState( 'all', ) const [sortBy, setSortBy] = useState<'date' | 'amount' | 'dueDate'>('date') const filteredInvoices = invoices .filter((invoice) => { if ( searchTerm && !invoice.invoiceNumber.toLowerCase().includes(searchTerm.toLowerCase()) && !invoice.currentAccount?.accountCode?.toLowerCase().includes(searchTerm.toLowerCase()) && !invoice.waybillNumber?.toLowerCase().includes(searchTerm.toLowerCase()) ) { return false } if (selectedType !== 'all' && invoice.invoiceType !== selectedType) { return false } if (selectedStatus !== 'all' && invoice.status !== selectedStatus) { return false } if (selectedPaymentStatus !== 'all' && invoice.paymentStatus !== selectedPaymentStatus) { return false } return true }) .sort((a, b) => { switch (sortBy) { case 'date': return new Date(b.invoiceDate).getTime() - new Date(a.invoiceDate).getTime() case 'amount': return b.totalAmount - a.totalAmount case 'dueDate': return new Date(a.dueDate).getTime() - new Date(b.dueDate).getTime() default: return 0 } }) const getDaysUntilDue = (dueDate: Date) => { const today = new Date() const due = new Date(dueDate) const diffTime = due.getTime() - today.getTime() const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)) return diffDays } const formatCurrency = (amount: number) => { return amount.toLocaleString('tr-TR', { style: 'currency', currency: 'TRY', minimumFractionDigits: 2, }) } const columns: Column[] = [ { key: 'invoiceNumber', header: 'Fatura No', sortable: true, render: (invoice: FiInvoice) => (
{invoice.invoiceNumber}
{invoice.waybillNumber && (
İrs: {invoice.waybillNumber}
)}
), }, { key: 'type', header: 'Tür', render: (invoice: FiInvoice) => ( {getInvoiceTypeText(invoice.invoiceType)} ), }, { key: 'currentAccount', header: 'Cari Hesap', render: (invoice: FiInvoice) => (
{invoice.currentAccount?.accountCode || 'Bilinmeyen'}
), }, { key: 'dates', header: 'Tarihler', render: (invoice: FiInvoice) => { const daysUntilDue = getDaysUntilDue(invoice.dueDate) return (
Fatura: {new Date(invoice.invoiceDate).toLocaleDateString('tr-TR')}
Vade: {new Date(invoice.dueDate).toLocaleDateString('tr-TR')}
{daysUntilDue < 0 && (
{Math.abs(daysUntilDue)} gün gecikme
)}
) }, }, { key: 'amounts', header: 'Tutarlar', render: (invoice: FiInvoice) => (
{formatCurrency(invoice.totalAmount)}
{invoice.paidAmount > 0 && (
Ödenen: {formatCurrency(invoice.paidAmount)}
)} {invoice.remainingAmount > 0 && (
Kalan: {formatCurrency(invoice.remainingAmount)}
)}
), }, { key: 'status', header: 'Durum', render: (invoice: FiInvoice) => (
{getInvoiceStatusText(invoice.status)}
{getPaymentStatusText(invoice.paymentStatus)}
), }, { key: 'actions', header: 'İşlemler', render: (invoice: FiInvoice) => (
{invoice.paymentStatus !== PaymentStatusEnum.Paid && ( )}
), }, ] // Calculate statistics const totalInvoices = invoices.length const totalSalesAmount = invoices .filter((i) => i.invoiceType === InvoiceTypeEnum.Sales) .reduce((sum, i) => sum + i.totalAmount, 0) const totalPurchaseAmount = invoices .filter((i) => i.invoiceType === InvoiceTypeEnum.Purchase) .reduce((sum, i) => sum + i.totalAmount, 0) const totalUnpaidAmount = invoices .filter((i) => i.paymentStatus !== PaymentStatusEnum.Paid) .reduce((sum, i) => sum + i.remainingAmount, 0) // Overdue invoices const overdueInvoices = invoices.filter( (i) => i.paymentStatus !== PaymentStatusEnum.Paid && new Date(i.dueDate) < new Date(), ) // Payment status distribution const paymentDistribution = Object.values(PaymentStatusEnum).map((status) => ({ status, count: invoices.filter((i) => i.paymentStatus === status).length, amount: invoices .filter((i) => i.paymentStatus === status) .reduce((sum, i) => sum + i.totalAmount, 0), })) // Invoice type distribution const typeDistribution = Object.values(InvoiceTypeEnum).map((type) => ({ type, count: invoices.filter((i) => i.invoiceType === type).length, amount: invoices .filter((i) => i.invoiceType === type) .reduce((sum, i) => sum + i.totalAmount, 0), })) return (
{/* Header */}

Fatura Yönetimi

Alış ve satış faturaları yönetimi

{/* Stats Cards */}
{/* Distribution Charts */}

Fatura Türü Dağılımı

{typeDistribution.map(({ type, count, amount }) => (
{getInvoiceTypeText(type)}
{count} fatura {formatCurrency(amount)}
))}

Ödeme Durumu Dağılımı

{paymentDistribution.map(({ status, count, amount }) => (
{getPaymentStatusText(status)}
{count} fatura {formatCurrency(amount)}
))}
{/* Overdue Invoices Alert */} {overdueInvoices.length > 0 && (

Vadesi Geçmiş Faturalar

{overdueInvoices.length} adet fatura vadesi geçmiş durumda. Toplam tutar:{' '} {formatCurrency(overdueInvoices.reduce((sum, i) => sum + i.remainingAmount, 0))}

{overdueInvoices.slice(0, 3).map((invoice) => { const daysOverdue = Math.abs(getDaysUntilDue(invoice.dueDate)) return (
{invoice.invoiceNumber} - {invoice.currentAccount?.accountCode}
{daysOverdue} gün gecikme {formatCurrency(invoice.remainingAmount)}
) })}
)} {/* Filters */}
setSearchTerm(e.target.value)} className="w-full pl-10 pr-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" />
{/* Data Table */}
{filteredInvoices.length === 0 && (

Fatura bulunamadı

Yeni bir fatura ekleyin veya arama kriterlerinizi değiştirin.

)}
) } export default InvoiceManagement