107 lines
4.4 KiB
PHP
107 lines
4.4 KiB
PHP
<?php
|
|
/**
|
|
* TaxReportManager
|
|
*
|
|
* Generates VAT and withholding tax reports from journal lines
|
|
* tagged to tax accounts (output VAT, input VAT, WHT) in md_account.
|
|
* Matches accounts where account_name contains 'vat' or 'tax' (case-insensitive).
|
|
* Read-only — no writes.
|
|
*/
|
|
class TaxReportManager
|
|
{
|
|
private PDO $pdo;
|
|
private int $companyId;
|
|
|
|
public function __construct(PDO $pdo, int $company_id)
|
|
{
|
|
$this->pdo = $pdo;
|
|
$this->companyId = $company_id;
|
|
}
|
|
|
|
private function normalizeDate(string $date, bool $end_of_month = false): string
|
|
{
|
|
$date = trim($date);
|
|
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) {
|
|
return $date;
|
|
}
|
|
if (preg_match('/^\d{4}-\d{2}$/', $date)) {
|
|
return $end_of_month ? date('Y-m-t', strtotime($date . '-01')) : $date . '-01';
|
|
}
|
|
return date('Y-m-d');
|
|
}
|
|
|
|
// ── VAT Report ────────────────────────────────────────────────────────────
|
|
// Returns all GL lines for accounts whose account_category is 'sales_tax'
|
|
// or 'purchase_tax'. Pass $categories = [] to get both; pass one or more
|
|
// category strings to narrow (e.g. ['sales_tax']).
|
|
|
|
public function getVATReport(string $from_date, string $to_date, array $categories = [], int $dept_id = 0): array
|
|
{
|
|
$from_date = $this->normalizeDate($from_date);
|
|
$to_date = $this->normalizeDate($to_date, true);
|
|
|
|
$valid = ['sales_tax', 'purchase_tax'];
|
|
$cats = $categories ? array_intersect($categories, $valid) : $valid;
|
|
|
|
if (empty($cats)) {
|
|
return ['rows' => [], 'total_debit' => 0.0, 'total_credit' => 0.0,
|
|
'from_date' => $from_date, 'to_date' => $to_date,
|
|
'from_period' => substr($from_date, 0, 7), 'to_period' => substr($to_date, 0, 7)];
|
|
}
|
|
|
|
$placeholders = implode(',', array_map(fn($i) => ":cat$i", array_keys($cats)));
|
|
$params = [':cid' => $this->companyId, ':from_date' => $from_date, ':to_date' => $to_date];
|
|
foreach (array_values($cats) as $i => $c) { $params[":cat$i"] = $c; }
|
|
|
|
$sth = $this->pdo->prepare("
|
|
SELECT
|
|
g.id AS gl_id,
|
|
g.source_type,
|
|
COALESCE(g.reference, '') AS reference,
|
|
g.period,
|
|
COALESCE(g.journal_date, DATE(g.created_at)) AS entry_date,
|
|
a.account_code,
|
|
a.account_name,
|
|
a.account_category,
|
|
i.department_id,
|
|
COALESCE(d.dept_code, '') AS dept_code,
|
|
COALESCE(d.dept_name, '') AS dept_name,
|
|
i.debit,
|
|
i.credit,
|
|
COALESCE(i.description, '') AS description
|
|
FROM td_gl_item i
|
|
JOIN td_gl g ON g.id = i.gl_id AND g.company_id = i.company_id
|
|
JOIN md_account a ON a.company_id = i.company_id AND a.account_code = i.account_code
|
|
LEFT JOIN md_department d ON d.company_id = i.company_id AND d.id = i.department_id
|
|
WHERE i.company_id = :cid
|
|
AND COALESCE(g.journal_date, DATE(g.created_at)) BETWEEN :from_date AND :to_date
|
|
AND a.account_category IN ($placeholders)
|
|
AND (:dept_id = 0 OR i.department_id = :dept_id)
|
|
ORDER BY g.period ASC, g.journal_date ASC, g.id ASC
|
|
");
|
|
$params[':dept_id'] = $dept_id;
|
|
$sth->execute($params);
|
|
$rows = $sth->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
return [
|
|
'rows' => $rows,
|
|
'total_debit' => (float)array_sum(array_column($rows, 'debit')),
|
|
'total_credit' => (float)array_sum(array_column($rows, 'credit')),
|
|
'from_date' => $from_date,
|
|
'to_date' => $to_date,
|
|
'from_period' => substr($from_date, 0, 7),
|
|
'to_period' => substr($to_date, 0, 7),
|
|
];
|
|
}
|
|
|
|
public function getOutputVAT(string $from_period, string $to_period, int $dept_id = 0): array
|
|
{
|
|
return $this->getVATReport($from_period, $to_period, ['sales_tax'], $dept_id);
|
|
}
|
|
|
|
public function getInputVAT(string $from_period, string $to_period, int $dept_id = 0): array
|
|
{
|
|
return $this->getVATReport($from_period, $to_period, ['purchase_tax'], $dept_id);
|
|
}
|
|
}
|