DeclarationTVA/core/class/declarationtva_config.class.php
Frank Cools 8a498cb3f5 Remove Notice 4722 references from section headers
- Remove 'Notice 4722 (3310-CA3-SD)' from section A description
- Remove 'Notice 4722 - Summary Table CA3 (3310-CA3-SD)' reference
- Remove 'Notice 4722 - VAT Due Calculation' reference
- Remove 'Notice 4722 - Final Result' reference
- Clean up configuration page by removing technical notice references
- Simplify section descriptions for better user experience
2025-10-07 20:11:28 +02:00

518 lines
21 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* DeclarationTVA_Config Class
* Configuration management for DeclarationTVA module
* MVP Version - Phase 1
*/
class DeclarationTVA_Config
{
/**
* @var DoliDB Database handler
*/
public $db;
/**
* @var int Entity ID
*/
public $entity;
/**
* @var string Error message
*/
public $error;
/**
* Constructor
*
* @param DoliDB $db Database handler
* @param int $entity Entity ID
*/
public function __construct($db, $entity = 1)
{
$this->db = $db;
$this->entity = $entity;
}
/**
* Get configuration value
*
* @param string $key Configuration key
* @param mixed $default Default value
* @return mixed Configuration value
*/
public function get($key, $default = null)
{
$sql = "SELECT config_value FROM " . MAIN_DB_PREFIX . "declarationtva_config
WHERE entity = " . $this->entity . " AND config_key = '" . $this->db->escape($key) . "'";
$result = $this->db->query($sql);
if ($result && $this->db->num_rows($result) > 0) {
$obj = $this->db->fetch_object($result);
return $obj->config_value;
}
return $default;
}
/**
* Set configuration value
*
* @param string $key Configuration key
* @param mixed $value Configuration value
* @return bool Success
*/
public function set($key, $value)
{
$sql = "INSERT INTO " . MAIN_DB_PREFIX . "declarationtva_config
(entity, config_key, config_value, created_date)
VALUES (" . $this->entity . ", '" . $this->db->escape($key) . "',
'" . $this->db->escape($value) . "', NOW())
ON DUPLICATE KEY UPDATE config_value = '" . $this->db->escape($value) . "'";
$result = $this->db->query($sql);
return $result !== false;
}
/**
* Get account mapping for a CA-3 line
*
* @param string $ca3_line CA-3 line code
* @return array|false Account mapping or false if not found
*/
public function getAccountMapping($ca3_line)
{
$sql = "SELECT * FROM " . MAIN_DB_PREFIX . "declarationtva_account_mappings
WHERE entity = " . $this->entity . " AND ca3_line = '" . $this->db->escape($ca3_line) . "'";
$result = $this->db->query($sql);
if ($result && $this->db->num_rows($result) > 0) {
return $this->db->fetch_array($result);
}
return false;
}
/**
* Update account mapping for multiple accounts
*
* @param string $ca3_line CA-3 line code
* @param array $account_codes Array of account codes
* @return bool Success
*/
public function updateAccountMapping($ca3_line, $account_codes)
{
// First, deactivate all existing mappings for this CA-3 line
$sql = "UPDATE " . MAIN_DB_PREFIX . "declarationtva_account_mappings
SET is_active = 0
WHERE entity = " . $this->entity . " AND ca3_line = '" . $this->db->escape($ca3_line) . "'";
$this->db->query($sql);
// Then insert/activate new mappings (only if account_codes is not empty)
if (!empty($account_codes) && is_array($account_codes)) {
foreach ($account_codes as $account_code) {
if (!empty($account_code)) {
// Check if mapping already exists (active or inactive)
$check_sql = "SELECT rowid, is_active FROM " . MAIN_DB_PREFIX . "declarationtva_account_mappings
WHERE entity = " . $this->entity . "
AND ca3_line = '" . $this->db->escape($ca3_line) . "'
AND account_code = '" . $this->db->escape($account_code) . "'";
$check_result = $this->db->query($check_sql);
if ($check_result && $this->db->num_rows($check_result) > 0) {
// Update existing mapping (reactivate it)
$sql = "UPDATE " . MAIN_DB_PREFIX . "declarationtva_account_mappings
SET is_active = 1
WHERE entity = " . $this->entity . "
AND ca3_line = '" . $this->db->escape($ca3_line) . "'
AND account_code = '" . $this->db->escape($account_code) . "'";
$this->db->query($sql);
} else {
// Insert new mapping
$sql = "INSERT INTO " . MAIN_DB_PREFIX . "declarationtva_account_mappings
(entity, ca3_line, account_code, account_label, vat_rate, is_active, created_date)
VALUES (" . $this->entity . ", '" . $this->db->escape($ca3_line) . "',
'" . $this->db->escape($account_code) . "', '', 0, 1, NOW())";
$this->db->query($sql);
}
}
}
}
// If account_codes is empty, all mappings for this line remain deactivated
// This ensures that clearing all selections properly saves the empty state
return true;
}
/**
* Get all account mappings
*
* @return array Account mappings
*/
public function getAllAccountMappings()
{
$sql = "SELECT * 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(
'rowid' => $obj->rowid,
'ca3_line' => $obj->ca3_line,
'account_code' => $obj->account_code,
'account_label' => $obj->account_label,
'vat_rate' => $obj->vat_rate,
'is_active' => $obj->is_active
);
}
}
return $mappings;
}
/**
* Get account mappings grouped by CA-3 line
*
* @return array Account mappings grouped by CA-3 line
*/
public function getAccountMappingsByLine()
{
$sql = "SELECT ca3_line, account_code FROM " . MAIN_DB_PREFIX . "declarationtva_account_mappings
WHERE entity = " . $this->entity . " AND is_active = 1
ORDER BY ca3_line, account_code";
$result = $this->db->query($sql);
$mappings = array();
if ($result) {
while ($obj = $this->db->fetch_object($result)) {
if (!isset($mappings[$obj->ca3_line])) {
$mappings[$obj->ca3_line] = array();
}
$mappings[$obj->ca3_line][] = $obj->account_code;
}
}
return $mappings;
}
/**
* Get available accounting accounts from Dolibarr
*
* @return array Accounting accounts
*/
public function getAccountingAccounts()
{
$sql = "SELECT account_number, label FROM " . MAIN_DB_PREFIX . "accounting_account
WHERE active = 1
ORDER BY account_number";
$result = $this->db->query($sql);
$accounts = array();
if ($result) {
while ($obj = $this->db->fetch_object($result)) {
$accounts[] = array(
'account_number' => $obj->account_number,
'label' => $obj->label
);
}
}
return $accounts;
}
/**
* Get CA-3 line definitions (Notice 4722 - Latest Official Structure)
*
* @return array CA-3 line definitions
*/
public function getCA3LineDefinitions()
{
return array(
// A. Opérations imposables (Taxable Operations) - Notice 4722
'A1' => array(
'label' => 'Ventes, prestations de services',
'type' => 'base',
'section' => 'A',
'description' => 'Ventes, prestations de services',
'pcg_accounts' => 'Sales: 7xxxx; VAT: 44571x / 44572x / 44573x / 44574x'
),
'A2' => array(
'label' => 'Autres opérations imposables',
'type' => 'base',
'section' => 'A',
'description' => 'Autres opérations imposables',
'pcg_accounts' => '775xxx (gains on disposal), 72xxx (production immobilisée), VAT: 44571x'
),
'A3' => array(
'label' => 'Achats de prestations de services réalisés auprès d\'un assujetti non établi en France (article 283-2 du code général des impôts)',
'type' => 'base',
'section' => 'A',
'description' => 'Achats de prestations de services réalisés auprès d\'un assujetti non établi en France (article 283-2 du code général des impôts)',
'pcg_accounts' => '6xxxx (services purchased), 4452xxx (TVA due autoliquidée)'
),
'A4' => array(
'label' => 'Importations (autres que les produits pétroliers)',
'type' => 'base',
'section' => 'A',
'description' => 'Importations (autres que les produits pétroliers)',
'pcg_accounts' => '6xxxx / 2xxxx purchases or assets; VAT: 4452xxx (import VAT)'
),
'A5' => array(
'label' => 'Sorties de régime fiscal suspensif (autres que les produits pétroliers) et sorties de régime particulier douanier uniquement lorsque des livraisons ont eu lieu en cours de régime',
'type' => 'base',
'section' => 'A',
'description' => 'Sorties de régime fiscal suspensif (autres que les produits pétroliers) et sorties de régime particulier douanier uniquement lorsque des livraisons ont eu lieu en cours de régime',
'pcg_accounts' => 'Specific 6xxxx/2xxxx depending on goods; VAT: 4452xxx'
),
// B. Décompte de la TVA due (VAT Due Calculation) - Notice 4722
'08' => array(
'label' => 'TVA due au taux de 20% (Base HT + TVA)',
'type' => 'base_vat',
'section' => 'B',
'description' => 'Base HT and VAT amounts due at 20% rate',
'pcg_accounts' => 'Base: 7xxxx (Sales); VAT: 44571x (TVA collectée à 20%)'
),
'09' => array(
'label' => 'TVA due au taux de 10% (Base HT + TVA)',
'type' => 'base_vat',
'section' => 'B',
'description' => 'Base HT and VAT amounts due at 10% rate',
'pcg_accounts' => 'Base: 7xxxx (Sales); VAT: 44572x (TVA collectée à 10%)'
),
'9B' => array(
'label' => 'TVA due aux taux réduits (Base HT + TVA)',
'type' => 'base_vat',
'section' => 'B',
'description' => 'Base HT and VAT amounts due at reduced rates (5,5% and 2,1%)',
'pcg_accounts' => 'Base: 7xxxx (Sales); VAT: 44573x (5,5%) / 44574x (2,1%)'
),
'17' => array(
'label' => 'TVA due au titre des acquisitions intracommunautaires (autoliquidation)',
'type' => 'vat',
'section' => 'B',
'description' => 'VAT due on intra-EU acquisitions (autoliquidation)',
'pcg_accounts' => '4452xxx (TVA due intracommunautaire)'
),
'18' => array(
'label' => 'Dont TVA sur opérations à destination de Monaco',
'type' => 'vat',
'section' => 'B',
'description' => 'VAT on operations to Monaco',
'pcg_accounts' => '4452xxx (TVA due Monaco)'
),
'19' => array(
'label' => 'Biens constituant des immobilisations',
'type' => 'vat',
'section' => 'B',
'description' => 'Goods constituting fixed assets',
'pcg_accounts' => '44562x (TVA déductible immobilisations)'
),
'20' => array(
'label' => 'Autres biens et services',
'type' => 'vat',
'section' => 'B',
'description' => 'Other goods and services',
'pcg_accounts' => '44566x (TVA déductible autres)'
),
// Additional deductible VAT lines
'21' => array(
'label' => 'Autre TVA à déduire',
'type' => 'vat',
'section' => 'B',
'description' => 'Other deductible VAT',
'pcg_accounts' => '44566x (Autre TVA à déduire)'
),
'22' => array(
'label' => 'Report du crédit apparaissant ligne 27 de la précédente déclaration',
'type' => 'vat',
'section' => 'B',
'description' => 'Carry forward of credit appearing on line 27 of the previous declaration',
'pcg_accounts' => '44567x (Report crédit TVA)'
),
// E. Export and Non-Taxable Operations (part of Section A) - Notice 4722
'E1' => array(
'label' => 'Exportations hors UE',
'type' => 'base',
'section' => 'A',
'description' => 'Exportations hors UE',
'pcg_accounts' => '7xxxx (exports), 4458xxx (TVA export)'
),
'E2' => array(
'label' => 'Autres opérations non imposables',
'type' => 'base',
'section' => 'A',
'description' => 'Autres opérations non imposables',
'pcg_accounts' => '7xxxx (exempt sales), 4458xxx (TVA exempt)'
),
'E3' => array(
'label' => 'Ventes à distance taxables dans un autre État membre au profit des personnes non assujetties Ventes B to C',
'type' => 'base',
'section' => 'A',
'description' => 'Ventes à distance taxables dans un autre État membre au profit des personnes non assujetties Ventes B to C',
'pcg_accounts' => '7xxxx (distance sales), 4458xxx (TVA distance)'
),
'E4' => array(
'label' => 'Importations (autres que les produits pétroliers)',
'type' => 'base',
'section' => 'A',
'description' => 'Importations (autres que les produits pétroliers)',
'pcg_accounts' => '6xxxx (imports), 4452xxx (TVA import)'
),
'E5' => array(
'label' => 'Sorties de régime fiscal suspensif (autres que les produits pétroliers)',
'type' => 'base',
'section' => 'A',
'description' => 'Sorties de régime fiscal suspensif (autres que les produits pétroliers)',
'pcg_accounts' => '6xxxx (suspensive regime exits), 4452xxx (TVA suspensive)'
),
'E6' => array(
'label' => 'Importations placées sous régime fiscal suspensif (autres que les produits pétroliers)',
'type' => 'base',
'section' => 'A',
'description' => 'Importations placées sous régime fiscal suspensif (autres que les produits pétroliers)',
'pcg_accounts' => '6xxxx (suspensive regime imports), 4452xxx (TVA suspensive)'
),
// F. Intracom Operations (part of Section A) - Notice 4722
'F1' => array(
'label' => 'Acquisitions intracommunautaires',
'type' => 'base',
'section' => 'A',
'description' => 'Acquisitions intracommunautaires',
'pcg_accounts' => '6xxxx (purchases from EU), 2xxxx (assets from EU)'
),
'F2' => array(
'label' => 'Livraisons intracommunautaires à destination d\'une personne assujettie Ventes B to B',
'type' => 'vat',
'section' => 'A',
'description' => 'Livraisons intracommunautaires à destination d\'une personne assujettie Ventes B to B',
'pcg_accounts' => '7xxxx (sales to EU), 4452xxx (TVA due autoliquidée sur livraisons intra-EU)'
),
'F6' => array(
'label' => 'Achats en franchise',
'type' => 'base',
'section' => 'A',
'description' => 'Achats en franchise',
'pcg_accounts' => '6xxxx (franchise purchases), 4458xxx (TVA franchise)'
),
'F7' => array(
'label' => 'Ventes de biens ou prestations de services réalisées par un assujetti non établi en France (article 283-1 du code général des impôts)',
'type' => 'base',
'section' => 'A',
'description' => 'Ventes de biens ou prestations de services réalisées par un assujetti non établi en France (article 283-1 du code général des impôts)',
'pcg_accounts' => '7xxxx (non-established sales), 4452xxx (TVA non-established)'
),
'F8' => array(
'label' => 'Régularisations (important : cf. notice)',
'type' => 'base',
'section' => 'A',
'description' => 'Régularisations (important : cf. notice)',
'pcg_accounts' => 'Various (adjustments), 445xxx (TVA adjustments)'
),
// D. Résultat (Result) - Notice 4722
'25' => array(
'label' => 'TVA brute due (Total TVA due)',
'type' => 'vat',
'section' => 'D',
'description' => 'Total VAT due (sum of all VAT due amounts)',
'pcg_accounts' => 'Sum of 08 + 09 + 9B + 17'
),
'26' => array(
'label' => 'TVA déductible totale (Total deductible VAT)',
'type' => 'vat',
'section' => 'D',
'description' => 'Total deductible VAT (sum of all deductible VAT amounts)',
'pcg_accounts' => 'Sum of 20 + 21 + 22'
),
'28' => array(
'label' => 'TVA nette à payer',
'type' => 'vat',
'section' => 'D',
'description' => 'Net VAT to pay (if total due > total deductible)',
'pcg_accounts' => '445510 (État - TVA à décaisser)'
),
'29' => array(
'label' => 'Crédit de TVA à reporter ou remboursement',
'type' => 'vat',
'section' => 'D',
'description' => 'VAT credit to carry forward or refund (if total deductible > total due)',
'pcg_accounts' => '445670 (État - Crédit de TVA à reporter ou rembourser)'
)
);
}
/**
* Get CA-3 section headers (Notice 4722)
*
* @return array Section headers
*/
public function getCA3SectionHeaders()
{
return array(
'A' => array(
'title' => 'A. MONTANT DES OPÉRATIONS RÉALISÉES',
'description' => 'HT amounts of all taxable operations',
'notice' => ''
),
'B' => array(
'title' => 'B. DÉCOMPTE DE LA TVA À PAYER',
'description' => 'VAT amounts due, calculated on A1/A2 bases per applicable rate',
'notice' => ''
),
'D' => array(
'title' => 'D. RÉSULTAT',
'description' => 'Final calculation: net VAT to pay or credit to carry forward',
'notice' => ''
)
);
}
/**
* Get supported VAT rates
*
* @return array VAT rates
*/
public function getVATRates()
{
return array(
'20.00' => '20%',
'10.00' => '10%',
'5.50' => '5.5%',
'2.10' => '2.1%',
'0.00' => '0%'
);
}
/**
* Validate account mapping
*
* @param string $ca3_line CA-3 line code
* @param string $account_code Account code
* @return bool Valid
*/
public function validateAccountMapping($ca3_line, $account_code)
{
// Check if account exists in Dolibarr
$sql = "SELECT COUNT(*) as count FROM " . MAIN_DB_PREFIX . "accounting_account
WHERE account_number = '" . $this->db->escape($account_code) . "' AND active = 1";
$result = $this->db->query($sql);
if ($result && $this->db->num_rows($result) > 0) {
$obj = $this->db->fetch_object($result);
return $obj->count > 0;
}
return false;
}
}