From e00c6f89f720b613ccb5da3300f721deb8c6d1a0 Mon Sep 17 00:00:00 2001 From: Frank Cools Date: Wed, 8 Oct 2025 16:28:18 +0200 Subject: [PATCH] Add VAT refund threshold logic with configurable threshold and 445671 account support --- admin/setup.php | 14 ++++ core/class/declarationtva.class.php | 67 +++++++++++---- core/class/declarationtva_config.class.php | 37 +++++++- core/class/declarationtva_pdf.class.php | 98 ++++++++++++++-------- langs/fr_FR/declarationtva.lang | 4 + 5 files changed, 168 insertions(+), 52 deletions(-) diff --git a/admin/setup.php b/admin/setup.php index 2ca0f2c..fdfc048 100644 --- a/admin/setup.php +++ b/admin/setup.php @@ -145,6 +145,20 @@ $formSetup->newItem('DECLARATIONTVA_MYPARAM8')->setAsProduct(); // Add a title for a new section $formSetup->newItem('NewSection')->setAsTitle(); +// VAT Refund Threshold Configuration +$item = $formSetup->newItem('DECLARATIONTVA_VAT_REFUND_THRESHOLD'); +$item->nameText = 'VAT Refund Threshold (€)'; +$item->defaultFieldValue = 760.00; +$item->fieldAttr['placeholder'] = '760.00'; +$item->helpText = 'Threshold amount for immediate VAT refund vs carry forward. Amounts below this threshold will be carried forward to the next declaration.'; +$item->cssClass = 'minwidth200'; + +// VAT Refund Threshold Enabled +$item = $formSetup->newItem('DECLARATIONTVA_VAT_REFUND_THRESHOLD_ENABLED'); +$item->nameText = 'Enable VAT Refund Threshold Logic'; +$item->setAsYesNo(); +$item->helpText = 'Enable or disable the threshold logic for VAT refunds.'; + $TField = array( 'test01' => $langs->trans('test01'), 'test02' => $langs->trans('test02'), diff --git a/core/class/declarationtva.class.php b/core/class/declarationtva.class.php index 48518fa..e767aa9 100644 --- a/core/class/declarationtva.class.php +++ b/core/class/declarationtva.class.php @@ -441,9 +441,31 @@ class DeclarationTVA )); } - // Line 27: Crédit de TVA à reporter (ligne 25 – ligne 26) - same value as line 25, only if > 0 and < 760 + // Get VAT refund threshold configuration + require_once DOL_DOCUMENT_ROOT . '/custom/declarationtva/core/class/declarationtva_config.class.php'; + $config = new DeclarationTVA_Config($this->db, $this->entity); + $threshold_config = $config->getVATRefundThresholdConfiguration(); + $refund_threshold = $threshold_config['refund_threshold']; + $threshold_enabled = $threshold_config['refund_threshold_enabled']; + + // Line 26: Crédit de TVA à rembourser (≥ threshold) + if ($line_25_amount > 0 && (!$threshold_enabled || $line_25_amount >= $refund_threshold)) { + $this->createCA3Line($declaration_id, '26', 'Crédit de TVA à rembourser (ligne 25 – ligne 26)', array( + 'base_amount' => 0, + 'vat_amount' => $line_25_amount, + 'total_amount' => $line_25_amount + )); + } else { + $this->createCA3Line($declaration_id, '26', 'Crédit de TVA à rembourser (ligne 25 – ligne 26)', array( + 'base_amount' => 0, + 'vat_amount' => 0, + 'total_amount' => 0 + )); + } + + // Line 27: Crédit de TVA à reporter (< threshold) $line_27_amount = $line_25_amount; // Same value as line 25 - if ($line_27_amount > 0 && $line_27_amount < 760) { + if ($line_25_amount > 0 && $threshold_enabled && $line_25_amount < $refund_threshold) { $this->createCA3Line($declaration_id, '27', 'Crédit de TVA à reporter (ligne 25 – ligne 26) (Cette somme est à reporter ligne 22 de la prochaine déclaration)', array( 'base_amount' => 0, 'vat_amount' => $line_27_amount, @@ -457,21 +479,6 @@ class DeclarationTVA )); } - // Line 26: Remboursement de crédit de TVA demandé sur formulaire n°3519 - same value as line 25, only if >= 760 - $line_26_amount = $line_25_amount; // Same value as line 25 - if ($line_26_amount >= 760) { - $this->createCA3Line($declaration_id, '26', 'Remboursement de crédit de TVA demandé sur formulaire n°3519', array( - 'base_amount' => 0, - 'vat_amount' => $line_26_amount, - 'total_amount' => $line_26_amount - )); - } else { - $this->createCA3Line($declaration_id, '26', 'Remboursement de crédit de TVA demandé sur formulaire n°3519', array( - 'base_amount' => 0, - 'vat_amount' => 0, - 'total_amount' => 0 - )); - } // Line TD: TVA due (ligne 16 – ligne 23) - only if > 0 $line_td_amount = $line_16_amount - $line_23_amount; @@ -868,6 +875,32 @@ class DeclarationTVA return $this->calculateCA3Amounts($declaration_id, $period); } + /** + * Get VAT credit carry-forward from previous periods + */ + public function getVATCreditCarryForward($declaration_start_date) + { + // Get journal configuration to use the correct account + require_once DOL_DOCUMENT_ROOT . '/custom/declarationtva/core/class/declarationtva_config.class.php'; + $config = new DeclarationTVA_Config($this->db, $this->entity); + $journal_config = $config->getJournalConfiguration(); + $vat_to_receive_account = $journal_config['vat_to_receive']; + + // Check VAT credit account balance at declaration start date + $sql = "SELECT SUM(debit - credit) as balance + FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping + WHERE account_number = '" . $this->db->escape($vat_to_receive_account) . "' + AND doc_date < '" . $declaration_start_date . "'"; + + $result = $this->db->query($sql); + if ($result && $this->db->num_rows($result) > 0) { + $obj = $this->db->fetch_object($result); + return max(0, $obj->balance); // Only positive balances (credits) + } + + return 0; + } + /** * Get account mappings with labels from chart of accounts * diff --git a/core/class/declarationtva_config.class.php b/core/class/declarationtva_config.class.php index 5d81017..25eabc4 100644 --- a/core/class/declarationtva_config.class.php +++ b/core/class/declarationtva_config.class.php @@ -717,7 +717,8 @@ class DeclarationTVA_Config { $default_config = array( 'vat_to_pay' => '44551', // TVA A DECAISSER - 'vat_to_receive' => '44567', // TVA A PAYER + 'vat_to_receive' => '44567', // TVA A PAYER (carry forward) + 'vat_refund' => '445671', // TVA A REMBOURSER (immediate refund) 'other_charges' => '658', // AUTRES CHARGES DE GESTION COURANTE 'other_products' => '758' // AUTRES PRODUITS DE GESTION COURANT ); @@ -729,7 +730,41 @@ class DeclarationTVA_Config return $config; } + + /** + * Get VAT refund threshold configuration + * + * @return array VAT refund threshold configuration + */ + public function getVATRefundThresholdConfiguration() + { + $default_config = array( + 'refund_threshold' => 760.00, // Threshold for immediate refund vs carry forward + 'refund_threshold_enabled' => 1 // Enable/disable threshold logic + ); + $config = array(); + foreach ($default_config as $key => $default_value) { + $config[$key] = $this->get('vat_refund_' . $key, $default_value); + } + + return $config; + } + + /** + * Update VAT refund threshold configuration + * + * @param array $threshold_config VAT refund threshold configuration + * @return bool Success + */ + public function updateVATRefundThresholdConfiguration($threshold_config) + { + foreach ($threshold_config as $key => $value) { + $this->set('vat_refund_' . $key, $value); + } + return true; + } + /** * Update journal configuration * diff --git a/core/class/declarationtva_pdf.class.php b/core/class/declarationtva_pdf.class.php index 9bf6b48..8690242 100644 --- a/core/class/declarationtva_pdf.class.php +++ b/core/class/declarationtva_pdf.class.php @@ -2352,7 +2352,7 @@ class DeclarationTVA_PDF } /** - * Get VAT result entry on account 4455100 or 4456700 + * Get VAT result entry using configured accounts and threshold * * @param DeclarationTVA $declaration Declaration object * @param array $ca3_lookup CA-3 data lookup array @@ -2360,52 +2360,82 @@ class DeclarationTVA_PDF */ private function getVATResultEntry($declaration, $ca3_lookup) { + // Get journal configuration + $journal_config = $this->getJournalConfiguration(); + $vat_to_pay_account = $journal_config['vat_to_pay']; + $vat_to_receive_account = $journal_config['vat_to_receive']; + $vat_refund_account = $journal_config['vat_refund']; + + // Get VAT refund threshold configuration + $threshold_config = $this->getVATRefundThresholdConfiguration(); + $refund_threshold = $threshold_config['refund_threshold']; + $threshold_enabled = $threshold_config['refund_threshold_enabled']; + // Get TD line amount (Line 16 - Line 23) $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 27 value and account 4456700 - if (abs($td_amount) < 0.01) { - $line27_amount = $this->getLineAmount($declaration, '27'); - - if (abs($line27_amount) < 0.01) { - return null; - } - - $entry = array( - 'account_code' => '4456700', - 'account_label' => $this->getAccountLabel('4456700'), + // If TD > 0, use VAT due account (445510) + if ($td_amount > 0) { + return array( + 'account_code' => $vat_to_pay_account, + 'account_label' => $this->getAccountLabel($vat_to_pay_account), 'entry_label' => $declaration->declaration_name, 'debit' => '', - 'credit' => '' + 'credit' => $this->formatAmount($td_amount) ); + } + + // If TD < 0, determine which credit account to use + if ($td_amount < 0) { + $vat_credit = abs($td_amount); - // Put line 23 amount on debit side - $line23_amount = $this->getLineAmount($declaration, '23'); - if ($line23_amount > 0) { - $entry['debit'] = $this->formatAmount($line23_amount); + // Check if threshold logic is enabled and amount is below threshold + if ($threshold_enabled && $vat_credit < $refund_threshold) { + // Use carry-forward account (445670) + $account_code = $vat_to_receive_account; + $account_label = $this->getAccountLabel($vat_to_receive_account); + } else { + // Use immediate refund account (445671) + $account_code = $vat_refund_account; + $account_label = $this->getAccountLabel($vat_refund_account); } - return $entry; + return array( + 'account_code' => $account_code, + 'account_label' => $account_label, + 'entry_label' => $declaration->declaration_name, + 'debit' => '', + 'credit' => $this->formatAmount($vat_credit) + ); } - // If TD > 0, use TD value and account 4455100 (existing logic) - $entry = array( - 'account_code' => '4455100', - 'account_label' => $this->getAccountLabel('4455100'), - 'entry_label' => $declaration->declaration_name, - 'debit' => '', - 'credit' => '' - ); - - if ($td_amount < 0) { - $entry['debit'] = $this->formatAmount(abs($td_amount)); - } else { - $entry['credit'] = $this->formatAmount($td_amount); - } - - return $entry; + return null; + } + + /** + * 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 VAT refund threshold configuration + * + * @return array VAT refund threshold configuration + */ + private function getVATRefundThresholdConfiguration() + { + require_once DOL_DOCUMENT_ROOT . '/custom/declarationtva/core/class/declarationtva_config.class.php'; + $config = new DeclarationTVA_Config($this->db, $this->entity); + return $config->getVATRefundThresholdConfiguration(); } /** diff --git a/langs/fr_FR/declarationtva.lang b/langs/fr_FR/declarationtva.lang index 122cdbd..30b9298 100644 --- a/langs/fr_FR/declarationtva.lang +++ b/langs/fr_FR/declarationtva.lang @@ -527,3 +527,7 @@ 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 +VATRefundThreshold = Seuil de remboursement TVA (€) +VATRefundThresholdEnabled = Activer la logique de seuil de remboursement TVA +VATRefundThresholdHelp = Seuil de montant pour le remboursement immédiat de la TVA vs report. Les montants en dessous de ce seuil seront reportés à la prochaine déclaration. +VATRefundThresholdEnabledHelp = Activer ou désactiver la logique de seuil pour les remboursements de TVA.