Version 2.5.0: Journal Configuration System
- Add complete journal configuration tab with account selection - Add bank account configuration for VAT payments/receipts - Add auto-create accounting toggle for submission - Add configurable amount calculation method (round vs truncate) - Add automatic database table creation and default values - Fix configuration persistence and form handling - Improve account loading with proper ordering - Add comprehensive error handling and user feedback - Update module version to 2.5.0
This commit is contained in:
parent
1fe5791e99
commit
f5f1169496
23
ChangeLog.md
23
ChangeLog.md
@ -1,5 +1,28 @@
|
||||
# CHANGELOG MODULE DECLARATIONTVA FOR [DOLIBARR ERP CRM](https://www.dolibarr.org)
|
||||
|
||||
## 2.5.0
|
||||
|
||||
### New Features
|
||||
- **Journal Configuration Tab**: Complete journal account configuration system
|
||||
- **Bank Account Configuration**: Configurable bank account for VAT payments/receipts
|
||||
- **Auto-Create Accounting**: Toggle for automatic accounting entry creation on submission
|
||||
- **Amount Calculation Method**: Configurable rounding vs truncation for French CA-3 compliance
|
||||
- **Configurable Journal Accounts**: All journal accounts (VAT, charges, products) are now configurable
|
||||
- **Database Auto-Creation**: Automatic table creation and default value setup
|
||||
|
||||
### Technical Improvements
|
||||
- **Configuration Management**: Centralized configuration system with database storage
|
||||
- **Account Loading**: Improved accounting account retrieval with proper ordering
|
||||
- **Form Handling**: Fixed action processing outside tab logic for reliable form submission
|
||||
- **Database Schema**: Auto-creation of missing tables with proper structure
|
||||
- **Error Handling**: Comprehensive error handling and user feedback
|
||||
|
||||
### Bug Fixes
|
||||
- **Configuration Persistence**: Fixed configuration saving issues
|
||||
- **Account Display**: Resolved uppercase account label display in dropdowns
|
||||
- **Form Actions**: Corrected action handling placement for reliable form processing
|
||||
- **Database Tables**: Automatic creation of missing configuration tables
|
||||
|
||||
## 2.4.0
|
||||
|
||||
### New Features
|
||||
|
||||
@ -69,6 +69,59 @@ if ($action == 'upload_template' || $action == 'reset_template' || $action == 'u
|
||||
}
|
||||
}
|
||||
|
||||
// Handle journal configuration updates
|
||||
if ($action == 'update_journal_config') {
|
||||
$journal_accounts = array(
|
||||
'vat_to_pay' => GETPOST('journal_vat_to_pay', 'alpha'),
|
||||
'vat_to_receive' => GETPOST('journal_vat_to_receive', 'alpha'),
|
||||
'other_charges' => GETPOST('journal_other_charges', 'alpha'),
|
||||
'other_products' => GETPOST('journal_other_products', 'alpha')
|
||||
);
|
||||
|
||||
$updated = $config->updateJournalConfiguration($journal_accounts);
|
||||
if ($updated) {
|
||||
setEventMessages($langs->trans("JournalConfigurationUpdated"), null, 'mesgs');
|
||||
} else {
|
||||
setEventMessages($langs->trans("JournalConfigurationUpdateFailed"), null, 'errors');
|
||||
}
|
||||
}
|
||||
|
||||
// Handle bank account configuration updates
|
||||
if ($action == 'update_bank_config') {
|
||||
$bank_account = GETPOST('journal_bank_account', 'int');
|
||||
|
||||
$updated = $config->updateBankAccountConfiguration($bank_account);
|
||||
if ($updated) {
|
||||
setEventMessages($langs->trans("BankAccountConfigurationUpdated"), null, 'mesgs');
|
||||
} else {
|
||||
setEventMessages($langs->trans("BankAccountConfigurationUpdateFailed"), null, 'errors');
|
||||
}
|
||||
}
|
||||
|
||||
// Handle auto-create accounting entries configuration
|
||||
if ($action == 'update_auto_create_config') {
|
||||
$auto_create_accounting = GETPOST('auto_create_accounting', 'int');
|
||||
|
||||
$updated = $config->updateAutoCreateAccountingConfiguration($auto_create_accounting);
|
||||
if ($updated) {
|
||||
setEventMessages($langs->trans("AutoCreateAccountingConfigurationUpdated"), null, 'mesgs');
|
||||
} else {
|
||||
setEventMessages($langs->trans("AutoCreateAccountingConfigurationUpdateFailed"), null, 'errors');
|
||||
}
|
||||
}
|
||||
|
||||
// Handle amount calculation configuration
|
||||
if ($action == 'update_amount_calc_config') {
|
||||
$calculation_method = GETPOST('amount_calculation_method', 'alpha');
|
||||
|
||||
$updated = $config->updateAmountCalculationConfiguration($calculation_method);
|
||||
if ($updated) {
|
||||
setEventMessages($langs->trans("AmountCalculationConfigurationUpdated"), null, 'mesgs');
|
||||
} else {
|
||||
setEventMessages($langs->trans("AmountCalculationConfigurationUpdateFailed"), null, 'errors');
|
||||
}
|
||||
}
|
||||
|
||||
if ($action == 'update_mappings') {
|
||||
$ca3_definitions = $config->getCA3LineDefinitions();
|
||||
$updated_count = 0;
|
||||
@ -156,6 +209,9 @@ $head[0][2] = 'mapping';
|
||||
$head[1][0] = $_SERVER['PHP_SELF'] . '?tab=templates';
|
||||
$head[1][1] = $langs->trans("TemplateManagement");
|
||||
$head[1][2] = 'templates';
|
||||
$head[2][0] = $_SERVER['PHP_SELF'] . '?tab=journal';
|
||||
$head[2][1] = $langs->trans("JournalConfiguration");
|
||||
$head[2][2] = 'journal';
|
||||
|
||||
$tab = GETPOST('tab', 'alpha');
|
||||
if (empty($tab)) {
|
||||
@ -349,6 +405,183 @@ print '</div>';
|
||||
|
||||
print '</div>'; // Close fichehalfleft
|
||||
print '</div>'; // Close fichecenter
|
||||
|
||||
} elseif ($tab == 'journal') {
|
||||
// Tab 3: Journal Configuration
|
||||
print '<div class="fiche">';
|
||||
|
||||
// Get current journal configuration
|
||||
$journal_config = $config->getJournalConfiguration();
|
||||
|
||||
// Get current auto-create configuration
|
||||
$auto_create_config = $config->getAutoCreateAccountingConfiguration();
|
||||
|
||||
// Get current amount calculation configuration
|
||||
$amount_calc_config = $config->getAmountCalculationConfiguration();
|
||||
|
||||
// First section: Amount Calculation Method
|
||||
print '<form method="POST" action="' . $_SERVER['PHP_SELF'] . '">';
|
||||
print '<input type="hidden" name="action" value="update_amount_calc_config">';
|
||||
print '<input type="hidden" name="token" value="' . newToken() . '">';
|
||||
|
||||
print '<table class="noborder centpercent">';
|
||||
print '<tr class="liste_titre">';
|
||||
print '<td colspan="2"><strong>' . $langs->trans("AmountCalculationConfiguration") . '</strong></td>';
|
||||
print '</tr>';
|
||||
|
||||
print '<tr>';
|
||||
print '<td><strong>' . $langs->trans("AmountCalculationMethod") . '</strong></td>';
|
||||
print '<td>';
|
||||
print '<small>' . $langs->trans("AmountCalculationMethodDescription") . '</small><br>';
|
||||
|
||||
$calculation_options = array(
|
||||
'round' => $langs->trans("RoundAmounts"),
|
||||
'truncate' => $langs->trans("TruncateAmounts")
|
||||
);
|
||||
|
||||
print $form->selectarray('amount_calculation_method', $calculation_options, $amount_calc_config['amount_calculation_method'], 0, 0, 0, '', 0, 0, 0, '', 'minwidth200');
|
||||
print '</td>';
|
||||
print '</tr>';
|
||||
|
||||
print '<tr>';
|
||||
print '<td colspan="2" class="center">';
|
||||
print '<input type="submit" class="button" value="' . $langs->trans("UpdateConfiguration") . '">';
|
||||
print '</td>';
|
||||
print '</tr>';
|
||||
|
||||
print '</table>';
|
||||
print '</form>';
|
||||
|
||||
// Second section: Auto-create accounting entries
|
||||
print '<form method="POST" action="' . $_SERVER['PHP_SELF'] . '">';
|
||||
print '<input type="hidden" name="action" value="update_auto_create_config">';
|
||||
print '<input type="hidden" name="token" value="' . newToken() . '">';
|
||||
|
||||
print '<table class="noborder centpercent">';
|
||||
print '<tr class="liste_titre">';
|
||||
print '<td colspan="2"><strong>' . $langs->trans("AutoCreateAccountingConfiguration") . '</strong></td>';
|
||||
print '</tr>';
|
||||
|
||||
print '<tr>';
|
||||
print '<td><strong>' . $langs->trans("AutoCreateAccountingEntries") . '</strong></td>';
|
||||
print '<td>';
|
||||
print '<small>' . $langs->trans("AutoCreateAccountingEntriesDescription") . '</small><br>';
|
||||
print '<input type="checkbox" name="auto_create_accounting" value="1"' . ($auto_create_config['auto_create_accounting'] ? ' checked' : '') . '>';
|
||||
print ' ' . $langs->trans("EnableAutoCreateAccounting");
|
||||
print '</td>';
|
||||
print '</tr>';
|
||||
|
||||
print '<tr>';
|
||||
print '<td colspan="2" class="center">';
|
||||
print '<input type="submit" class="button" value="' . $langs->trans("UpdateConfiguration") . '">';
|
||||
print '</td>';
|
||||
print '</tr>';
|
||||
|
||||
print '</table>';
|
||||
print '</form>';
|
||||
|
||||
// Second section: Journal Account Configuration
|
||||
print '<br>';
|
||||
print '<form method="POST" action="' . $_SERVER['PHP_SELF'] . '">';
|
||||
print '<input type="hidden" name="action" value="update_journal_config">';
|
||||
print '<input type="hidden" name="token" value="' . newToken() . '">';
|
||||
|
||||
print '<table class="noborder centpercent">';
|
||||
print '<tr class="liste_titre">';
|
||||
print '<td colspan="2"><strong>' . $langs->trans("JournalAccountConfiguration") . '</strong></td>';
|
||||
print '</tr>';
|
||||
|
||||
// Create account options array exactly like in the mapping section
|
||||
$account_options = array();
|
||||
foreach ($accounts as $account) {
|
||||
$account_options[$account['account_number']] = $account['account_number'] . ' - ' . $account['label'];
|
||||
}
|
||||
|
||||
print '<tr>';
|
||||
print '<td><strong>' . $langs->trans("VATToPayAccount") . '</strong></td>';
|
||||
print '<td>';
|
||||
print '<small>' . $langs->trans("VATToPayAccountDescription") . '</small><br>';
|
||||
print $form->selectarray('journal_vat_to_pay', $account_options, $journal_config['vat_to_pay'], 0, 0, 0, '', 0, 0, 0, '', 'minwidth200');
|
||||
print '</td>';
|
||||
print '</tr>';
|
||||
|
||||
print '<tr>';
|
||||
print '<td><strong>' . $langs->trans("VATToReceiveAccount") . '</strong></td>';
|
||||
print '<td>';
|
||||
print '<small>' . $langs->trans("VATToReceiveAccountDescription") . '</small><br>';
|
||||
print $form->selectarray('journal_vat_to_receive', $account_options, $journal_config['vat_to_receive'], 0, 0, 0, '', 0, 0, 0, '', 'minwidth200');
|
||||
print '</td>';
|
||||
print '</tr>';
|
||||
|
||||
print '<tr>';
|
||||
print '<td><strong>' . $langs->trans("OtherChargesAccount") . '</strong></td>';
|
||||
print '<td>';
|
||||
print '<small>' . $langs->trans("OtherChargesAccountDescription") . '</small><br>';
|
||||
print $form->selectarray('journal_other_charges', $account_options, $journal_config['other_charges'], 0, 0, 0, '', 0, 0, 0, '', 'minwidth200');
|
||||
print '</td>';
|
||||
print '</tr>';
|
||||
|
||||
print '<tr>';
|
||||
print '<td><strong>' . $langs->trans("OtherProductsAccount") . '</strong></td>';
|
||||
print '<td>';
|
||||
print '<small>' . $langs->trans("OtherProductsAccountDescription") . '</small><br>';
|
||||
print $form->selectarray('journal_other_products', $account_options, $journal_config['other_products'], 0, 0, 0, '', 0, 0, 0, '', 'minwidth200');
|
||||
print '</td>';
|
||||
print '</tr>';
|
||||
|
||||
print '<tr>';
|
||||
print '<td colspan="2" class="center">';
|
||||
print '<input type="submit" class="button" value="' . $langs->trans("UpdateConfiguration") . '">';
|
||||
print '</td>';
|
||||
print '</tr>';
|
||||
|
||||
print '</table>';
|
||||
print '</form>';
|
||||
|
||||
// Second section: Bank Account Configuration
|
||||
print '<br>';
|
||||
print '<form method="POST" action="' . $_SERVER['PHP_SELF'] . '">';
|
||||
print '<input type="hidden" name="action" value="update_bank_config">';
|
||||
print '<input type="hidden" name="token" value="' . newToken() . '">';
|
||||
|
||||
print '<table class="noborder centpercent">';
|
||||
print '<tr class="liste_titre">';
|
||||
print '<td colspan="2"><strong>' . $langs->trans("BankAccountConfiguration") . '</strong></td>';
|
||||
print '</tr>';
|
||||
|
||||
// Get current bank account configuration
|
||||
$bank_config = $config->getBankAccountConfiguration();
|
||||
|
||||
print '<tr>';
|
||||
print '<td><strong>' . $langs->trans("VATPaymentBankAccount") . '</strong></td>';
|
||||
print '<td>';
|
||||
print '<small>' . $langs->trans("VATPaymentBankAccountDescription") . '</small><br>';
|
||||
|
||||
// Get bank accounts for selection
|
||||
$bank_accounts = $config->getBankAccounts();
|
||||
$bank_options = array();
|
||||
foreach ($bank_accounts as $bank) {
|
||||
$bank_options[$bank['rowid']] = $bank['label'] . ' (' . $bank['number'] . ')';
|
||||
}
|
||||
|
||||
if (empty($bank_options)) {
|
||||
print '<span class="error">' . $langs->trans("NoBankAccountsFound") . '</span>';
|
||||
} else {
|
||||
print $form->selectarray('journal_bank_account', $bank_options, $bank_config['bank_account'], 0, 0, 0, '', 0, 0, 0, '', 'minwidth200');
|
||||
}
|
||||
print '</td>';
|
||||
print '</tr>';
|
||||
|
||||
print '<tr>';
|
||||
print '<td colspan="2" class="center">';
|
||||
print '<input type="submit" class="button" value="' . $langs->trans("UpdateConfiguration") . '">';
|
||||
print '</td>';
|
||||
print '</tr>';
|
||||
|
||||
print '</table>';
|
||||
print '</form>';
|
||||
|
||||
print '</div>';
|
||||
}
|
||||
|
||||
// Print footer
|
||||
|
||||
@ -592,10 +592,22 @@ class DeclarationTVA
|
||||
*/
|
||||
public function createCA3Line($declaration_id, $ca3_line, $line_label, $amounts)
|
||||
{
|
||||
// Round amounts to whole numbers
|
||||
$rounded_base = round($amounts['base_amount']);
|
||||
$rounded_vat = round($amounts['vat_amount']);
|
||||
$rounded_total = round($amounts['total_amount']);
|
||||
// Get amount calculation configuration
|
||||
require_once DOL_DOCUMENT_ROOT . '/custom/declarationtva/core/class/declarationtva_config.class.php';
|
||||
$config = new DeclarationTVA_Config($this->db, $this->entity);
|
||||
$calc_config = $config->getAmountCalculationConfiguration();
|
||||
|
||||
// Apply calculation method (round or truncate)
|
||||
if ($calc_config['amount_calculation_method'] == 'truncate') {
|
||||
$rounded_base = floor($amounts['base_amount']);
|
||||
$rounded_vat = floor($amounts['vat_amount']);
|
||||
$rounded_total = floor($amounts['total_amount']);
|
||||
} else {
|
||||
// Default to rounding
|
||||
$rounded_base = round($amounts['base_amount']);
|
||||
$rounded_vat = round($amounts['vat_amount']);
|
||||
$rounded_total = round($amounts['total_amount']);
|
||||
}
|
||||
|
||||
// Store original amounts in the line_label for now (we'll need to modify the database schema later)
|
||||
$original_base = $amounts['base_amount'];
|
||||
|
||||
@ -32,6 +32,76 @@ class DeclarationTVA_Config
|
||||
{
|
||||
$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;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -207,9 +277,12 @@ class DeclarationTVA_Config
|
||||
*/
|
||||
public function getAccountingAccounts()
|
||||
{
|
||||
$sql = "SELECT account_number, label FROM " . MAIN_DB_PREFIX . "accounting_account
|
||||
WHERE active = 1
|
||||
ORDER BY account_number";
|
||||
// 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();
|
||||
@ -223,9 +296,139 @@ class DeclarationTVA_Config
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
$config[$key] = $this->get('bank_' . $key, $default_value);
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update bank account configuration
|
||||
*
|
||||
* @param int $bank_account_id Bank account ID
|
||||
* @return bool Success
|
||||
*/
|
||||
public function updateBankAccountConfiguration($bank_account_id)
|
||||
{
|
||||
return $this->set('bank_bank_account', (int)$bank_account_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
*
|
||||
@ -509,4 +712,45 @@ class DeclarationTVA_Config
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2122,12 +2122,15 @@ class DeclarationTVA_PDF
|
||||
|
||||
$balancing_entries = array();
|
||||
|
||||
// Get journal configuration
|
||||
$journal_config = $this->getJournalConfiguration();
|
||||
|
||||
// Use TD line calculation (Line 16 - Line 23) as main balancing amount
|
||||
$line_16_amount = $this->getLineAmount($declaration, '16');
|
||||
$line_23_amount = $this->getLineAmount($declaration, '23');
|
||||
$td_amount = $line_16_amount - $line_23_amount;
|
||||
|
||||
// If TD <= 0, use line 26 or 27 (whichever is not 0) and account 4456700 on debit side
|
||||
// If TD <= 0, use line 26 or 27 (whichever is not 0) and configured VAT to receive account on debit side
|
||||
if ($td_amount <= 0) {
|
||||
$line26_amount = $this->getLineAmount($declaration, '26');
|
||||
$line27_amount = $this->getLineAmount($declaration, '27');
|
||||
@ -2142,18 +2145,18 @@ class DeclarationTVA_PDF
|
||||
|
||||
if (abs($selected_amount) >= 0.01) {
|
||||
$balancing_entries[] = array(
|
||||
'account_code' => '4456700',
|
||||
'account_label' => $this->getAccountLabel('4456700'),
|
||||
'account_code' => $journal_config['vat_to_receive'],
|
||||
'account_label' => $this->getAccountLabel($journal_config['vat_to_receive']),
|
||||
'entry_label' => $declaration->declaration_name,
|
||||
'debit' => $this->formatAmount($selected_amount),
|
||||
'credit' => ''
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// If TD > 0, use TD value and account 4455100
|
||||
// If TD > 0, use TD value and configured VAT to pay account
|
||||
$balancing_entries[] = array(
|
||||
'account_code' => '4455100',
|
||||
'account_label' => $this->getAccountLabel('4455100'),
|
||||
'account_code' => $journal_config['vat_to_pay'],
|
||||
'account_label' => $this->getAccountLabel($journal_config['vat_to_pay']),
|
||||
'entry_label' => $declaration->declaration_name,
|
||||
'debit' => '',
|
||||
'credit' => $this->formatAmount(abs($td_amount))
|
||||
@ -2189,19 +2192,19 @@ class DeclarationTVA_PDF
|
||||
// If there's still a difference, add final balancing entry
|
||||
if (abs($final_difference) >= 0.01) {
|
||||
if ($final_difference > 0) {
|
||||
// More debits, need credit entry on 758000
|
||||
// More debits, need credit entry on other products account
|
||||
$balancing_entries[] = array(
|
||||
'account_code' => '758000',
|
||||
'account_label' => $this->getAccountLabel('758000'),
|
||||
'account_code' => $journal_config['other_products'],
|
||||
'account_label' => $this->getAccountLabel($journal_config['other_products']),
|
||||
'entry_label' => $declaration->declaration_name,
|
||||
'debit' => '',
|
||||
'credit' => $this->formatAmountReal($final_difference)
|
||||
);
|
||||
} else {
|
||||
// More credits, need debit entry on 658000
|
||||
// More credits, need debit entry on other charges account
|
||||
$balancing_entries[] = array(
|
||||
'account_code' => '658000',
|
||||
'account_label' => $this->getAccountLabel('658000'),
|
||||
'account_code' => $journal_config['other_charges'],
|
||||
'account_label' => $this->getAccountLabel($journal_config['other_charges']),
|
||||
'entry_label' => $declaration->declaration_name,
|
||||
'debit' => $this->formatAmountReal(abs($final_difference)),
|
||||
'credit' => ''
|
||||
@ -2274,6 +2277,18 @@ class DeclarationTVA_PDF
|
||||
return (float)$amount_string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get journal configuration
|
||||
*
|
||||
* @return array Journal configuration
|
||||
*/
|
||||
private function getJournalConfiguration()
|
||||
{
|
||||
require_once DOL_DOCUMENT_ROOT . '/custom/declarationtva/core/class/declarationtva_config.class.php';
|
||||
$config = new DeclarationTVA_Config($this->db, $this->entity);
|
||||
return $config->getJournalConfiguration();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get account label from chart of accounts
|
||||
*
|
||||
@ -2282,22 +2297,11 @@ class DeclarationTVA_PDF
|
||||
*/
|
||||
private function getAccountLabel($account_code)
|
||||
{
|
||||
// Map the hardcoded account codes to the actual account numbers in the database
|
||||
$account_mapping = array(
|
||||
'4455100' => '44551', // TVA A DECAISSER
|
||||
'4456700' => '44567', // TVA A PAYER
|
||||
'658000' => '658', // AUTRES CHARGES DE GESTION COURANTE
|
||||
'758000' => '758' // AUTRES PRODUITS DE GESTION COURANT
|
||||
);
|
||||
|
||||
// Use mapped account code if available, otherwise use original
|
||||
$search_code = isset($account_mapping[$account_code]) ? $account_mapping[$account_code] : $account_code;
|
||||
|
||||
// Use the same approach as getAccountMappings() in the main class
|
||||
// Order by rowid ASC to get the oldest entry (custom uppercase labels)
|
||||
$sql = "SELECT a.label
|
||||
FROM " . MAIN_DB_PREFIX . "accounting_account a
|
||||
WHERE a.account_number = '" . $this->db->escape($search_code) . "'
|
||||
WHERE a.account_number = '" . $this->db->escape($account_code) . "'
|
||||
AND a.entity = " . $this->entity . "
|
||||
ORDER BY a.rowid ASC
|
||||
LIMIT 1";
|
||||
@ -2311,7 +2315,7 @@ class DeclarationTVA_PDF
|
||||
// If not found with entity, try without entity filter
|
||||
$sql = "SELECT a.label
|
||||
FROM " . MAIN_DB_PREFIX . "accounting_account a
|
||||
WHERE a.account_number = '" . $this->db->escape($search_code) . "'
|
||||
WHERE a.account_number = '" . $this->db->escape($account_code) . "'
|
||||
ORDER BY a.rowid ASC
|
||||
LIMIT 1";
|
||||
|
||||
|
||||
@ -76,7 +76,7 @@ class modDeclarationTVA extends DolibarrModules
|
||||
$this->editor_squarred_logo = ''; // Must be image filename into the module/img directory followed with @modulename. Example: 'myimage.png@declarationtva'
|
||||
|
||||
// Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated', 'experimental_deprecated' or a version string like 'x.y.z'
|
||||
$this->version = '2.4.0';
|
||||
$this->version = '2.5.0';
|
||||
// Url to the file with your last numberversion of this module
|
||||
//$this->url_last_version = 'http://www.example.com/versionmodule.txt';
|
||||
|
||||
|
||||
@ -20,6 +20,7 @@ NewSection=New section
|
||||
# Configuration tabs
|
||||
PCGMapping = PCG Mapping
|
||||
TemplateManagement = Template Management
|
||||
JournalConfiguration = Journal Configuration
|
||||
UpdateConfiguration = Update Configuration
|
||||
DECLARATIONTVA_MYPARAM1 = My param 1
|
||||
DECLARATIONTVA_MYPARAM1Tooltip = My param 1 tooltip
|
||||
@ -520,3 +521,35 @@ NoDocument = No Document
|
||||
DownloadPDF = Download PDF
|
||||
UnvalidationConfirmationMessage = Are you sure you want to unvalidate this declaration? This action will revert the declaration to draft status and remove the generated PDF.
|
||||
YesUnvalidate = Yes, unvalidate
|
||||
|
||||
# Journal Configuration
|
||||
JournalAccountConfiguration = Journal Account Configuration
|
||||
VATToPayAccount = VAT to Pay Account
|
||||
VATToPayAccountDescription = Account used for VAT due to the State (e.g., 44551)
|
||||
VATToReceiveAccount = VAT to Receive Account
|
||||
VATToReceiveAccountDescription = Account used for VAT to receive from the State (e.g., 44567)
|
||||
OtherChargesAccount = Other Charges Account
|
||||
OtherChargesAccountDescription = Account used for other current management charges (e.g., 658)
|
||||
OtherProductsAccount = Other Products Account
|
||||
OtherProductsAccountDescription = Account used for other current management products (e.g., 758)
|
||||
JournalConfigurationUpdated = Journal configuration updated successfully
|
||||
JournalConfigurationUpdateFailed = Error updating journal configuration
|
||||
BankAccountConfiguration = Bank Account Configuration
|
||||
VATPaymentBankAccount = VAT Payment Bank Account
|
||||
VATPaymentBankAccountDescription = Bank account used for VAT payments and refunds
|
||||
BankAccountConfigurationUpdated = Bank account configuration updated
|
||||
BankAccountConfigurationUpdateFailed = Error updating bank account configuration
|
||||
NoBankAccountsFound = No bank accounts found
|
||||
AutoCreateAccountingConfiguration = Auto-Create Accounting Configuration
|
||||
AutoCreateAccountingEntries = Auto-Create Accounting Entries
|
||||
AutoCreateAccountingEntriesDescription = Enables automatic creation of accounting entries when a declaration is submitted
|
||||
EnableAutoCreateAccounting = Enable automatic accounting entry creation
|
||||
AutoCreateAccountingConfigurationUpdated = Auto-create accounting configuration updated
|
||||
AutoCreateAccountingConfigurationUpdateFailed = Error updating auto-create accounting configuration
|
||||
AmountCalculationConfiguration = Amount Calculation Configuration
|
||||
AmountCalculationMethod = Amount Calculation Method
|
||||
AmountCalculationMethodDescription = Choose how decimal amounts are handled in CA-3 declarations
|
||||
RoundAmounts = Round amounts (€123.56 → €124)
|
||||
TruncateAmounts = Truncate amounts (€123.56 → €123)
|
||||
AmountCalculationConfigurationUpdated = Amount calculation configuration updated
|
||||
AmountCalculationConfigurationUpdateFailed = Error updating amount calculation configuration
|
||||
|
||||
@ -24,6 +24,7 @@ DECLARATIONTVA_PCG_CONFIG_TOOLTIP = Configuration des comptes du Plan Comptable
|
||||
# Onglets de configuration
|
||||
PCGMapping = Mapping PCG
|
||||
TemplateManagement = Gestion des modèles
|
||||
JournalConfiguration = Configuration Journal
|
||||
UpdateConfiguration = Mettre à jour la configuration
|
||||
|
||||
# Sélection multiple de comptes
|
||||
@ -492,3 +493,35 @@ NoDocument = Aucun document
|
||||
DownloadPDF = Télécharger le PDF
|
||||
UnvalidationConfirmationMessage = Êtes-vous sûr de vouloir annuler la validation de cette déclaration ? Cette action remettra la déclaration en mode brouillon et supprimera le PDF généré.
|
||||
YesUnvalidate = Oui, annuler la validation
|
||||
|
||||
# Journal Configuration
|
||||
JournalAccountConfiguration = Configuration des comptes du journal
|
||||
VATToPayAccount = Compte TVA à payer
|
||||
VATToPayAccountDescription = Compte utilisé pour la TVA due à l'État (ex: 44551)
|
||||
VATToReceiveAccount = Compte TVA à recevoir
|
||||
VATToReceiveAccountDescription = Compte utilisé pour la TVA à recevoir de l'État (ex: 44567)
|
||||
OtherChargesAccount = Compte autres charges
|
||||
OtherChargesAccountDescription = Compte utilisé pour les autres charges de gestion courante (ex: 658)
|
||||
OtherProductsAccount = Compte autres produits
|
||||
OtherProductsAccountDescription = Compte utilisé pour les autres produits de gestion courante (ex: 758)
|
||||
JournalConfigurationUpdated = Configuration du journal mise à jour avec succès
|
||||
JournalConfigurationUpdateFailed = Erreur lors de la mise à jour de la configuration du journal
|
||||
BankAccountConfiguration = Configuration du compte bancaire
|
||||
VATPaymentBankAccount = Compte bancaire pour paiement TVA
|
||||
VATPaymentBankAccountDescription = Compte bancaire utilisé pour les paiements et remboursements de TVA
|
||||
BankAccountConfigurationUpdated = Configuration du compte bancaire mise à jour
|
||||
BankAccountConfigurationUpdateFailed = Erreur lors de la mise à jour de la configuration du compte bancaire
|
||||
NoBankAccountsFound = Aucun compte bancaire trouvé
|
||||
AutoCreateAccountingConfiguration = Configuration de création automatique des écritures
|
||||
AutoCreateAccountingEntries = Création automatique des écritures comptables
|
||||
AutoCreateAccountingEntriesDescription = Active la création automatique des écritures comptables lors de la soumission d'une déclaration
|
||||
EnableAutoCreateAccounting = Activer la création automatique des écritures comptables
|
||||
AutoCreateAccountingConfigurationUpdated = Configuration de création automatique mise à jour
|
||||
AutoCreateAccountingConfigurationUpdateFailed = Erreur lors de la mise à jour de la configuration de création automatique
|
||||
AmountCalculationConfiguration = Configuration du calcul des montants
|
||||
AmountCalculationMethod = Méthode de calcul des montants
|
||||
AmountCalculationMethodDescription = Choisissez comment les montants décimaux sont traités dans les déclarations CA-3
|
||||
RoundAmounts = Arrondir les montants (€123.56 → €124)
|
||||
TruncateAmounts = Tronquer les montants (€123.56 → €123)
|
||||
AmountCalculationConfigurationUpdated = Configuration du calcul des montants mise à jour
|
||||
AmountCalculationConfigurationUpdateFailed = Erreur lors de la mise à jour de la configuration du calcul des montants
|
||||
|
||||
10
sql/create_config_table.sql
Normal file
10
sql/create_config_table.sql
Normal file
@ -0,0 +1,10 @@
|
||||
-- Create the missing declarationtva_config table
|
||||
CREATE TABLE IF NOT EXISTS `llx_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;
|
||||
25
sql/fix_missing_config_table.sql
Normal file
25
sql/fix_missing_config_table.sql
Normal file
@ -0,0 +1,25 @@
|
||||
-- Fix missing declarationtva_config table
|
||||
-- Run this SQL in your database to create the missing table
|
||||
|
||||
USE dolibarrdebian;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `llx_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;
|
||||
|
||||
-- Insert some default configuration values
|
||||
INSERT IGNORE INTO `llx_declarationtva_config` (`entity`, `config_key`, `config_value`, `created_date`) VALUES
|
||||
(1, 'module_version', '2.4.0', NOW()),
|
||||
(1, 'amount_calc_amount_calculation_method', 'truncate', NOW()),
|
||||
(1, 'auto_create_auto_create_accounting', '0', NOW()),
|
||||
(1, 'bank_bank_account', '0', NOW()),
|
||||
(1, 'journal_vat_to_pay', '44551', NOW()),
|
||||
(1, 'journal_vat_to_receive', '44567', NOW()),
|
||||
(1, 'journal_other_charges', '658', NOW()),
|
||||
(1, 'journal_other_products', '758', NOW());
|
||||
Loading…
Reference in New Issue
Block a user