کانال نوحه و مداحی ناب

API های کامل برای مدیریت سیستم حسابداری - بخش دوم

4. API مدیریت فاکتورهای فروش (sales_api.php)

php
<?php
include 'config.php';

$method = $_SERVER['REQUEST_METHOD'];
$conn = getDBConnection();
$userId = authenticateUser();

switch ($method) {
    case 'GET':
        getSalesInvoices();
        break;
    case 'POST':
        createSalesInvoice();
        break;
    case 'PUT':
        updateSalesInvoice();
        break;
}

function getSalesInvoices() {
    global $conn, $userId;
    
    $companyId = $_GET['company_id'] ?? 1;
    $invoiceId = $_GET['invoice_id'] ?? null;
    $customerId = $_GET['customer_id'] ?? null;
    $status = $_GET['status'] ?? null;
    $startDate = $_GET['start_date'] ?? null;
    $endDate = $_GET['end_date'] ?? null;
    
    if (!checkPermission($userId, 'sales', 'view')) {
        sendResponse(false, null, 'Permission denied', 403);
    }
    
    $query = "
        SELECT 
            si.*,
            c.CustomerCode, c.CustomerName,
            curr.CurrencyCode,
            u.FirstName as CreatedByFirstName, u.LastName as CreatedByLastName,
            DATEDIFF(si.DueDate, CURDATE()) as DaysToDue,
            CASE 
                WHEN si.Status = 'Issued' AND si.DueDate < CURDATE() THEN 'Overdue'
                ELSE si.Status
            END as InvoiceStatus
        FROM SalesInvoices si
        INNER JOIN Customers c ON si.CustomerID = c.CustomerID
        INNER JOIN Currencies curr ON si.CurrencyID = curr.CurrencyID
        INNER JOIN Users u ON si.CreatedBy = u.UserID
        WHERE si.CompanyID = ?
    ";
    
    $params = [$companyId];
    $types = "i";
    
    if ($invoiceId) {
        $query .= " AND si.InvoiceID = ?";
        $params[] = $invoiceId;
        $types .= "i";
    }
    
    if ($customerId) {
        $query .= " AND si.CustomerID = ?";
        $params[] = $customerId;
        $types .= "i";
    }
    
    if ($status) {
        $query .= " AND si.Status = ?";
        $params[] = $status;
        $types .= "s";
    }
    
    if ($startDate) {
        $query .= " AND si.InvoiceDate >= ?";
        $params[] = $startDate;
        $types .= "s";
    }
    
    if ($endDate) {
        $query .= " AND si.InvoiceDate <= ?";
        $params[] = $endDate;
        $types .= "s";
    }
    
    $query .= " ORDER BY si.InvoiceDate DESC, si.InvoiceID DESC";
    
    $stmt = $conn->prepare($query);
    $stmt->bind_param($types, ...$params);
    $stmt->execute();
    $result = $stmt->get_result();
    
    $invoices = [];
    while ($row = $result->fetch_assoc()) {
        // گرفتن اقلام فاکتور
        $itemsQuery = "
            SELECT 
                sii.*,
                p.ProductCode, p.ProductName,
                a_inv.AccountCode as InventoryAccountCode,
                a_sales.AccountCode as SalesAccountCode
            FROM SalesInvoiceItems sii
            LEFT JOIN Products p ON sii.ProductID = p.ProductID
            LEFT JOIN ChartOfAccounts a_inv ON sii.InventoryAccountID = a_inv.AccountID
            LEFT JOIN ChartOfAccounts a_sales ON sii.SalesAccountID = a_sales.AccountID
            WHERE sii.InvoiceID = ?
        ";
        $itemsStmt = $conn->prepare($itemsQuery);
        $itemsStmt->bind_param("i", $row['InvoiceID']);
        $itemsStmt->execute();
        $itemsResult = $itemsStmt->get_result();
        
        $row['items'] = [];
        while ($item = $itemsResult->fetch_assoc()) {
            $row['items'][] = $item;
        }
        
        $invoices[] = $row;
    }
    
    sendResponse(true, $invoices, 'Sales invoices retrieved successfully');
}

function createSalesInvoice() {
    global $conn, $userId;
    
    $data = json_decode(file_get_contents("php://input"), true);
    
    if (!checkPermission($userId, 'sales', 'create')) {
        sendResponse(false, null, 'Permission denied', 403);
    }
    
    $required = ['CompanyID', 'InvoiceDate', 'CustomerID', 'CurrencyID', 'items'];
    foreach ($required as $field) {
        if (!isset($data[$field]) || empty($data[$field])) {
            sendResponse(false, null, "Field $field is required", 400);
        }
    }
    
    $conn->begin_transaction();
    
    try {
        // تولید شماره فاکتور
        $invoiceNumber = generateInvoiceNumber($data['CompanyID']);
        
        // محاسبه مبالغ
        $subTotal = 0;
        $taxAmount = 0;
        $discountAmount = 0;
        
        foreach ($data['items'] as $item) {
            $lineTotal = ($item['Quantity'] * $item['UnitPrice']) - ($item['DiscountAmount'] ?? 0);
            $subTotal += $lineTotal;
            $taxAmount += $item['TaxAmount'] ?? 0;
            $discountAmount += $item['DiscountAmount'] ?? 0;
        }
        
        $totalAmount = $subTotal + $taxAmount;
        
        // ایجاد فاکتور
        $invoiceQuery = "
            INSERT INTO SalesInvoices (
                CompanyID, InvoiceNumber, InvoiceDate, CustomerID, CurrencyID, ExchangeRate,
                SubTotal, TaxAmount, DiscountAmount, TotalAmount, DueDate, PaymentTerms,
                ReceivableAccountID, SalesAccountID, TaxAccountID, ProjectID, Notes, CreatedBy
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
        ";
        
        $dueDate = $data['DueDate'] ?? date('Y-m-d', strtotime('+30 days'));
        
        $invoiceStmt = $conn->prepare($invoiceQuery);
        $invoiceStmt->bind_param(
            "isssiddddddssiissi",
            $data['CompanyID'], $invoiceNumber, $data['InvoiceDate'], $data['CustomerID'],
            $data['CurrencyID'], $data['ExchangeRate'] ?? 1, $subTotal, $taxAmount,
            $discountAmount, $totalAmount, $dueDate, $data['PaymentTerms'] ?? 'Net30',
            $data['ReceivableAccountID'] ?? null, $data['SalesAccountID'] ?? null,
            $data['TaxAccountID'] ?? null, $data['ProjectID'] ?? null,
            $data['Notes'] ?? null, $userId
        );
        $invoiceStmt->execute();
        $invoiceId = $invoiceStmt->insert_id;
        
        // ایجاد اقلام فاکتور
        foreach ($data['items'] as $item) {
            $lineTotal = ($item['Quantity'] * $item['UnitPrice']) - ($item['DiscountAmount'] ?? 0);
            
            $itemQuery = "
                INSERT INTO SalesInvoiceItems (
                    InvoiceID, ProductID, Description, Quantity, UnitPrice,
                    DiscountRate, DiscountAmount, TaxRate, TaxAmount, LineTotal,
                    InventoryAccountID, COGSAccountID, SalesAccountID
                ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            ";
            
            $itemStmt = $conn->prepare($itemQuery);
            $itemStmt->bind_param(
                "iisdddddddiii",
                $invoiceId, $item['ProductID'] ?? null, $item['Description'] ?? null,
                $item['Quantity'], $item['UnitPrice'], $item['DiscountRate'] ?? 0,
                $item['DiscountAmount'] ?? 0, $item['TaxRate'] ?? 0,
                $item['TaxAmount'] ?? 0, $lineTotal, $item['InventoryAccountID'] ?? null,
                $item['COGSAccountID'] ?? null, $item['SalesAccountID'] ?? null
            );
            $itemStmt->execute();
        }
        
        // ایجاد سند حسابداری خودکار اگر وضعیت Issued باشد
        if ($data['Status'] === 'Issued') {
            createVoucherFromInvoice($invoiceId, $data['CompanyID'], $userId);
        }
        
        $conn->commit();
        
        logAudit($userId, $data['CompanyID'], 'CREATE', 'SalesInvoices', $invoiceId, 'Sales invoice created: ' . $invoiceNumber);
        
        sendResponse(true, [
            'invoice_id' => $invoiceId,
            'invoice_number' => $invoiceNumber
        ], 'Sales invoice created successfully', 201);
        
    } catch (Exception $e) {
        $conn->rollback();
        sendResponse(false, null, 'Failed to create sales invoice: ' . $e->getMessage(), 500);
    }
}

function generateInvoiceNumber($companyId) {
    global $conn;
    
    $year = date('Y');
    $month = date('m');
    
    $query = "
        SELECT COUNT(*) as count 
        FROM SalesInvoices 
        WHERE CompanyID = ? AND YEAR(InvoiceDate) = ? AND MONTH(InvoiceDate) = ?
    ";
    $stmt = $conn->prepare($query);
    $stmt->bind_param("iii", $companyId, $year, $month);
    $stmt->execute();
    $result = $stmt->get_result();
    $count = $result->fetch_assoc()['count'] + 1;
    
    return 'INV' . $year . $month . str_pad($count, 4, '0', STR_PAD_LEFT);
}

function createVoucherFromInvoice($invoiceId, $companyId, $userId) {
    global $conn;
    
    // گرفتن اطلاعات فاکتور
    $invoiceQuery = "
        SELECT * FROM SalesInvoices WHERE InvoiceID = ?
    ";
    $invoiceStmt = $conn->prepare($invoiceQuery);
    $invoiceStmt->bind_param("i", $invoiceId);
    $invoiceStmt->execute();
    $invoice = $invoiceStmt->get_result()->fetch_assoc();
    
    // پیدا کردن دوره مالی
    $periodQuery = "
        SELECT PeriodID FROM FiscalPeriods 
        WHERE CompanyID = ? AND ? BETWEEN StartDate AND EndDate AND Status = 'Open'
    ";
    $periodStmt = $conn->prepare($periodQuery);
    $periodStmt->bind_param("is", $companyId, $invoice['InvoiceDate']);
    $periodStmt->execute();
    $periodResult = $periodStmt->get_result();
    
    if ($periodResult->num_rows === 0) {
        throw new Exception('No open fiscal period found for invoice date');
    }
    
    $period = $periodResult->fetch_assoc();
    
    // ایجاد سند حسابداری
    $voucherNumber = generateVoucherNumber($companyId, 'Sales');
    
    $voucherQuery = "
        INSERT INTO AccountingVouchers (
            CompanyID, VoucherNumber, VoucherDate, VoucherType, PeriodID,
            Description, TotalDebit, TotalCredit, CurrencyID, ExchangeRate, PreparedBy, Status
        ) VALUES (?, ?, ?, 'Sales', ?, ?, ?, ?, ?, ?, ?, 'Posted')
    ";
    
    $voucherStmt = $conn->prepare($voucherQuery);
    $voucherStmt->bind_param(
        "issssdddsi",
        $companyId, $voucherNumber, $invoice['InvoiceDate'], $period['PeriodID'],
        'فاکتور فروش ' . $invoice['InvoiceNumber'], $invoice['TotalAmount'], $invoice['TotalAmount'],
        $invoice['CurrencyID'], $invoice['ExchangeRate'], $userId
    );
    $voucherStmt->execute();
    $voucherId = $voucherStmt->insert_id;
    
    // ایجاد سطرهای سند
    // بدهکار: حساب دریافتنی
    if ($invoice['ReceivableAccountID']) {
        $debitItemQuery = "
            INSERT INTO VoucherItems (
                VoucherID, AccountID, Description, DebitAmount, CreditAmount,
                CurrencyID, ExchangeRate, CustomerID, ReferenceType, ReferenceID
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'Invoice', ?)
        ";
        $debitStmt = $conn->prepare($debitItemQuery);
        $debitStmt->bind_param(
            "iisdddsii",
            $voucherId, $invoice['ReceivableAccountID'], 'بدهکار بابت فاکتور فروش',
            $invoice['TotalAmount'], 0, $invoice['CurrencyID'], $invoice['ExchangeRate'],
            $invoice['CustomerID'], $invoiceId
        );
        $debitStmt->execute();
    }
    
    // بستانکار: حساب فروش
    if ($invoice['SalesAccountID']) {
        $creditItemQuery = "
            INSERT INTO VoucherItems (
                VoucherID, AccountID, Description, DebitAmount, CreditAmount,
                CurrencyID, ExchangeRate, ReferenceType, ReferenceID
            ) VALUES (?, ?, ?, ?, ?, ?, ?, 'Invoice', ?)
        ";
        $creditStmt = $conn->prepare($creditItemQuery);
        $creditStmt->bind_param(
            "iisdddsi",
            $voucherId, $invoice['SalesAccountID'], 'فروش محصولات',
            0, $invoice['SubTotal'], $invoice['CurrencyID'], $invoice['ExchangeRate'], $invoiceId
        );
        $creditStmt->execute();
    }
    
    // بستانکار: حساب مالیات
    if ($invoice['TaxAmount'] > 0 && $invoice['TaxAccountID']) {
        $taxItemQuery = "
            INSERT INTO VoucherItems (
                VoucherID, AccountID, Description, DebitAmount, CreditAmount,
                CurrencyID, ExchangeRate, ReferenceType, ReferenceID
            ) VALUES (?, ?, ?, ?, ?, ?, ?, 'Invoice', ?)
        ";
        $taxStmt = $conn->prepare($taxItemQuery);
        $taxStmt->bind_param(
            "iisdddsi",
            $voucherId, $invoice['TaxAccountID'], 'مالیات بر ارزش افزوده',
            0, $invoice['TaxAmount'], $invoice['CurrencyID'], $invoice['ExchangeRate'], $invoiceId
        );
        $taxStmt->execute();
    }
    
    return $voucherId;
}
?>

5. API گزارشات مالی (reports_api.php)

php
Copy
Download
<?php
include 'config.php';

$method = $_SERVER['REQUEST_METHOD'];

if ($method == 'GET') {
    $reportType = $_GET['type'] ?? 'trial_balance';
    $userId = authenticateUser();
    
    if (!checkPermission($userId, 'reports', 'view')) {
        sendResponse(false, null, 'Permission denied', 403);
    }
    
    switch ($reportType) {
        case 'trial_balance':
            getTrialBalance();
            break;
        case 'balance_sheet':
            getBalanceSheet();
            break;
        case 'income_statement':
            getIncomeStatement();
            break;
        case 'general_ledger':
            getGeneralLedger();
            break;
        case 'account_statement':
            getAccountStatement();
            break;
        default:
            sendResponse(false, null, 'Invalid report type', 400);
    }
}

function getTrialBalance() {
    global $conn;
    
    $companyId = $_GET['company_id'] ?? 1;
    $periodId = $_GET['period_id'] ?? null;
    $asOfDate = $_GET['as_of_date'] ?? date('Y-m-d');
    
    if (!$periodId) {
        // پیدا کردن دوره بر اساس تاریخ
        $periodQuery = "
            SELECT PeriodID FROM FiscalPeriods 
            WHERE CompanyID = ? AND ? BETWEEN StartDate AND EndDate
        ";
        $periodStmt = $conn->prepare($periodQuery);
        $periodStmt->bind_param("is", $companyId, $asOfDate);
        $periodStmt->execute();
        $periodResult = $periodStmt->get_result();
        
        if ($periodResult->num_rows === 0) {
            sendResponse(false, null, 'No fiscal period found for the specified date', 400);
        }
        
        $period = $periodResult->fetch_assoc();
        $periodId = $period['PeriodID'];
    }
    
    $query = "
        SELECT 
            a.AccountID,
            a.AccountCode,
            a.AccountName,
            a.AccountType,
            a.NormalBalance,
            COALESCE(SUM(CASE WHEN vi.DebitAmount > 0 THEN vi.BaseDebitAmount ELSE 0 END), 0) as TotalDebit,
            COALESCE(SUM(CASE WHEN vi.CreditAmount > 0 THEN vi.BaseCreditAmount ELSE 0 END), 0) as TotalCredit,
            CASE 
                WHEN a.NormalBalance = 'Debit' THEN 
                    COALESCE(SUM(vi.BaseDebitAmount - vi.BaseCreditAmount), 0)
                ELSE 
                    COALESCE(SUM(vi.BaseCreditAmount - vi.BaseDebitAmount), 0)
            END as Balance
        FROM ChartOfAccounts a
        LEFT JOIN VoucherItems vi ON a.AccountID = vi.AccountID
        LEFT JOIN AccountingVouchers v ON vi.VoucherID = v.VoucherID
        WHERE a.CompanyID = ? AND a.IsActive = 1 
        AND v.PeriodID = ? AND v.Status = 'Posted'
        GROUP BY a.AccountID, a.AccountCode, a.AccountName, a.AccountType, a.NormalBalance
        HAVING TotalDebit != 0 OR TotalCredit != 0
        ORDER BY a.AccountCode
    ";
    
    $stmt = $conn->prepare($query);
    $stmt->bind_param("ii", $companyId, $periodId);
    $stmt->execute();
    $result = $stmt->get_result();
    
    $trialBalance = [];
    $totalDebit = 0;
    $totalCredit = 0;
    
    while ($row = $result->fetch_assoc()) {
        $trialBalance[] = $row;
        $totalDebit += $row['TotalDebit'];
        $totalCredit += $row['TotalCredit'];
    }
    
    sendResponse(true, [
        'trial_balance' => $trialBalance,
        'totals' => [
            'total_debit' => $totalDebit,
            'total_credit' => $totalCredit,
            'difference' => abs($totalDebit - $totalCredit)
        ],
        'period_id' => $periodId,
        'as_of_date' => $asOfDate
    ], 'Trial balance report generated successfully');
}

function getBalanceSheet() {
    global $conn;
    
    $companyId = $_GET['company_id'] ?? 1;
    $asOfDate = $_GET['as_of_date'] ?? date('Y-m-d');
    
    // پیدا کردن دوره
    $periodQuery = "
        SELECT PeriodID FROM FiscalPeriods 
        WHERE CompanyID = ? AND ? BETWEEN StartDate AND EndDate
    ";
    $periodStmt = $conn->prepare($periodQuery);
    $periodStmt->bind_param("is", $companyId, $asOfDate);
    $periodStmt->execute();
    $periodResult = $periodStmt->get_result();
    
    if ($periodResult->num_rows === 0) {
        sendResponse(false, null, 'No fiscal period found for the specified date', 400);
    }
    
    $period = $periodResult->fetch_assoc();
    $periodId = $period['PeriodID'];
    
    // دارایی‌ها
    $assetsQuery = "
        SELECT 
            a.AccountCode,
            a.AccountName,
            SUM(vi.BaseDebitAmount - vi.BaseCreditAmount) as Balance
        FROM ChartOfAccounts a
        LEFT JOIN VoucherItems vi ON a.AccountID = vi.AccountID
        LEFT JOIN AccountingVouchers v ON vi.VoucherID = v.VoucherID
        WHERE a.CompanyID = ? AND a.AccountType = 'Asset' 
        AND v.PeriodID = ? AND v.Status = 'Posted'
        GROUP BY a.AccountID
        HAVING Balance != 0
        ORDER BY a.AccountCode
    ";
    
    $assetsStmt = $conn->prepare($assetsQuery);
    $assetsStmt->bind_param("ii", $companyId, $periodId);
    $assetsStmt->execute();
    $assetsResult = $assetsStmt->get_result();
    
    $assets = [];
    $totalAssets = 0;
    
    while ($row = $assetsResult->fetch_assoc()) {
        $assets[] = $row;
        $totalAssets += $row['Balance'];
    }
    
    // بدهی‌ها
    $liabilitiesQuery = "
        SELECT 
            a.AccountCode,
            a.AccountName,
            SUM(vi.BaseCreditAmount - vi.BaseDebitAmount) as Balance
        FROM ChartOfAccounts a
        LEFT JOIN VoucherItems vi ON a.AccountID = vi.AccountID
        LEFT JOIN AccountingVouchers v ON vi.VoucherID = v.VoucherID
        WHERE a.CompanyID = ? AND a.AccountType = 'Liability' 
        AND v.PeriodID = ? AND v.Status = 'Posted'
        GROUP BY a.AccountID
        HAVING Balance != 0
        ORDER BY a.AccountCode
    ";
    
    $liabilitiesStmt = $conn->prepare($liabilitiesQuery);
    $liabilitiesStmt->bind_param("ii", $companyId, $periodId);
    $liabilitiesStmt->execute();
    $liabilitiesResult = $liabilitiesStmt->get_result();
    
    $liabilities = [];
    $totalLiabilities = 0;
    
    while ($row = $liabilitiesResult->fetch_assoc()) {
        $liabilities[] = $row;
        $totalLiabilities += $row['Balance'];
    }
    
    // حقوق صاحبان سهام
    $equityQuery = "
        SELECT 
            a.AccountCode,
            a.AccountName,
            SUM(vi.BaseCreditAmount - vi.BaseDebitAmount) as Balance
        FROM ChartOfAccounts a
        LEFT JOIN VoucherItems vi ON a.AccountID = vi.AccountID
        LEFT JOIN AccountingVouchers v ON vi.VoucherID = v.VoucherID
        WHERE a.CompanyID = ? AND a.AccountType = 'Equity' 
        AND v.PeriodID = ? AND v.Status = 'Posted'
        GROUP BY a.AccountID
        HAVING Balance != 0
        ORDER BY a.AccountCode
    ";
    
    $equityStmt = $conn->prepare($equityQuery);
    $equityStmt->bind_param("ii", $companyId, $periodId);
    $equityStmt->execute();
    $equityResult = $equityStmt->get_result();
    
    $equity = [];
    $totalEquity = 0;
    
    while ($row = $equityResult->fetch_assoc()) {
        $equity[] = $row;
        $totalEquity += $row['Balance'];
    }
    
    // جمع کل بدهی و حقوق صاحبان سهام
    $totalLiabilitiesEquity = $totalLiabilities + $totalEquity;
    
    sendResponse(true, [
        'assets' => [
            'items' => $assets,
            'total' => $totalAssets
        ],
        'liabilities' => [
            'items' => $liabilities,
            'total' => $totalLiabilities
        ],
        'equity' => [
            'items' => $equity,
            'total' => $totalEquity
        ],
        'totals' => [
            'total_assets' => $totalAssets,
            'total_liabilities_equity' => $totalLiabilitiesEquity,
            'balance_check' => $totalAssets == $totalLiabilitiesEquity
        ],
        'as_of_date' => $asOfDate
    ], 'Balance sheet generated successfully');
}

function getIncomeStatement() {
    global $conn;
    
    $companyId = $_GET['company_id'] ?? 1;
    $startDate = $_GET['start_date'] ?? date('Y-m-01');
    $endDate = $_GET['end_date'] ?? date('Y-m-d');
    
    // درآمدها
    $revenueQuery = "
        SELECT 
            a.AccountCode,
            a.AccountName,
            SUM(vi.BaseCreditAmount - vi.BaseDebitAmount) as Amount
        FROM ChartOfAccounts a
        LEFT JOIN VoucherItems vi ON a.AccountID = vi.AccountID
        LEFT JOIN AccountingVouchers v ON vi.VoucherID = v.VoucherID
        WHERE a.CompanyID = ? AND a.AccountType = 'Income' 
        AND v.VoucherDate BETWEEN ? AND ? AND v.Status = 'Posted'
        GROUP BY a.AccountID
        HAVING Amount != 0
        ORDER BY a.AccountCode
    ";
    
    $revenueStmt = $conn->prepare($revenueQuery);
    $revenueStmt->bind_param("iss", $companyId, $startDate, $endDate);
    $revenueStmt->execute();
    $revenueResult = $revenueStmt->get_result();
    
    $revenues = [];
    $totalRevenue = 0;
    
    while ($row = $revenueResult->fetch_assoc()) {
        $revenues[] = $row;
        $totalRevenue += $row['Amount'];
    }
    
    // هزینه‌ها
    $expenseQuery = "
        SELECT 
            a.AccountCode,
            a.AccountName,
            SUM(vi.BaseDebitAmount - vi.BaseCreditAmount) as Amount
        FROM ChartOfAccounts a
        LEFT JOIN VoucherItems vi ON a.AccountID = vi.AccountID
        LEFT JOIN AccountingVouchers v ON vi.VoucherID = v.VoucherID
        WHERE a.CompanyID = ? AND a.AccountType = 'Expense' 
        AND v.VoucherDate BETWEEN ? AND ? AND v.Status = 'Posted'
        GROUP BY a.AccountID
        HAVING Amount != 0
        ORDER BY a.AccountCode
    ";
    
    $expenseStmt = $conn->prepare($expenseQuery);
    $expenseStmt->bind_param("iss", $companyId, $startDate, $endDate);
    $expenseStmt->execute();
    $expenseResult = $expenseStmt->get_result();
    
    $expenses = [];
    $totalExpense = 0;
    
    while ($row = $expenseResult->fetch_assoc()) {
        $expenses[] = $row;
        $totalExpense += $row['Amount'];
    }
    
    $netIncome = $totalRevenue - $totalExpense;
    
    sendResponse(true, [
        'revenues' => [
            'items' => $revenues,
            'total' => $totalRevenue
        ],
        'expenses' => [
            'items' => $expenses,
            'total' => $totalExpense
        ],
        'net_income' => $netIncome,
        'period' => [
            'start_date' => $startDate,
            'end_date' => $endDate
        ]
    ], 'Income statement generated successfully');
}
?>

6. فایل روتر اصلی (router.php)

php
<?php
include 'config.php';

$request_uri = $_SERVER['REQUEST_URI'];
$method = $_SERVER['REQUEST_METHOD'];
$path = parse_url($request_uri, PHP_URL_PATH);

// مسیرهای API
$routes = [
    'GET' => [
        '/api/accounts' => 'accounts_api.php',
        '/api/vouchers' => 'vouchers_api.php',
        '/api/sales' => 'sales_api.php',
        '/api/purchases' => 'purchases_api.php',
        '/api/customers' => 'customers_api.php',
        '/api/suppliers' => 'suppliers_api.php',
        '/api/reports' => 'reports_api.php',
        '/api/currencies' => 'currencies_api.php',
        '/api/periods' => 'periods_api.php'
    ],
    'POST' => [
        '/api/accounts' => 'accounts_api.php',
        '/api/vouchers' => 'vouchers_api.php',
        '/api/sales' => 'sales_api.php',
        '/api/purchases' => 'purchases_api.php',
        '/api/vouchers/post' => 'vouchers_api.php?action=post',
        '/api/vouchers/cancel' => 'vouchers_api.php?action=cancel'
    ],
    'PUT' => [
        '/api/accounts' => 'accounts_api.php',
        '/api/vouchers' => 'vouchers_api.php',
        '/api/sales' => 'sales_api.php'
    ],
    'DELETE' => [
        '/api/accounts' => 'accounts_api.php',
        '/api/vouchers' => 'vouchers_api.php'
    ]
];

// پیدا کردن مسیر منطبق
$matched = false;
foreach ($routes[$method] as $route => $file) {
    if (strpos($path, $route) === 0) {
        include($file);
        $matched = true;
        break;
    }
}

if (!$matched) {
    sendResponse(false, null, 'Endpoint not found', 404);
}
?>

7. مثال استفاده از API ها

javascript
// گرفتن chart of accounts
fetch('/api/accounts?company_id=1')
    .then(response => response.json())
    .then(data => console.log(data));

// ایجاد سند حسابداری
fetch('/api/vouchers', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer your-token-here'
    },
    body: JSON.stringify({
        CompanyID: 1,
        VoucherDate: '2024-01-15',
        VoucherType: 'General',
        PeriodID: 1,
        CurrencyID: 1,
        Description: 'سند آزمایشی',
        items: [
            {
                AccountID: 10101,
                Description: 'بدهکار',
                DebitAmount: 1000000,
                CreditAmount: 0,
                LineNumber: 1
            },
            {
                AccountID: 10102,
                Description: 'بستانکار',
                DebitAmount: 0,
                CreditAmount: 1000000,
                LineNumber: 2
            }
        ]
    })
});

// ایجاد فاکتور فروش
fetch('/api/sales', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer your-token-here'
    },
    body: JSON.stringify({
        CompanyID: 1,
        InvoiceDate: '2024-01-15',
        CustomerID: 1,
        CurrencyID: 1,
        Status: 'Issued',
        items: [
            {
                ProductID: 1,
                Description: 'محصول آزمایشی',
                Quantity: 10,
                UnitPrice: 50000,
                TaxRate: 9,
                DiscountRate: 5
            }
        ]
    })
});

// گرفتن تراز آزمایشی
fetch('/api/reports?type=trial_balance&company_id=1&period_id=1')
    .then(response => response.json())
    .then(data => console.log(data));

// گرفتن صورت سود و زیان
fetch('/api/reports?type=income_statement&company_id=1&start_date=2024-01-01&end_date=2024-01-31')
    .then(response => response.json())
    .then(data => console.log(data));

این API های کامل تمام نیازهای اصلی یک سیستم حسابداری جامع را پوشش می‌دهند و می‌توانند بر اساس نیازهای خاص سازمان توسعه داده شوند.

 
 
کانال نوحه و مداحی ناب

نظرات (۰)
هیچ نظری هنوز ثبت نشده است

ارسال نظر

ارسال نظر آزاد است، اما اگر قبلا در بیان ثبت نام کرده اید می توانید ابتدا وارد شوید.
شما میتوانید از این تگهای html استفاده کنید:
<b> یا <strong>، <em> یا <i>، <u>، <strike> یا <s>، <sup>، <sub>، <blockquote>، <code>، <pre>، <hr>، <br>، <p>، <a href="" title="">، <span style="">، <div align="">
تجدید کد امنیتی