- Added light gray backgrounds to all section titles in detailed pages - Enhanced visual hierarchy for better readability - Improved professional appearance of PDF exports - Updated module version to 2.5.1
762 lines
28 KiB
PHP
762 lines
28 KiB
PHP
<?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;
|
||
|
||
// Ensure the config table exists
|
||
$this->ensureConfigTableExists();
|
||
}
|
||
|
||
/**
|
||
* Ensure the declarationtva_config table exists
|
||
*
|
||
* @return bool Success
|
||
*/
|
||
private function ensureConfigTableExists()
|
||
{
|
||
// Check if table exists
|
||
$sql = "SHOW TABLES LIKE '" . MAIN_DB_PREFIX . "declarationtva_config'";
|
||
$result = $this->db->query($sql);
|
||
|
||
if (!$result || $this->db->num_rows($result) == 0) {
|
||
// Table doesn't exist, create it
|
||
$create_sql = "CREATE TABLE IF NOT EXISTS `" . MAIN_DB_PREFIX . "declarationtva_config` (
|
||
`rowid` int(11) NOT NULL AUTO_INCREMENT,
|
||
`entity` int(11) NOT NULL DEFAULT 1,
|
||
`config_key` varchar(64) NOT NULL,
|
||
`config_value` text,
|
||
`created_date` datetime DEFAULT NULL,
|
||
PRIMARY KEY (`rowid`),
|
||
UNIQUE KEY `uk_config_entity_key` (`entity`, `config_key`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci";
|
||
|
||
$create_result = $this->db->query($create_sql);
|
||
if (!$create_result) {
|
||
error_log("DeclarationTVA: Failed to create config table: " . $this->db->lasterror());
|
||
return false;
|
||
}
|
||
|
||
// Insert default configuration values
|
||
$this->insertDefaultConfigValues();
|
||
|
||
error_log("DeclarationTVA: Created declarationtva_config table");
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* Insert default configuration values
|
||
*
|
||
* @return bool Success
|
||
*/
|
||
private function insertDefaultConfigValues()
|
||
{
|
||
$default_configs = array(
|
||
'module_version' => '2.4.0',
|
||
'amount_calc_amount_calculation_method' => 'truncate',
|
||
'auto_create_auto_create_accounting' => '0',
|
||
'bank_bank_account' => '0',
|
||
'journal_vat_to_pay' => '44551',
|
||
'journal_vat_to_receive' => '44567',
|
||
'journal_other_charges' => '658',
|
||
'journal_other_products' => '758'
|
||
);
|
||
|
||
foreach ($default_configs as $key => $value) {
|
||
$sql = "INSERT IGNORE 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())";
|
||
$this->db->query($sql);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 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()
|
||
{
|
||
// Use the same approach as in the view page - check how it's done there
|
||
// Order by rowid DESC to get the most recent account for each account number
|
||
$sql = "SELECT a.account_number, a.label
|
||
FROM " . MAIN_DB_PREFIX . "accounting_account a
|
||
WHERE a.entity = " . $this->entity . "
|
||
ORDER BY a.account_number, a.rowid DESC";
|
||
|
||
$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
|
||
);
|
||
}
|
||
}
|
||
|
||
// Debug: Log what we found
|
||
error_log("DeclarationTVA: getAccountingAccounts() found " . count($accounts) . " accounts");
|
||
if (!empty($accounts)) {
|
||
error_log("DeclarationTVA: First account: " . $accounts[0]['account_number'] . " - " . $accounts[0]['label']);
|
||
}
|
||
|
||
return $accounts;
|
||
}
|
||
|
||
/**
|
||
* Get auto-create accounting configuration
|
||
*
|
||
* @return array Auto-create accounting configuration
|
||
*/
|
||
public function getAutoCreateAccountingConfiguration()
|
||
{
|
||
$default_config = array(
|
||
'auto_create_accounting' => 0 // Disabled by default
|
||
);
|
||
|
||
$config = array();
|
||
foreach ($default_config as $key => $default_value) {
|
||
$config[$key] = $this->get('auto_create_' . $key, $default_value);
|
||
}
|
||
|
||
return $config;
|
||
}
|
||
|
||
/**
|
||
* Get amount calculation configuration
|
||
*
|
||
* @return array Amount calculation configuration
|
||
*/
|
||
public function getAmountCalculationConfiguration()
|
||
{
|
||
$default_config = array(
|
||
'amount_calculation_method' => 'truncate' // 'round' or 'truncate'
|
||
);
|
||
|
||
$config = array();
|
||
foreach ($default_config as $key => $default_value) {
|
||
$config[$key] = $this->get('amount_calc_' . $key, $default_value);
|
||
}
|
||
|
||
return $config;
|
||
}
|
||
|
||
/**
|
||
* Update amount calculation configuration
|
||
*
|
||
* @param string $method Calculation method ('round' or 'truncate')
|
||
* @return bool Success
|
||
*/
|
||
public function updateAmountCalculationConfiguration($method)
|
||
{
|
||
if (!in_array($method, array('round', 'truncate'))) {
|
||
return false;
|
||
}
|
||
|
||
return $this->set('amount_calc_amount_calculation_method', $method);
|
||
}
|
||
|
||
/**
|
||
* Update auto-create accounting configuration
|
||
*
|
||
* @param int $auto_create_accounting Auto-create accounting flag (0 or 1)
|
||
* @return bool Success
|
||
*/
|
||
public function updateAutoCreateAccountingConfiguration($auto_create_accounting)
|
||
{
|
||
return $this->set('auto_create_auto_create_accounting', (int)$auto_create_accounting);
|
||
}
|
||
|
||
/**
|
||
* Get bank account configuration
|
||
*
|
||
* @return array Bank account configuration
|
||
*/
|
||
public function getBankAccountConfiguration()
|
||
{
|
||
$default_config = array(
|
||
'bank_account' => 0 // No bank account selected by default
|
||
);
|
||
|
||
$config = array();
|
||
foreach ($default_config as $key => $default_value) {
|
||
$value = $this->get('bank_' . $key, $default_value);
|
||
$config[$key] = $value;
|
||
error_log("DeclarationTVA: Retrieved bank config " . $key . ": " . $value);
|
||
}
|
||
|
||
return $config;
|
||
}
|
||
|
||
/**
|
||
* Update bank account configuration
|
||
*
|
||
* @param int $bank_account_id Bank account ID
|
||
* @return bool Success
|
||
*/
|
||
public function updateBankAccountConfiguration($bank_account_id)
|
||
{
|
||
error_log("DeclarationTVA: Updating bank account to: " . $bank_account_id);
|
||
$result = $this->set('bank_bank_account', (int)$bank_account_id);
|
||
error_log("DeclarationTVA: Bank account update result: " . ($result ? 'success' : 'failed'));
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* Get available bank accounts
|
||
*
|
||
* @return array Bank accounts
|
||
*/
|
||
public function getBankAccounts()
|
||
{
|
||
$sql = "SELECT rowid, label, number, bank
|
||
FROM " . MAIN_DB_PREFIX . "bank_account
|
||
WHERE entity = " . $this->entity . "
|
||
AND clos = 0
|
||
ORDER BY label";
|
||
|
||
$result = $this->db->query($sql);
|
||
$accounts = array();
|
||
|
||
if ($result) {
|
||
while ($obj = $this->db->fetch_object($result)) {
|
||
$accounts[] = array(
|
||
'rowid' => $obj->rowid,
|
||
'label' => $obj->label,
|
||
'number' => $obj->number,
|
||
'bank' => $obj->bank
|
||
);
|
||
}
|
||
}
|
||
|
||
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' => '',
|
||
'notice' => ''
|
||
),
|
||
'B' => array(
|
||
'title' => 'B. DÉCOMPTE DE LA TVA À PAYER',
|
||
'description' => '',
|
||
'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;
|
||
}
|
||
|
||
/**
|
||
* Get journal configuration
|
||
*
|
||
* @return array Journal configuration
|
||
*/
|
||
public function getJournalConfiguration()
|
||
{
|
||
$default_config = array(
|
||
'vat_to_pay' => '44551', // TVA A DECAISSER
|
||
'vat_to_receive' => '44567', // TVA A PAYER
|
||
'other_charges' => '658', // AUTRES CHARGES DE GESTION COURANTE
|
||
'other_products' => '758' // AUTRES PRODUITS DE GESTION COURANT
|
||
);
|
||
|
||
$config = array();
|
||
foreach ($default_config as $key => $default_value) {
|
||
$config[$key] = $this->get('journal_' . $key, $default_value);
|
||
}
|
||
|
||
return $config;
|
||
}
|
||
|
||
/**
|
||
* Update journal configuration
|
||
*
|
||
* @param array $journal_accounts Journal account configuration
|
||
* @return bool Success
|
||
*/
|
||
public function updateJournalConfiguration($journal_accounts)
|
||
{
|
||
$success = true;
|
||
|
||
foreach ($journal_accounts as $key => $account_code) {
|
||
if (!$this->set('journal_' . $key, $account_code)) {
|
||
$success = false;
|
||
}
|
||
}
|
||
|
||
return $success;
|
||
}
|
||
}
|