Content is user-generated and unverified.
<?php // Classe Template - Define o fluxo padrão de processamento abstract class ProcessadorNotaFiscal { // TEMPLATE METHOD - Define a sequência de passos public final function processarNotaFiscal(DadosNota $dados): string { echo "=== Iniciando processamento da Nota Fiscal ===\n"; // 1. Validações básicas (método concreto - comum a todos) if (!$this->validarDadosBasicos($dados)) { return "Erro: Dados básicos inválidos"; } // 2. Validações específicas (método abstrato - cada tipo implementa) if (!$this->validarDadosEspecificos($dados)) { return "Erro: Validação específica falhou"; } // 3. Calcular impostos (método abstrato - cada tipo tem sua regra) $impostos = $this->calcularImpostos($dados); $dados->setImpostos($impostos); // 4. Gerar XML (método abstrato - formato específico por tipo) $xml = $this->gerarXML($dados); // 5. Assinar digitalmente (método concreto - mesmo para todos) $xmlAssinado = $this->assinarDigitalmente($xml); // 6. Enviar para SEFAZ (hook method - pode ser sobrescrito) $this->enviarParaSEFAZ($xmlAssinado); // 7. Salvar no banco (método concreto - mesmo processo) $this->salvarNoBanco($dados, $xmlAssinado); echo "=== Processamento concluído ===\n"; return "Nota Fiscal processada com sucesso"; } // Método concreto - implementação padrão protected function validarDadosBasicos(DadosNota $dados): bool { return !empty($dados->getCnpjEmitente()) && $dados->getValorTotal() > 0 && !empty($dados->getItens()); } // Métodos abstratos - devem ser implementados pelas subclasses abstract protected function validarDadosEspecificos(DadosNota $dados): bool; abstract protected function calcularImpostos(DadosNota $dados): float; abstract protected function gerarXML(DadosNota $dados): string; // Método concreto - implementação padrão protected function assinarDigitalmente(string $xml): string { return "<assinatura>" . $xml . "</assinatura>"; } // Hook method - pode ser sobrescrito se necessário protected function enviarParaSEFAZ(string $xml): void { echo "Enviando para SEFAZ: " . substr($xml, 0, 50) . "...\n"; } // Método concreto - implementação padrão protected function salvarNoBanco(DadosNota $dados, string $xml): void { echo "Salvando nota no banco de dados...\n"; } } // Implementação para Nota Fiscal de Produto class ProcessadorNFeProduto extends ProcessadorNotaFiscal { protected function validarDadosEspecificos(DadosNota $dados): bool { // Validações específicas para produtos foreach ($dados->getItens() as $item) { if (empty($item->getNcm()) || strlen($item->getNcm()) !== 8) { echo "Erro: NCM inválido para produto\n"; return false; } if (empty($item->getCfop())) { echo "Erro: CFOP obrigatório para produtos\n"; return false; } } return true; } protected function calcularImpostos(DadosNota $dados): float { $totalImpostos = 0; foreach ($dados->getItens() as $item) { // ICMS para produtos $icms = $item->getValor() * 0.18; // 18% // IPI para produtos industrializados $ipi = $item->getValor() * 0.10; // 10% // PIS/COFINS $pisCofins = $item->getValor() * 0.0925; // 9,25% $totalImpostos += $icms + $ipi + $pisCofins; } echo "Impostos calculados para NFe Produto: R$ " . number_format($totalImpostos, 2, ',', '.') . "\n"; return $totalImpostos; } protected function gerarXML(DadosNota $dados): string { $xml = "<?xml version='1.0' encoding='UTF-8'?>"; $xml .= "<NFe xmlns='http://www.portalfiscal.inf.br/nfe'>"; $xml .= "<infNFe>"; $xml .= "<emit><CNPJ>" . $dados->getCnpjEmitente() . "</CNPJ></emit>"; foreach ($dados->getItens() as $item) { $xml .= "<det>"; $xml .= "<prod>"; $xml .= "<cProd>" . $item->getCodigo() . "</cProd>"; $xml .= "<xProd>" . $item->getDescricao() . "</xProd>"; $xml .= "<NCM>" . $item->getNcm() . "</NCM>"; $xml .= "<CFOP>" . $item->getCfop() . "</CFOP>"; $xml .= "<vProd>" . $item->getValor() . "</vProd>"; $xml .= "</prod>"; $xml .= "</det>"; } $xml .= "<total><vNF>" . $dados->getValorTotal() . "</vNF></total>"; $xml .= "</infNFe>"; $xml .= "</NFe>"; return $xml; } } // Implementação para Nota Fiscal de Serviço class ProcessadorNFSeServico extends ProcessadorNotaFiscal { protected function validarDadosEspecificos(DadosNota $dados): bool { // Validações específicas para serviços foreach ($dados->getItens() as $item) { if (empty($item->getCodigoServico())) { echo "Erro: Código do serviço obrigatório\n"; return false; } } if (empty($dados->getLocalPrestacao())) { echo "Erro: Local de prestação obrigatório\n"; return false; } return true; } protected function calcularImpostos(DadosNota $dados): float { $totalImpostos = 0; foreach ($dados->getItens() as $item) { // ISS para serviços $iss = $item->getValor() * 0.05; // 5% // PIS/COFINS $pisCofins = $item->getValor() * 0.0925; // 9,25% // IR e CSLL para alguns serviços $irCsll = $item->getValor() * 0.0465; // 4,65% $totalImpostos += $iss + $pisCofins + $irCsll; } echo "Impostos calculados para NFSe Serviço: R$ " . number_format($totalImpostos, 2, ',', '.') . "\n"; return $totalImpostos; } protected function gerarXML(DadosNota $dados): string { $xml = "<?xml version='1.0' encoding='UTF-8'?>"; $xml .= "<NFSe xmlns='http://www.abrasf.org.br/nfse.xsd'>"; $xml .= "<InfNfse>"; $xml .= "<PrestadorServico><Cnpj>" . $dados->getCnpjEmitente() . "</Cnpj></PrestadorServico>"; $xml .= "<TomadorServico><Cnpj>" . $dados->getCnpjDestinatario() . "</Cnpj></TomadorServico>"; foreach ($dados->getItens() as $item) { $xml .= "<Servico>"; $xml .= "<CodigoTributacaoMunicipio>" . $item->getCodigoServico() . "</CodigoTributacaoMunicipio>"; $xml .= "<Discriminacao>" . $item->getDescricao() . "</Discriminacao>"; $xml .= "<ValorServicos>" . $item->getValor() . "</ValorServicos>"; $xml .= "</Servico>"; } $xml .= "<ValorTotalServicos>" . $dados->getValorTotal() . "</ValorTotalServicos>"; $xml .= "</InfNfse>"; $xml .= "</NFSe>"; return $xml; } // Sobrescreve o hook method para NFSe protected function enviarParaSEFAZ(string $xml): void { echo "Enviando NFSe para Prefeitura Municipal...\n"; // Lógica específica para envio de NFSe } } // Implementação para Nota Fiscal Rural class ProcessadorNFProdutoRural extends ProcessadorNotaFiscal { protected function validarDadosEspecificos(DadosNota $dados): bool { // Validações específicas para produtos rurais if (empty($dados->getInscricaoEstadual())) { echo "Erro: Inscrição Estadual obrigatória para produtor rural\n"; return false; } foreach ($dados->getItens() as $item) { $descricao = strtolower($item->getDescricao()); if (strpos($descricao, 'rural') === false && strpos($descricao, 'agrícola') === false) { echo "Aviso: Item pode não ser produto rural\n"; } } return true; } protected function calcularImpostos(DadosNota $dados): float { $totalImpostos = 0; foreach ($dados->getItens() as $item) { // ICMS reduzido para produtos rurais $icms = $item->getValor() * 0.07; // 7% (reduzido) // Produtos rurais podem ter isenção de IPI $ipi = 0; // Isento // PIS/COFINS com alíquota diferenciada $pisCofins = $item->getValor() * 0.0365; // 3,65% $totalImpostos += $icms + $ipi + $pisCofins; } echo "Impostos calculados para NF Rural: R$ " . number_format($totalImpostos, 2, ',', '.') . "\n"; return $totalImpostos; } protected function gerarXML(DadosNota $dados): string { $xml = "<?xml version='1.0' encoding='UTF-8'?>"; $xml .= "<NFe xmlns='http://www.portalfiscal.inf.br/nfe'>"; $xml .= "<infNFe>"; $xml .= "<emit>"; $xml .= "<CNPJ>" . $dados->getCnpjEmitente() . "</CNPJ>"; $xml .= "<IE>" . $dados->getInscricaoEstadual() . "</IE>"; $xml .= "<CRT>1</CRT>"; // Simples Nacional $xml .= "</emit>"; foreach ($dados->getItens() as $item) { $xml .= "<det>"; $xml .= "<prod>"; $xml .= "<cProd>" . $item->getCodigo() . "</cProd>"; $xml .= "<xProd>" . $item->getDescricao() . " - PRODUTO RURAL</xProd>"; $xml .= "<NCM>" . $item->getNcm() . "</NCM>"; $xml .= "<CFOP>5101</CFOP>"; // CFOP típico para venda rural $xml .= "<vProd>" . $item->getValor() . "</vProd>"; $xml .= "</prod>"; $xml .= "</det>"; } $xml .= "<total><vNF>" . $dados->getValorTotal() . "</vNF></total>"; $xml .= "</infNFe>"; $xml .= "</NFe>"; return $xml; } } // Classes de apoio class DadosNota { private string $cnpjEmitente; private string $cnpjDestinatario; private ?string $inscricaoEstadual = null; private ?string $localPrestacao = null; private float $valorTotal; private float $impostos = 0; private array $itens; public function __construct(string $cnpjEmitente, string $cnpjDestinatario, float $valorTotal, array $itens) { $this->cnpjEmitente = $cnpjEmitente; $this->cnpjDestinatario = $cnpjDestinatario; $this->valorTotal = $valorTotal; $this->itens = $itens; } // Getters e Setters public function getCnpjEmitente(): string { return $this->cnpjEmitente; } public function getCnpjDestinatario(): string { return $this->cnpjDestinatario; } public function getInscricaoEstadual(): ?string { return $this->inscricaoEstadual; } public function setInscricaoEstadual(string $ie): void { $this->inscricaoEstadual = $ie; } public function getLocalPrestacao(): ?string { return $this->localPrestacao; } public function setLocalPrestacao(string $local): void { $this->localPrestacao = $local; } public function getValorTotal(): float { return $this->valorTotal; } public function getImpostos(): float { return $this->impostos; } public function setImpostos(float $impostos): void { $this->impostos = $impostos; } public function getItens(): array { return $this->itens; } } class ItemNota { private string $codigo; private string $descricao; private float $valor; private ?string $ncm = null; private ?string $cfop = null; private ?string $codigoServico = null; public function __construct(string $codigo, string $descricao, float $valor) { $this->codigo = $codigo; $this->descricao = $descricao; $this->valor = $valor; } // Getters e Setters public function getCodigo(): string { return $this->codigo; } public function getDescricao(): string { return $this->descricao; } public function getValor(): float { return $this->valor; } public function getNcm(): ?string { return $this->ncm; } public function setNcm(string $ncm): void { $this->ncm = $ncm; } public function getCfop(): ?string { return $this->cfop; } public function setCfop(string $cfop): void { $this->cfop = $cfop; } public function getCodigoServico(): ?string { return $this->codigoServico; } public function setCodigoServico(string $codigoServico): void { $this->codigoServico = $codigoServico; } } // Factory para seleção do processador class ProcessadorFactory { public static function criar(string $tipo): ProcessadorNotaFiscal { switch ($tipo) { case 'NFE_PRODUTO': return new ProcessadorNFeProduto(); case 'NFSE_SERVICO': return new ProcessadorNFSeServico(); case 'NF_RURAL': return new ProcessadorNFProdutoRural(); default: throw new InvalidArgumentException("Tipo não suportado: $tipo"); } } } // Controller para API REST class NotaFiscalController { public function processarNota(array $request): array { try { $processador = ProcessadorFactory::criar($request['tipo']); $resultado = $processador->processarNotaFiscal($request['dados']); return [ 'status' => 'success', 'message' => $resultado, 'timestamp' => date('Y-m-d H:i:s') ]; } catch (Exception $e) { return [ 'status' => 'error', 'message' => $e->getMessage(), 'timestamp' => date('Y-m-d H:i:s') ]; } } } // Exemplo de uso echo "=== DEMONSTRAÇÃO DO TEMPLATE METHOD EM PHP ===\n\n"; try { // Preparar dados para NFe de Produto $itensProduto = [ new ItemNota("001", "Notebook Dell", 2500.00), new ItemNota("002", "Mouse Logitech", 50.00) ]; // Configurar dados específicos para produtos $itensProduto[0]->setNcm("84713012"); $itensProduto[0]->setCfop("5102"); $itensProduto[1]->setNcm("84716060"); $itensProduto[1]->setCfop("5102"); $dadosNFe = new DadosNota("12345678000123", "98765432000187", 2550.00, $itensProduto); // Processar NFe de Produto echo "1. PROCESSANDO NFe DE PRODUTO:\n"; echo str_repeat("-", 50) . "\n"; $processadorNFe = new ProcessadorNFeProduto(); $resultadoNFe = $processadorNFe->processarNotaFiscal($dadosNFe); echo "Resultado NFe: $resultadoNFe\n\n"; // Preparar dados para NFSe de Serviço $itensServico = [ new ItemNota("SERV001", "Consultoria em TI", 1500.00), new ItemNota("SERV002", "Desenvolvimento de Sistema", 3000.00) ]; // Configurar dados específicos para serviços $itensServico[0]->setCodigoServico("01.01"); $itensServico[1]->setCodigoServico("01.02"); $dadosNFSe = new DadosNota("12345678000123", "98765432000187", 4500.00, $itensServico); $dadosNFSe->setLocalPrestacao("São Paulo/SP"); // Processar NFSe de Serviço echo "2. PROCESSANDO NFSe DE SERVIÇO:\n"; echo str_repeat("-", 50) . "\n"; $processadorNFSe = new ProcessadorNFSeServico(); $resultadoNFSe = $processadorNFSe->processarNotaFiscal($dadosNFSe); echo "Resultado NFSe: $resultadoNFSe\n\n"; // Preparar dados para NF Rural $itensRural = [ new ItemNota("RURAL001", "Soja em grão rural", 5000.00), new ItemNota("RURAL002", "Milho agrícola", 2000.00) ]; // Configurar dados específicos para produtos rurais $itensRural[0]->setNcm("12019000"); $itensRural[1]->setNcm("10051000"); $dadosRural = new DadosNota("12345678000123", "98765432000187", 7000.00, $itensRural); $dadosRural->setInscricaoEstadual("123456789"); // Processar NF Rural echo "3. PROCESSANDO NF RURAL:\n"; echo str_repeat("-", 50) . "\n"; $processadorRural = new ProcessadorNFProdutoRural(); $resultadoRural = $processadorRural->processarNotaFiscal($dadosRural); echo "Resultado NF Rural: $resultadoRural\n\n"; // Exemplo usando Factory e Controller echo "4. EXEMPLO COM FACTORY E CONTROLLER:\n"; echo str_repeat("-", 50) . "\n"; $controller = new NotaFiscalController(); $request = [ 'tipo' => 'NFE_PRODUTO', 'dados' => $dadosNFe ]; $response = $controller->processarNota($request); echo "Response do Controller:\n"; echo json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "\n"; } catch (Exception $e) { echo "Erro durante execução: " . $e->getMessage() . "\n"; } ?> <!-- === COMO INTEGRAR COM FRAMEWORK WEB === // Laravel Route Route::post('/api/notas-fiscais/processar', [NotaFiscalController::class, 'processarNota']); // Symfony Controller #[Route('/api/notas-fiscais/processar', methods: ['POST'])] public function processarNota(Request $request): JsonResponse { $dados = json_decode($request->getContent(), true); $controller = new NotaFiscalController(); $resultado = $controller->processarNota($dados); return new JsonResponse($resultado); } // CodeIgniter 4 public function processar() { $dados = $this->request->getJSON(true); $controller = new NotaFiscalController(); $resultado = $controller->processarNota($dados); return $this->response->setJSON($resultado); } -->
Content is user-generated and unverified.
    Template Method - Portal de Notas Fiscais | Claude