diff --git a/samples/CalculatorMod.php.sample b/samples/CalculatorMod.php.sample index 140598a..62849af 100644 --- a/samples/CalculatorMod.php.sample +++ b/samples/CalculatorMod.php.sample @@ -5,71 +5,71 @@ namespace FacturaScripts\[[NAME_SPACE]]\Mod; use FacturaScripts\Core\Template\CalculatorModClass; use FacturaScripts\Core\Model\Base\BusinessDocument; use FacturaScripts\Core\Model\Base\BusinessDocumentLine; -use FacturaScripts\Core\Model\RegimenIVA; /** * Mod para modificar los cálculos de totales y subtotales de los albaranes, facturas, etc. - * + * * @see https://facturascripts.com/publicaciones/como-modificar-el-calculator-desde-un-plugin */ -class [[NAME]] implements CalculatorModClass +class [[NAME]] extends CalculatorModClass { - /** @var string */ - private $regimenIVA; - /** - * Podemos utilizar apply para aplicar configuraciones o precargar datos. + * Se ejecuta antes de los cálculos. Útil para precargar datos del documento. */ - public function apply(BusinessDocument &$doc, array &$lines): bool + public function apply(BusinessDocument $doc, array &$lines): string { - // Obtener y guardar el régimen de IVA una sola vez - // $subject = $doc->getSubject(); - // $this->regimenIVA = $subject->regimeniva ?? RegimenIVA::TAX_SYSTEM_GENERAL; - return true; + return $this->done(); } /** - * La función calculate se usa para recalcular el total del documento. + * Se ejecuta para recalcular el total del documento. */ - public function calculate(BusinessDocument &$doc, array &$lines): bool + public function calculate(BusinessDocument $doc, array &$lines): string { // $doc->total = 'aquí tu cálculo'; - return true; + return $this->done(); } /** - * Para recalcular las líneas de los documentos se usa calculateLine. + * Se ejecuta para recalcular cada línea del documento. */ - public function calculateLine(BusinessDocument $doc, BusinessDocumentLine &$line): bool + public function calculateLine(BusinessDocument $doc, BusinessDocumentLine $line): string { // $line->pvptotal = 'aquí tu cálculo'; - return true; + return $this->done(); + } + + /** + * Se ejecuta para inicializar los totales del documento a 0. + */ + public function clear(BusinessDocument $doc, array &$lines): string + { + return $this->done(); } /** - * Para inicializar los registros se usa clear. Normalmente se inicializan todos los valores a 0, - * aunque si es necesario se puede utilizar otro valor. + * Se ejecuta para acumular subtotales (neto, iva, etc.) desde las líneas. */ - public function clear(BusinessDocument &$doc, array &$lines): bool + public function accumulateSubtotals(array &$subtotals, BusinessDocument $doc, array &$lines): string { - /* - $doc->total = 0.0; - - foreach ($lines as $line) { - $line->total = 0.0; - } - */ - - return true; + return $this->done(); } /** - * Para modificar los subtotales se utiliza getSubtotals, donde los subtotales se especifican mediante un array. + * Se ejecuta para modificar los subtotales finales del documento. */ - public function getSubtotals(array &$subtotals, BusinessDocument $doc, array $lines) + public function updateSubtotals(array &$subtotals, BusinessDocument $doc, array $lines): string { // $subtotals['neto'] += 10; // $subtotals['total'] += 10; - return true; + return $this->done(); + } + + /** + * Se ejecuta al guardar el documento. + */ + public function save(BusinessDocument $doc, array &$lines): string + { + return $this->done(); } } diff --git a/src/Command/Generator/UpgradeCommand.php b/src/Command/Generator/UpgradeCommand.php index 507bb53..e7efa72 100644 --- a/src/Command/Generator/UpgradeCommand.php +++ b/src/Command/Generator/UpgradeCommand.php @@ -28,6 +28,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int FileUpdater::upgradeXmlFiles(); FileUpdater::upgradeTwigFiles(); FileUpdater::upgradeIniFile(); + FileUpdater::flushWarnings(); return Command::SUCCESS; } diff --git a/src/Command/Mod/ModCommand.php b/src/Command/Mod/ModCommand.php index 2067e82..fd2f42a 100644 --- a/src/Command/Mod/ModCommand.php +++ b/src/Command/Mod/ModCommand.php @@ -85,9 +85,13 @@ private function createMod(string $name, string $sampleName, string $useClass, s // Escribir en Init.php $use = 'use ' . $useClass . ';'; $newInitContent = InitEditor::addUse($use); - InitEditor::setInitContent($newInitContent); + if ($newInitContent !== null) { + InitEditor::setInitContent($newInitContent); + } $newInitContent = InitEditor::addToInitFunction($initCode); - InitEditor::setInitContent($newInitContent); + if ($newInitContent !== null) { + InitEditor::setInitContent($newInitContent); + } return Command::SUCCESS; } diff --git a/src/FileUpdater.php b/src/FileUpdater.php index 78a7b7a..985e4a5 100644 --- a/src/FileUpdater.php +++ b/src/FileUpdater.php @@ -9,6 +9,24 @@ final class FileUpdater { const OK = " -> OK.\n"; + private static array $warnings = []; + + public static function flushWarnings(): void + { + if (empty(self::$warnings)) { + return; + } + + Utils::echo("\n⚠️ AVISOS IMPORTANTES — requieren revisión manual:\n"); + Utils::echo(str_repeat('-', 60) . "\n"); + foreach (self::$warnings as $warning) { + Utils::echo($warning); + } + Utils::echo(str_repeat('-', 60) . "\n"); + + self::$warnings = []; + } + private const WHERE_FACTORY_MAP = [ '=' => ['and' => 'eq', 'or' => 'orEq'], '!=' => ['and' => 'notEq', 'or' => 'orNotEq'], @@ -259,6 +277,56 @@ public static function upgradePhpFiles(): void // reemplazamos contratos $fileStr = str_replace('use FacturaScripts\Core\Base\Contract\CalculatorModInterface;', 'use FacturaScripts\Core\Contract\CalculatorModInterface;', $fileStr); + + // migramos CalculatorModInterface (deprecado) a CalculatorModClass + if (strpos($fileStr, 'use FacturaScripts\Core\Contract\CalculatorModInterface;') !== false) { + $fileStr = str_replace( + 'use FacturaScripts\Core\Contract\CalculatorModInterface;', + 'use FacturaScripts\Core\Template\CalculatorModClass;', + $fileStr + ); + $fileStr = str_replace('implements CalculatorModInterface', 'extends CalculatorModClass', $fileStr); + + // normalizamos firmas de los métodos del Calculator (quitar & en $doc/$line, bool -> string) + $calcSignaturePatterns = [ + '/(public\s+function\s+apply\s*\(\s*BusinessDocument\s*)&(\s*\$doc\b[^)]*\))\s*:\s*bool/' => '$1$2: string', + '/(public\s+function\s+calculate\s*\(\s*BusinessDocument\s*)&(\s*\$doc\b[^)]*\))\s*:\s*bool/' => '$1$2: string', + '/(public\s+function\s+calculateLine\s*\([^)]*BusinessDocumentLine\s*)&(\s*\$line\s*\))\s*:\s*bool/' => '$1$2: string', + '/(public\s+function\s+clear\s*\(\s*BusinessDocument\s*)&(\s*\$doc\b[^)]*\))\s*:\s*bool/' => '$1$2: string', + '/(public\s+function\s+getSubtotals\s*\([^)]*\))\s*:\s*bool/' => '$1: string', + ]; + foreach ($calcSignaturePatterns as $pattern => $replacement) { + $fileStr = preg_replace($pattern, $replacement, $fileStr); + } + + // añadimos TODO encima de return true/false para que el dev complete la migración + if (strpos($fileStr, '// TODO: reemplazar por $this->done()') === false) { + $fileStr = preg_replace( + '/^(\s+)(return true;)/m', + '$1// TODO: reemplazar por $this->done()' . "\n" . '$1$2', + $fileStr + ); + } + if (strpos($fileStr, '// TODO: reemplazar por $this->stopAll()') === false) { + $fileStr = preg_replace( + '/^(\s+)(return false;)/m', + '$1// TODO: reemplazar por $this->stopAll() o $this->stopMods()' . "\n" . '$1$2', + $fileStr + ); + } + + self::$warnings[] = + " * AVISO en " . $pathFile . ": \n" . + " se ha migrado CalculatorModInterface -> CalculatorModClass.\n" . + " Se han corregido automáticamente:\n" . + " - use e implements/extends\n" . + " - firmas de métodos (& en \$doc/\$line eliminado, bool -> string)\n" . + " Revisa manualmente:\n" . + " - Los TODO encima de cada return true/false (cambiar a \$this->done(), etc.)\n" . + " - getSubtotals (reemplazado en el core por accumulateSubtotals/updateSubtotals)\n" . + " Más info: https://facturascripts.com/publicaciones/como-modificar-el-calculator-desde-un-plugin\n"; + } + $fileStr = str_replace('use FacturaScripts\Core\Base\Contract\PurchasesLineModInterface;', 'use FacturaScripts\Core\Contract\PurchasesLineModInterface;', $fileStr); $fileStr = str_replace('use FacturaScripts\Core\Base\Contract\PurchasesModInterface;', 'use FacturaScripts\Core\Contract\PurchasesModInterface;', $fileStr); $fileStr = str_replace('use FacturaScripts\Core\Base\Contract\SalesLineModInterface;', 'use FacturaScripts\Core\Contract\SalesLineModInterface;', $fileStr);