db = $db; $this->entity = $entity; } /** * Fetch declaration by ID * * @param int $id Declaration ID * @return int 1 if found, 0 if not found, -1 if error */ public function fetch($id) { $sql = "SELECT * FROM " . MAIN_DB_PREFIX . "declarationtva_declarations WHERE rowid = " . (int)$id . " AND entity = " . $this->entity; $result = $this->db->query($sql); if ($result) { $obj = $this->db->fetch_object($result); if ($obj) { $this->rowid = $obj->rowid; $this->period_id = $obj->period_id; $this->declaration_number = $obj->declaration_number; $this->declaration_name = $obj->declaration_name; $this->start_date = $obj->start_date; $this->end_date = $obj->end_date; $this->status = $obj->status; $this->created_date = $obj->created_date; return 1; } } return 0; } /** * Create a new declaration for a period * * @param int $period_id Period ID * @return int Declaration ID or -1 if error */ public function createDeclaration($period_id) { global $user; $this->db->begin(); // Get period information $period = $this->getPeriod($period_id); if (!$period) { $this->error = "Period not found"; $this->db->rollback(); return -1; } // Generate declaration number $declaration_number = $this->generateDeclarationNumber($period); // Create declaration record $sql = "INSERT INTO " . MAIN_DB_PREFIX . "declarationtva_declarations (entity, period_id, declaration_number, status, created_date) VALUES (" . $this->entity . ", " . $period_id . ", '" . $declaration_number . "', 'draft', NOW())"; $result = $this->db->query($sql); if (!$result) { $this->error = "Error creating declaration: " . $this->db->lasterror(); $this->db->rollback(); return -1; } $declaration_id = $this->db->last_insert_id(MAIN_DB_PREFIX . "declarationtva_declarations"); // Calculate CA-3 amounts $this->calculateCA3Amounts($declaration_id, $period); $this->db->commit(); return $declaration_id; } /** * Create a new declaration with specific dates * * @param string $start_date Start date (YYYY-MM-DD) * @param string $end_date End date (YYYY-MM-DD) * @param string $declaration_name Declaration name * @return int Declaration ID or -1 if error */ public function createDeclarationWithDates($start_date, $end_date, $declaration_name = '') { global $user; $this->db->begin(); // Generate declaration number $declaration_number = $this->generateDeclarationNumberFromDates($start_date, $end_date); // Create declaration record $sql = "INSERT INTO " . MAIN_DB_PREFIX . "declarationtva_declarations (entity, period_id, declaration_number, declaration_name, start_date, end_date, status, created_date) VALUES (" . $this->entity . ", 0, '" . $declaration_number . "', '" . $this->db->escape($declaration_name) . "', '" . $start_date . "', '" . $end_date . "', 'draft', NOW())"; $result = $this->db->query($sql); if (!$result) { $this->error = "Error creating declaration: " . $this->db->lasterror(); $this->db->rollback(); return -1; } $declaration_id = $this->db->last_insert_id(MAIN_DB_PREFIX . "declarationtva_declarations"); // Calculate CA-3 amounts $period = array('start_date' => $start_date, 'end_date' => $end_date); $this->calculateCA3Amounts($declaration_id, $period); $this->db->commit(); return $declaration_id; } /** * Calculate CA-3 amounts for a declaration * * @param int $declaration_id Declaration ID * @param array $period Period information * @return bool Success */ public function calculateCA3Amounts($declaration_id, $period) { error_log("DeclarationTVA: Starting calculation for declaration $declaration_id"); error_log("DeclarationTVA: Period: " . $period['start_date'] . " to " . $period['end_date']); // Get account mappings $mappings = $this->getAccountMappings(); error_log("DeclarationTVA: Found " . count($mappings) . " account mappings"); $total_vat_collected = 0; $total_vat_deductible = 0; // Process each CA-3 line foreach ($mappings as $mapping) { error_log("DeclarationTVA: Processing mapping: " . $mapping['ca3_line'] . " -> " . $mapping['account_code']); $amounts = $this->getAccountAmounts($mapping['account_code'], $period['start_date'], $period['end_date']); // Create CA-3 line record $this->createCA3Line($declaration_id, $mapping['ca3_line'], $mapping['account_label'], $amounts); // Update totals if (in_array($mapping['ca3_line'], ['A1', 'A2', 'B1', 'B2', 'B3', 'B4', '17'])) { $total_vat_collected += $amounts['vat_amount']; } elseif (in_array($mapping['ca3_line'], ['20', '21'])) { $total_vat_deductible += $amounts['vat_amount']; } } error_log("DeclarationTVA: Totals - Collected: $total_vat_collected, Deductible: $total_vat_deductible"); // Calculate net amounts $net_vat_due = $total_vat_collected - $total_vat_deductible; $vat_credit = $net_vat_due < 0 ? abs($net_vat_due) : 0; $net_vat_due = $net_vat_due > 0 ? $net_vat_due : 0; // Update declaration totals $this->updateDeclarationTotals($declaration_id, $total_vat_collected, $total_vat_deductible, $net_vat_due, $vat_credit); return true; } /** * Get account amounts for a period * * @param string $account_code Account code * @param string $start_date Start date * @param string $end_date End date * @return array Amounts (base_amount, vat_amount, total_amount) */ public function getAccountAmounts($account_code, $start_date, $end_date) { // Query Dolibarr accounting entries $sql = "SELECT SUM(debit) as total_debit, SUM(credit) as total_credit FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping WHERE account_number = '" . $this->db->escape($account_code) . "' AND doc_date >= '" . $this->db->escape($start_date) . "' AND doc_date <= '" . $this->db->escape($end_date) . "'"; // Debug: Log the query error_log("DeclarationTVA: Querying account $account_code from $start_date to $end_date"); error_log("DeclarationTVA: SQL: $sql"); $result = $this->db->query($sql); if ($result && $this->db->num_rows($result) > 0) { $obj = $this->db->fetch_object($result); $total_amount = $obj->total_debit - $obj->total_credit; error_log("DeclarationTVA: Found amounts for $account_code: debit=$obj->total_debit, credit=$obj->total_credit, net=$total_amount"); return array( 'base_amount' => $total_amount, 'vat_amount' => $total_amount, 'total_amount' => $total_amount ); } error_log("DeclarationTVA: No data found for account $account_code"); return array('base_amount' => 0, 'vat_amount' => 0, 'total_amount' => 0); } /** * Create CA-3 line record * * @param int $declaration_id Declaration ID * @param string $ca3_line CA-3 line code * @param string $line_label Line label * @param array $amounts Amounts array * @return bool Success */ public function createCA3Line($declaration_id, $ca3_line, $line_label, $amounts) { $sql = "INSERT INTO " . MAIN_DB_PREFIX . "declarationtva_ca3_lines (declaration_id, ca3_line, line_label, base_amount, vat_amount, total_amount, created_date) VALUES (" . $declaration_id . ", '" . $this->db->escape($ca3_line) . "', '" . $this->db->escape($line_label) . "', " . $amounts['base_amount'] . ", " . $amounts['vat_amount'] . ", " . $amounts['total_amount'] . ", NOW())"; $result = $this->db->query($sql); return $result !== false; } /** * Update declaration totals * * @param int $declaration_id Declaration ID * @param float $total_vat_collected Total VAT collected * @param float $total_vat_deductible Total VAT deductible * @param float $net_vat_due Net VAT due * @param float $vat_credit VAT credit * @return bool Success */ public function updateDeclarationTotals($declaration_id, $total_vat_collected, $total_vat_deductible, $net_vat_due, $vat_credit) { $sql = "UPDATE " . MAIN_DB_PREFIX . "declarationtva_declarations SET total_vat_collected = " . $total_vat_collected . ", total_vat_deductible = " . $total_vat_deductible . ", net_vat_due = " . $net_vat_due . ", vat_credit = " . $vat_credit . " WHERE rowid = " . $declaration_id; $result = $this->db->query($sql); return $result !== false; } /** * Get account mappings * * @return array Account mappings */ public function getAccountMappings() { $sql = "SELECT ca3_line, account_code, account_label, vat_rate FROM " . MAIN_DB_PREFIX . "declarationtva_account_mappings WHERE entity = " . $this->entity . " AND is_active = 1 ORDER BY ca3_line"; $result = $this->db->query($sql); $mappings = array(); if ($result) { while ($obj = $this->db->fetch_object($result)) { $mappings[] = array( 'ca3_line' => $obj->ca3_line, 'account_code' => $obj->account_code, 'account_label' => $obj->account_label, 'vat_rate' => $obj->vat_rate ); } } return $mappings; } /** * Get period information * * @param int $period_id Period ID * @return array|false Period information or false if not found */ public function getPeriod($period_id) { $sql = "SELECT * FROM " . MAIN_DB_PREFIX . "declarationtva_periods WHERE rowid = " . $period_id . " AND entity = " . $this->entity; $result = $this->db->query($sql); if ($result && $this->db->num_rows($result) > 0) { return $this->db->fetch_array($result); } return false; } /** * Generate declaration number * * @param array $period Period information * @return string Declaration number */ public function generateDeclarationNumber($period) { $year = date('Y', strtotime($period['start_date'])); $start_month = date('m', strtotime($period['start_date'])); $end_month = date('m', strtotime($period['end_date'])); if ($start_month == $end_month) { $month_part = $start_month; } else { $month_part = $start_month . '-' . $end_month; } return 'CA3-' . $year . '-' . $month_part . '-' . date('YmdHis'); } /** * Generate declaration number from dates * * @param string $start_date Start date * @param string $end_date End date * @return string Declaration number */ public function generateDeclarationNumberFromDates($start_date, $end_date) { $year = date('Y', strtotime($start_date)); $start_month = date('m', strtotime($start_date)); $end_month = date('m', strtotime($end_date)); if ($start_month == $end_month) { $month_part = $start_month; } else { $month_part = $start_month . '-' . $end_month; } return 'CA3-' . $year . '-' . $month_part . '-' . date('YmdHis'); } /** * Get declaration information * * @param int $declaration_id Declaration ID * @return array|false Declaration information or false if not found */ public function getDeclaration($declaration_id) { $sql = "SELECT d.*, p.period_name, p.start_date, p.end_date FROM " . MAIN_DB_PREFIX . "declarationtva_declarations d LEFT JOIN " . MAIN_DB_PREFIX . "declarationtva_periods p ON d.period_id = p.rowid WHERE d.rowid = " . $declaration_id . " AND d.entity = " . $this->entity; $result = $this->db->query($sql); if ($result && $this->db->num_rows($result) > 0) { return $this->db->fetch_array($result); } return false; } /** * Get CA-3 lines for a declaration * * @param int $declaration_id Declaration ID * @return array CA-3 lines */ public function getCA3Lines($declaration_id) { $sql = "SELECT * FROM " . MAIN_DB_PREFIX . "declarationtva_ca3_lines WHERE declaration_id = " . $declaration_id . " ORDER BY ca3_line"; $result = $this->db->query($sql); $lines = array(); if ($result) { while ($obj = $this->db->fetch_object($result)) { $lines[] = array( 'ca3_line' => $obj->ca3_line, 'line_label' => $obj->line_label, 'base_amount' => $obj->base_amount, 'vat_amount' => $obj->vat_amount, 'total_amount' => $obj->total_amount ); } } return $lines; } /** * Validate declaration * * @param int $declaration_id Declaration ID * @return bool Success */ public function validateDeclaration($declaration_id) { $sql = "UPDATE " . MAIN_DB_PREFIX . "declarationtva_declarations SET status = 'validated' WHERE rowid = " . $declaration_id . " AND entity = " . $this->entity; $result = $this->db->query($sql); return $result !== false; } /** * Submit declaration * * @param int $declaration_id Declaration ID * @return bool Success */ public function submitDeclaration($declaration_id) { $sql = "UPDATE " . MAIN_DB_PREFIX . "declarationtva_declarations SET status = 'submitted', submission_date = NOW() WHERE rowid = " . $declaration_id . " AND entity = " . $this->entity; $result = $this->db->query($sql); return $result !== false; } /** * Delete a declaration * * @param int $declaration_id Declaration ID * @return bool Success */ public function deleteDeclaration($declaration_id) { $this->db->begin(); // Check if declaration exists and is in draft status $sql = "SELECT status FROM " . MAIN_DB_PREFIX . "declarationtva_declarations WHERE rowid = " . (int)$declaration_id . " AND entity = " . $this->entity; $result = $this->db->query($sql); if ($result) { $obj = $this->db->fetch_object($result); if ($obj && $obj->status == 'draft') { // Delete CA-3 lines first $sql_lines = "DELETE FROM " . MAIN_DB_PREFIX . "declarationtva_ca3_lines WHERE declaration_id = " . (int)$declaration_id; $this->db->query($sql_lines); // Delete declaration $sql_declaration = "DELETE FROM " . MAIN_DB_PREFIX . "declarationtva_declarations WHERE rowid = " . (int)$declaration_id . " AND entity = " . $this->entity; $result = $this->db->query($sql_declaration); if ($result) { $this->db->commit(); return true; } } } $this->db->rollback(); return false; } /** * Recalculate CA-3 amounts for a declaration * * @param int $declaration_id Declaration ID * @return bool Success */ public function recalculateCA3Amounts($declaration_id) { // Get declaration info directly from database $sql = "SELECT start_date, end_date FROM " . MAIN_DB_PREFIX . "declarationtva_declarations WHERE rowid = " . $declaration_id . " AND entity = " . $this->entity; $result = $this->db->query($sql); if (!$result || $this->db->num_rows($result) == 0) { return false; } $obj = $this->db->fetch_object($result); // Clear existing CA-3 lines $sql = "DELETE FROM " . MAIN_DB_PREFIX . "declarationtva_ca3_lines WHERE declaration_id = " . $declaration_id; $this->db->query($sql); // Recalculate using declaration dates $period = array( 'start_date' => $obj->start_date, 'end_date' => $obj->end_date ); return $this->calculateCA3Amounts($declaration_id, $period); } }