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< InvoiceStatusEnum | "all" >("all"); const [selectedPaymentStatus, setSelectedPaymentStatus] = useState< PaymentStatusEnum | "all" >("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;