Skip to main content

nfe_parser/base/
nfse.rs

1//! NFS-e - Nota Fiscal de Serviços Eletrônica
2//!
3//! Este módulo contém estruturas para representar NFS-e conforme padrão ABRASF 2.04
4//! e suporte a integrações com sistemas municipais.
5//!
6//! ## Importante
7//!
8//! A NFS-e não é padronizada nacionalmente. Cada município pode adotar um sistema
9//! diferente. Os padrões mais comuns são:
10//!
11//! - **ABRASF 1.0 / 2.0 / 2.04**: Padrão nacional mais adotado
12//! - **Ginfes**: Sistema da Tecnos
13//! - **ISSNet**: Sistema da ISSNet
14//! - **Betha**: Sistema da Betha Sistemas
15//! - **IPM**: Sistema da IPM Informática
16//! - **GISS Online**: Sistema de várias prefeituras (Matão, Araraquara, etc.)
17
18use serde::{Deserialize, Serialize};
19
20/// Nota Fiscal de Serviços Eletrônica
21#[derive(Debug, Clone, Serialize, Deserialize)]
22pub struct Nfse {
23    /// Identificação da NFS-e
24    pub identificacao: IdentificacaoNfse,
25    /// Dados do prestador de serviços
26    pub prestador: PrestadorServico,
27    /// Dados do tomador de serviços
28    pub tomador: Option<TomadorServico>,
29    /// Intermediário do serviço (se houver)
30    pub intermediario: Option<IntermediarioServico>,
31    /// Dados do serviço prestado
32    pub servico: ServicoNfse,
33    /// Valores da NFS-e
34    pub valores: ValoresNfse,
35    /// Informações complementares
36    pub informacoes_complementares: Option<String>,
37}
38
39/// Identificação da NFS-e
40#[derive(Debug, Clone, Serialize, Deserialize)]
41pub struct IdentificacaoNfse {
42    /// Número da NFS-e
43    pub numero: u64,
44    /// Código de verificação
45    pub codigo_verificacao: String,
46    /// Data de emissão
47    pub data_emissao: String,
48    /// Competência (mês/ano de referência)
49    pub competencia: String,
50    /// Número do RPS que originou a NFS-e (se houver)
51    pub numero_rps: Option<u64>,
52    /// Série do RPS
53    pub serie_rps: Option<String>,
54    /// Tipo do RPS (1=RPS, 2=Nota Fiscal Conjugada, 3=Cupom)
55    pub tipo_rps: Option<u8>,
56    /// Natureza da operação
57    pub natureza_operacao: NaturezaOperacaoNfse,
58    /// Regime especial de tributação
59    pub regime_especial: Option<RegimeEspecialNfse>,
60    /// Optante pelo Simples Nacional
61    pub optante_simples_nacional: bool,
62    /// Incentivador cultural
63    pub incentivador_cultural: bool,
64    /// Status da NFS-e
65    pub status: StatusNfse,
66}
67
68/// Natureza da operação para NFS-e
69#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
70#[repr(u8)]
71pub enum NaturezaOperacaoNfse {
72    /// Tributação no município
73    TributacaoMunicipio = 1,
74    /// Tributação fora do município
75    TributacaoForaMunicipio = 2,
76    /// Isenção
77    Isencao = 3,
78    /// Imune
79    Imune = 4,
80    /// Exigibilidade suspensa por decisão judicial
81    SuspensaJudicial = 5,
82    /// Exigibilidade suspensa por procedimento administrativo
83    SuspensaAdministrativo = 6,
84}
85
86/// Regime especial de tributação
87#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
88#[repr(u8)]
89pub enum RegimeEspecialNfse {
90    /// Microempresa Municipal
91    MicroempresaMunicipal = 1,
92    /// Estimativa
93    Estimativa = 2,
94    /// Sociedade de Profissionais
95    SociedadeProfissionais = 3,
96    /// Cooperativa
97    Cooperativa = 4,
98    /// MEI - Microempreendedor Individual
99    Mei = 5,
100    /// ME EPP - Simples Nacional
101    MeEppSimplesNacional = 6,
102}
103
104/// Status da NFS-e
105#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
106pub enum StatusNfse {
107    /// Normal
108    Normal,
109    /// Cancelada
110    Cancelada,
111    /// Substituída
112    Substituida,
113}
114
115/// Prestador de serviços
116#[derive(Debug, Clone, Serialize, Deserialize)]
117pub struct PrestadorServico {
118    /// CNPJ do prestador
119    pub cnpj: String,
120    /// Inscrição Municipal
121    pub inscricao_municipal: Option<String>,
122    /// Razão Social
123    pub razao_social: String,
124    /// Nome Fantasia
125    pub nome_fantasia: Option<String>,
126    /// Endereço
127    pub endereco: EnderecoNfse,
128    /// Telefone
129    pub telefone: Option<String>,
130    /// Email
131    pub email: Option<String>,
132}
133
134/// Tomador de serviços
135#[derive(Debug, Clone, Serialize, Deserialize)]
136pub struct TomadorServico {
137    /// Tipo de documento (1=CPF, 2=CNPJ)
138    pub tipo_documento: u8,
139    /// CPF ou CNPJ do tomador
140    pub documento: String,
141    /// Inscrição Municipal (se contribuinte)
142    pub inscricao_municipal: Option<String>,
143    /// Inscrição Estadual (se contribuinte)
144    pub inscricao_estadual: Option<String>,
145    /// Razão Social / Nome
146    pub razao_social: String,
147    /// Endereço
148    pub endereco: Option<EnderecoNfse>,
149    /// Telefone
150    pub telefone: Option<String>,
151    /// Email
152    pub email: Option<String>,
153}
154
155/// Intermediário do serviço
156#[derive(Debug, Clone, Serialize, Deserialize)]
157pub struct IntermediarioServico {
158    /// Tipo de documento (1=CPF, 2=CNPJ)
159    pub tipo_documento: u8,
160    /// CPF ou CNPJ
161    pub documento: String,
162    /// Razão Social / Nome
163    pub razao_social: String,
164    /// Inscrição Municipal
165    pub inscricao_municipal: Option<String>,
166}
167
168/// Endereço para NFS-e
169#[derive(Debug, Clone, Serialize, Deserialize)]
170pub struct EnderecoNfse {
171    /// Logradouro
172    pub logradouro: String,
173    /// Número
174    pub numero: String,
175    /// Complemento
176    pub complemento: Option<String>,
177    /// Bairro
178    pub bairro: String,
179    /// Código do município (IBGE)
180    pub codigo_municipio: String,
181    /// Nome do município
182    pub municipio: String,
183    /// UF
184    pub uf: String,
185    /// CEP
186    pub cep: String,
187    /// Código do país (1058 = Brasil)
188    pub codigo_pais: Option<String>,
189}
190
191/// Dados do serviço prestado
192#[derive(Debug, Clone, Serialize, Deserialize)]
193pub struct ServicoNfse {
194    /// Código do serviço conforme LC 116/2003
195    pub codigo_servico: String,
196    /// Código CNAE
197    pub codigo_cnae: Option<String>,
198    /// Código do serviço no município
199    pub codigo_servico_municipio: Option<String>,
200    /// Código tributação no município
201    pub codigo_tributacao_municipio: Option<String>,
202    /// Discriminação do serviço
203    pub discriminacao: String,
204    /// Código do município onde o serviço foi prestado
205    pub municipio_prestacao: String,
206    /// Código do país (se exterior)
207    pub codigo_pais: Option<String>,
208    /// Código de obra (construção civil)
209    pub codigo_obra: Option<String>,
210    /// ART da obra (construção civil)
211    pub art: Option<String>,
212}
213
214/// Valores da NFS-e
215#[derive(Debug, Clone, Serialize, Deserialize)]
216pub struct ValoresNfse {
217    /// Valor dos serviços
218    pub valor_servicos: f32,
219    /// Valor das deduções
220    pub valor_deducoes: f32,
221    /// Valor do PIS
222    pub valor_pis: f32,
223    /// Valor da COFINS
224    pub valor_cofins: f32,
225    /// Valor do INSS
226    pub valor_inss: f32,
227    /// Valor do IR
228    pub valor_ir: f32,
229    /// Valor da CSLL
230    pub valor_csll: f32,
231    /// Outras retenções
232    pub outras_retencoes: f32,
233    /// Valor do ISS
234    pub valor_iss: f32,
235    /// Alíquota do ISS (%)
236    pub aliquota_iss: f32,
237    /// Desconto incondicionado
238    pub desconto_incondicionado: f32,
239    /// Desconto condicionado
240    pub desconto_condicionado: f32,
241    /// Base de cálculo do ISS
242    pub base_calculo: f32,
243    /// Valor líquido
244    pub valor_liquido: f32,
245    /// ISS retido? (1=Sim, 2=Não)
246    pub iss_retido: bool,
247    /// Valor do ISS retido
248    pub valor_iss_retido: f32,
249    /// Responsável pela retenção (1=Prestador, 2=Tomador, 3=Intermediário)
250    pub responsavel_retencao: Option<u8>,
251}
252
253impl Default for ValoresNfse {
254    fn default() -> Self {
255        Self {
256            valor_servicos: 0.0,
257            valor_deducoes: 0.0,
258            valor_pis: 0.0,
259            valor_cofins: 0.0,
260            valor_inss: 0.0,
261            valor_ir: 0.0,
262            valor_csll: 0.0,
263            outras_retencoes: 0.0,
264            valor_iss: 0.0,
265            aliquota_iss: 0.0,
266            desconto_incondicionado: 0.0,
267            desconto_condicionado: 0.0,
268            base_calculo: 0.0,
269            valor_liquido: 0.0,
270            iss_retido: false,
271            valor_iss_retido: 0.0,
272            responsavel_retencao: None,
273        }
274    }
275}
276
277/// RPS - Recibo Provisório de Serviços
278#[derive(Debug, Clone, Serialize, Deserialize)]
279pub struct Rps {
280    /// Identificação do RPS
281    pub identificacao: IdentificacaoRps,
282    /// Data de emissão
283    pub data_emissao: String,
284    /// Status (1=Normal, 2=Cancelado)
285    pub status: u8,
286    /// Substituição de RPS (se for substituição)
287    pub rps_substituido: Option<IdentificacaoRps>,
288}
289
290/// Identificação do RPS
291#[derive(Debug, Clone, Serialize, Deserialize)]
292pub struct IdentificacaoRps {
293    /// Número do RPS
294    pub numero: u64,
295    /// Série do RPS
296    pub serie: String,
297    /// Tipo (1=RPS, 2=Nota Fiscal Conjugada, 3=Cupom)
298    pub tipo: u8,
299}
300
301/// Lote de RPS para envio
302#[derive(Debug, Clone, Serialize, Deserialize)]
303pub struct LoteRps {
304    /// Número do lote
305    pub numero_lote: String,
306    /// CNPJ do prestador
307    pub cnpj_prestador: String,
308    /// Inscrição municipal do prestador
309    pub inscricao_municipal_prestador: String,
310    /// Quantidade de RPS no lote
311    pub quantidade_rps: u32,
312    /// Lista de RPS
313    pub lista_rps: Vec<RpsCompleto>,
314}
315
316/// RPS completo para envio no lote
317#[derive(Debug, Clone, Serialize, Deserialize)]
318pub struct RpsCompleto {
319    /// Dados do RPS
320    pub rps: Rps,
321    /// Prestador
322    pub prestador: PrestadorServico,
323    /// Tomador
324    pub tomador: Option<TomadorServico>,
325    /// Serviço
326    pub servico: ServicoNfse,
327    /// Valores
328    pub valores: ValoresNfse,
329}
330
331/// Resposta da consulta de NFS-e
332#[derive(Debug, Clone, Serialize, Deserialize)]
333pub struct RespostaConsultaNfse {
334    /// Sucesso na consulta
335    pub sucesso: bool,
336    /// Mensagem de retorno
337    pub mensagem: Option<String>,
338    /// Lista de NFS-e encontradas
339    pub nfses: Vec<Nfse>,
340}
341
342/// Resposta do envio de lote de RPS
343#[derive(Debug, Clone, Serialize, Deserialize)]
344pub struct RespostaEnvioLote {
345    /// Número do lote
346    pub numero_lote: String,
347    /// Protocolo de recebimento
348    pub protocolo: Option<String>,
349    /// Data de recebimento
350    pub data_recebimento: Option<String>,
351    /// Situação do lote (1=Não Recebido, 2=Não Processado, 3=Processado com Erro, 4=Processado com Sucesso)
352    pub situacao: u8,
353    /// Lista de erros/alertas
354    pub mensagens: Vec<MensagemRetorno>,
355}
356
357/// Mensagem de retorno do processamento
358#[derive(Debug, Clone, Serialize, Deserialize)]
359pub struct MensagemRetorno {
360    /// Código da mensagem
361    pub codigo: String,
362    /// Descrição da mensagem
363    pub mensagem: String,
364    /// Correção sugerida
365    pub correcao: Option<String>,
366}
367
368/// Calcula os valores de uma NFS-e
369pub fn calcular_valores_nfse(
370    valor_servicos: f32,
371    aliquota_iss: f32,
372    valor_deducoes: f32,
373    iss_retido: bool,
374    aliquota_pis: Option<f32>,
375    aliquota_cofins: Option<f32>,
376    aliquota_inss: Option<f32>,
377    aliquota_ir: Option<f32>,
378    aliquota_csll: Option<f32>,
379) -> ValoresNfse {
380    let base_calculo = valor_servicos - valor_deducoes;
381    let valor_iss = base_calculo * (aliquota_iss / 100.0);
382
383    let valor_pis = aliquota_pis.map(|a| base_calculo * (a / 100.0)).unwrap_or(0.0);
384    let valor_cofins = aliquota_cofins.map(|a| base_calculo * (a / 100.0)).unwrap_or(0.0);
385    let valor_inss = aliquota_inss.map(|a| base_calculo * (a / 100.0)).unwrap_or(0.0);
386    let valor_ir = aliquota_ir.map(|a| base_calculo * (a / 100.0)).unwrap_or(0.0);
387    let valor_csll = aliquota_csll.map(|a| base_calculo * (a / 100.0)).unwrap_or(0.0);
388
389    let valor_iss_retido = if iss_retido { valor_iss } else { 0.0 };
390    let outras_retencoes = valor_pis + valor_cofins + valor_inss + valor_ir + valor_csll;
391
392    let valor_liquido = valor_servicos - valor_iss_retido - outras_retencoes;
393
394    ValoresNfse {
395        valor_servicos,
396        valor_deducoes,
397        valor_pis,
398        valor_cofins,
399        valor_inss,
400        valor_ir,
401        valor_csll,
402        outras_retencoes,
403        valor_iss,
404        aliquota_iss,
405        desconto_incondicionado: 0.0,
406        desconto_condicionado: 0.0,
407        base_calculo,
408        valor_liquido,
409        iss_retido,
410        valor_iss_retido,
411        responsavel_retencao: if iss_retido { Some(2) } else { None }, // 2 = Tomador
412    }
413}