diff --git a/core/class/declarationtva.class.php b/core/class/declarationtva.class.php index 7c6fe28..4ef352f 100644 --- a/core/class/declarationtva.class.php +++ b/core/class/declarationtva.class.php @@ -764,21 +764,6 @@ class DeclarationTVA 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 @@ -1005,4 +990,118 @@ class DeclarationTVA 'account_count' => count($details) ); } + + /** + * Validate a 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', + validated_date = NOW(), + validated_by = " . $this->db->escape($GLOBALS['user']->id) . " + WHERE rowid = " . (int)$declaration_id . " + AND entity = " . $this->entity; + + $result = $this->db->query($sql); + if ($result) { + return true; + } else { + $this->error = $this->db->lasterror(); + return false; + } + } + + /** + * Save validated PDF to Dolibarr documents + * + * @param int $declaration_id Declaration ID + * @param string $pdf_path Path to the PDF file + * @return bool Success + */ + public function saveValidatedPDF($declaration_id, $pdf_path) + { + global $conf, $user; + + // Create documents directory if it doesn't exist + $doc_dir = DOL_DATA_ROOT . '/declarationtva/validated/'; + if (!is_dir($doc_dir)) { + dol_mkdir($doc_dir); + } + + // Generate filename + $filename = 'CA3_Validated_' . $this->declaration_number . '_' . date('Y-m-d') . '.pdf'; + $dest_path = $doc_dir . $filename; + + // Copy PDF to documents directory + if (copy($pdf_path, $dest_path)) { + // Add document record to Dolibarr + require_once DOL_DOCUMENT_ROOT . '/core/class/ecmfiles.class.php'; + $ecmfile = new EcmFiles($this->db); + + $ecmfile->filepath = 'declarationtva/validated/'; + $ecmfile->filename = $filename; + $ecmfile->label = 'CA-3 Validated Declaration - ' . $this->declaration_number; + $ecmfile->description = 'Validated CA-3 declaration with detailed breakdown'; + $ecmfile->entity = $this->entity; + $ecmfile->fk_user_author = $user->id; + $ecmfile->fk_user_modif = $user->id; + $ecmfile->datec = dol_now(); + $ecmfile->tms = dol_now(); + $ecmfile->mimetype = 'application/pdf'; + $ecmfile->filesize = filesize($dest_path); + $ecmfile->checksum = md5_file($dest_path); + + $result = $ecmfile->create($user); + if ($result > 0) { + // Link document to declaration + $this->linkDocumentToDeclaration($declaration_id, $ecmfile->id); + return true; + } + } + + return false; + } + + /** + * Link document to declaration + * + * @param int $declaration_id Declaration ID + * @param int $document_id Document ID + * @return bool Success + */ + private function linkDocumentToDeclaration($declaration_id, $document_id) + { + $sql = "INSERT INTO " . MAIN_DB_PREFIX . "declarationtva_documents + (declaration_id, document_id, created_date) + VALUES (" . (int)$declaration_id . ", " . (int)$document_id . ", NOW())"; + + return $this->db->query($sql); + } + + /** + * Check if declaration has a validated document + * + * @param int $declaration_id Declaration ID + * @return bool Has document + */ + public function hasValidatedDocument($declaration_id) + { + $sql = "SELECT COUNT(*) as count + FROM " . MAIN_DB_PREFIX . "declarationtva_documents dd + INNER JOIN " . MAIN_DB_PREFIX . "ecm_files ef ON dd.document_id = ef.rowid + WHERE dd.declaration_id = " . (int)$declaration_id . " + AND dd.entity = " . $this->entity; + + $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; + } } diff --git a/declarationtva_view.php b/declarationtva_view.php index f1b35d0..cbaf062 100644 --- a/declarationtva_view.php +++ b/declarationtva_view.php @@ -98,6 +98,25 @@ if ($action == 'export_pdf_detailed') { } } +if ($action == 'validate' && $token) { + // Validate the declaration + if ($declarationtva->validateDeclaration($id)) { + setEventMessages($langs->trans("DeclarationValidated"), null, 'mesgs'); + + // Generate and save detailed PDF to Dolibarr documents + require_once DOL_DOCUMENT_ROOT . '/custom/declarationtva/core/class/declarationtva_pdf.class.php'; + $pdf_generator = new DeclarationTVA_PDF($db); + + $pdf_path = $pdf_generator->generateDetailedCA3PDF($id); + if ($pdf_path && file_exists($pdf_path)) { + // Save PDF to Dolibarr documents + $declarationtva->saveValidatedPDF($id, $pdf_path); + } + } else { + setEventMessages($langs->trans("ErrorValidatingDeclaration"), null, 'errors'); + } +} + // Fetch declaration if ($declarationtva->fetch($id) < 0) { setEventMessages($langs->trans("DeclarationNotFound"), null, 'errors'); @@ -409,15 +428,18 @@ print '
' . $langs->trans("Actions") . '
'; print '
'; -// Recalculate button (always available) -print '' . $langs->trans("Recalculate") . ' '; +// Recalculate button (only for draft status) +if ($declarationtva->status == 'draft') { + print '' . $langs->trans("Recalculate") . ' '; +} // PDF Export buttons (always available) print '' . $langs->trans("ExportPDF") . ' '; print '' . $langs->trans("ExportPDFDetailed") . ' '; if ($declarationtva->status == 'draft') { - print '' . $langs->trans("Validate") . ' '; + // Validation button with confirmation dialog + print '' . $langs->trans("Validate") . ' '; } elseif ($declarationtva->status == 'validated') { print '' . $langs->trans("Submit") . ' '; } @@ -520,6 +542,38 @@ function loadLineDetails(line) { }; xhr.send(); } + +function confirmValidation(declarationId) { + // Create confirmation dialog + var dialog = document.createElement("div"); + dialog.style.cssText = "position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 10000; display: flex; align-items: center; justify-content: center;"; + + var dialogContent = document.createElement("div"); + dialogContent.style.cssText = "background: white; padding: 20px; border-radius: 5px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); max-width: 500px; text-align: center;"; + + dialogContent.innerHTML = ` +

' . $langs->trans("ConfirmValidation") . '

+

' . $langs->trans("ValidationConfirmationMessage") . '

+
+ + +
+ `; + + dialog.appendChild(dialogContent); + document.body.appendChild(dialog); +} + +function proceedValidation(declarationId) { + // Redirect to validation action + window.location.href = "' . $_SERVER['PHP_SELF'] . '?id=" + declarationId + "&action=validate&token=' . newToken() . '"; +} '; // Print footer diff --git a/declarationtvaindex.php b/declarationtvaindex.php index f98eedc..d67d56b 100644 --- a/declarationtvaindex.php +++ b/declarationtvaindex.php @@ -123,6 +123,7 @@ if (empty($declarations)) { print '' . $langs->trans("Period") . ''; print '' . $langs->trans("Status") . ''; print '' . $langs->trans("NetVATDue") . ''; + print '' . $langs->trans("Document") . ''; print '' . $langs->trans("Actions") . ''; print ''; @@ -130,8 +131,33 @@ if (empty($declarations)) { print ''; print '' . $d['declaration_number'] . ''; print '' . dol_print_date($d['start_date'], 'day') . ' - ' . dol_print_date($d['end_date'], 'day') . ''; - print '' . $langs->trans("Status" . ucfirst($d['status'])) . ''; + + // Status with icon + $status_icon = ''; + if ($d['status'] == 'validated') { + $status_icon = ' '; + } elseif ($d['status'] == 'draft') { + $status_icon = ' '; + } + print '' . $langs->trans("Status" . ucfirst($d['status'])) . $status_icon . ''; + print '' . price($d['net_vat_due']) . ''; + + // Document column + print ''; + if ($d['status'] == 'validated') { + // Check if document exists + $has_document = $declarationtva->hasValidatedDocument($d['rowid']); + if ($has_document) { + print ''; + } else { + print ''; + } + } else { + print ''; + } + print ''; + print ''; if ($d['status'] == 'draft') { diff --git a/langs/en_US/declarationtva.lang b/langs/en_US/declarationtva.lang index 76b23cb..d3a1df6 100644 --- a/langs/en_US/declarationtva.lang +++ b/langs/en_US/declarationtva.lang @@ -492,3 +492,19 @@ TemplateResetFailed = Error resetting to official template ErrorGeneratingPDF = Error generating PDF TemplateUpdated = Template updated successfully TemplateUpdateFailed = Error updating template + +# Validation +Validate = Validate +ConfirmValidation = Confirm Validation +ValidationConfirmationMessage = Are you sure you want to validate this declaration? This action is irreversible and will automatically generate the detailed PDF. +YesValidate = Yes, validate +Cancel = Cancel +DeclarationValidated = Declaration validated successfully +ErrorValidatingDeclaration = Error validating declaration + +# Document and status icons +Document = Document +ValidatedDeclaration = Validated Declaration +DraftDeclaration = Draft Declaration +ValidatedPDFAvailable = Validated PDF Available +NoDocument = No Document diff --git a/langs/fr_FR/declarationtva.lang b/langs/fr_FR/declarationtva.lang index bddf4c6..f1c519b 100644 --- a/langs/fr_FR/declarationtva.lang +++ b/langs/fr_FR/declarationtva.lang @@ -464,3 +464,19 @@ TemplateResetFailed = Erreur lors du retour au modèle officiel ErrorGeneratingPDF = Erreur lors de la génération du PDF TemplateUpdated = Modèle mis à jour avec succès TemplateUpdateFailed = Erreur lors de la mise à jour du modèle + +# Validation +Validate = Valider +ConfirmValidation = Confirmer la validation +ValidationConfirmationMessage = Êtes-vous sûr de vouloir valider cette déclaration ? Cette action est irréversible et générera automatiquement le PDF détaillé. +YesValidate = Oui, valider +Cancel = Annuler +DeclarationValidated = Déclaration validée avec succès +ErrorValidatingDeclaration = Erreur lors de la validation de la déclaration + +# Document and status icons +Document = Document +ValidatedDeclaration = Déclaration validée +DraftDeclaration = Déclaration brouillon +ValidatedPDFAvailable = PDF validé disponible +NoDocument = Aucun document diff --git a/sql/migration_add_documents_table.sql b/sql/migration_add_documents_table.sql new file mode 100644 index 0000000..504ecb1 --- /dev/null +++ b/sql/migration_add_documents_table.sql @@ -0,0 +1,26 @@ +-- Migration: Add documents table for linking validated PDFs to declarations +-- Version: 2.1.0 +-- Date: 2025-01-06 + +-- Create table for linking documents to declarations +CREATE TABLE IF NOT EXISTS `llx_declarationtva_documents` ( + `rowid` int(11) NOT NULL AUTO_INCREMENT, + `declaration_id` int(11) NOT NULL, + `document_id` int(11) NOT NULL, + `created_date` datetime NOT NULL, + `entity` int(11) NOT NULL DEFAULT 1, + PRIMARY KEY (`rowid`), + KEY `idx_declaration_id` (`declaration_id`), + KEY `idx_document_id` (`document_id`), + KEY `idx_entity` (`entity`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- Add validated_date and validated_by columns to declarations table if they don't exist +ALTER TABLE `llx_declarationtva_declarations` +ADD COLUMN IF NOT EXISTS `validated_date` datetime DEFAULT NULL, +ADD COLUMN IF NOT EXISTS `validated_by` int(11) DEFAULT NULL; + +-- Add indexes for performance +ALTER TABLE `llx_declarationtva_declarations` +ADD INDEX IF NOT EXISTS `idx_validated_date` (`validated_date`), +ADD INDEX IF NOT EXISTS `idx_validated_by` (`validated_by`);