def xml_cancel(self, cr, uid, ids, inv, cancel_rps, cert_name, context=None): cert_password = str(inv.company_id.nfe_a1_password) proc = ProcessadorNFSeSP(cert_name, cert_password) if datetime.datetime.now() > proc._certificado._data_fim_validade: return { 'action': 'cancel', 'message': '%s - %s' % ( u'Certificado Digital fora da validade', inv.company_id.name)} if not self._check_server(cr, uid, ids, proc.servidor): return { 'action': 'cancel', 'message': u'Falha de comunicação com o servidor'} if inv.company_id.ei_environment == 'production': success, res, warnings, errors = proc.cancelar_nfse(cancel_rps) else: return { 'action': 'cancel', 'message': u'Serviço de Teste para Cancelamento INDISPONÍVEL' } msg_alerta = '' for alerta_line in res.Alerta: msg_alerta += '%s-%s\n' % (str(alerta_line.Codigo or 0), alerta_line.Descricao or '') msg_erro = '' for erro_line in res.Erro: msg_erro += '%s-%s\n' % (str(erro_line.Codigo or 0), erro_line.Descricao or '') if msg_erro: result = { 'action': 'cancel', 'message': '%s%s' % (msg_alerta, msg_erro) } else: result = { 'action': 'cancel', 'ei_status': 'cancelled', 'message': '%s%s' % (msg_alerta, u'NF-e cancelada com SUCESSO') } return result
def xml_send(self, cr, uid, ids, inv, lote_rps, cabecalho_rps, consulta_rps, cert_name, context = None): cert_password = str(inv.company_id.nfe_a1_password) proc = ProcessadorNFSeSP(cert_name, cert_password) user_timezone = self.pool.get('res.users').browse(cr, uid, uid).tz date_now = datetime.datetime.now( pytz.timezone(user_timezone)).strftime('%Y-%m-%d') if datetime.datetime.now() > proc._certificado._data_fim_validade: return {'action': 'send', 'ei_status': 'failed', 'message': '%s - %s' % ( u'Certificado Digital fora da validade', inv.company_id.name)} if not self._check_server(cr, uid, ids, proc.servidor): return { 'action': 'send', 'ei_status': 'failed', 'message': u'Falha de comunicação com o servidor'} if inv.company_id.ei_environment == 'production': success, res, warnings, errors = proc.consultar_nfse(consulta_rps) if success and not res.NFe: success, res, warnings, errors = proc.enviar_lote_rps( cabecalho=cabecalho_rps, lote_rps=lote_rps) else: success, res, warnings, errors = proc.testar_envio_lote_rps( cabecalho=cabecalho_rps, lote_rps=lote_rps) msg_alerta = '' for alerta_line in res.Alerta: msg_alerta += '%s-%s\n' % (str(alerta_line.Codigo or 0), alerta_line.Descricao or '') msg_erro = '' for erro_line in res.Erro: msg_erro += '%s-%s\n' % (str(erro_line.Codigo or 0), erro_line.Descricao or '') w_chave_nfe = False chave_write = False if hasattr(res, 'NFe'): w_chave_nfe = res.NFe elif hasattr(res, 'ChaveNFeRPS'): w_chave_nfe = res.ChaveNFeRPS for chave_line in w_chave_nfe: if chave_line.ChaveNFe: chave_write = { 'ei_code': chave_line.ChaveNFe.NumeroNFe, 'ei_verification_code': chave_line.ChaveNFe.CodigoVerificacao, 'ei_date': date_now, 'rps_serie': int(inv.document_serie_id.code), 'rps_code': lote_rps[0]['NumeroRPS']} message = 'Nf-e sent' self.log(cr, uid, inv, message, context=context) if inv.company_id.ei_environment == 'production': if msg_erro: result = { 'action': 'send', 'ei_status': 'failed', 'message': '%s%s' % (msg_alerta, msg_erro) } elif not chave_write: result = { 'action': 'send', 'ei_status': 'sent', 'message': '%s%s' % ( msg_alerta, u'NF-e enviada com SUCESSO, aguardando confirmação')} else: result = { 'action': 'send', 'ei_status': 'confirmed', 'message': '%s%s' % (msg_alerta, u'NF-e criada com SUCESSO')} result.update(chave_write) elif inv.company_id.ei_environment == 'test': if msg_erro: result = { 'action': 'send', 'message': '%s%s' % (msg_alerta, msg_erro)} else: result = { 'action': 'send', 'message': '%s%s' % ( msg_alerta, u'Teste de envio de NF-e efetuado com SUCESSO')} return result
def cancel_nfse(self, cr, uid, ids, context=None): """Cancel one or many NFS-e""" canceled_invoices = [] failed_invoices = [] inv_obj = self.pool.get('account.invoice') active_ids = [i.id for i in self.browse(cr, uid, ids[0]).selected_invoices] if len(active_ids) == 0: raise osv.except_osv( u'Atenção!', u'Não há notas confirmadas para efetuar o cancelamento.' ) conditions = [('id', 'in', active_ids), ('nfse_status', '=', NFSE_STATUS['send_ok'])] invoices_to_cancel = inv_obj.search(cr, uid, conditions) if len(invoices_to_cancel) == 0: raise osv.except_osv( u'Não foi possível cancelar a nota fiscal', u'A nota fiscal ainda não foi enviada, portanto não é ' + \ u'possível cancela-la.' ) for inv in inv_obj.browse(cr, uid, invoices_to_cancel, context=context): if not inv.nfse_numero or not inv.nfse_codigo_verificacao: raise osv.except_osv( u'Não foi possível cancelar a nota fiscal', u'A nota fiscal de número {} ainda '.format(inv.number) + \ u'não foi enviada, portanto não é possível cancela-la.' ) company = self.pool.get('res.company').browse( cr, uid, inv.company_id.id ) self._check_certificate(company) cert_file_content = base64.decodestring(company.nfse_cert_file) caminho_temporario = u'/tmp/' cert_file = caminho_temporario + uuid4().hex arq_tmp = open(cert_file, 'w') arq_tmp.write(cert_file_content) arq_tmp.close() cert_password = company.nfse_cert_password processor = ProcessadorNFSeSP(cert_file, cert_password) self._check_server(cr, uid, ids, processor.servidor) try: success, res, warnings, errors = processor.cancelar_nfse({ 'CPFCNPJRemetente': re.sub('[^0-9]', '', company.cnpj), 'InscricaoPrestador': company.inscr_mun, 'InscricaoTomador': inv.partner_id.inscr_mun, 'NumeroRPS': inv.internal_number, 'SerieRPS': inv.document_serie_id.code, 'NumeroNFe': inv.nfse_numero, 'CodigoVerificacao': inv.nfse_codigo_verificacao, 'Versao': 1, }) except CommunicationError, e: raise osv.except_osv( u'Ocorreu um erro de comunicação.', u'Código: {}\nDescrição: {}'.format(e.status, e.reason) ) if success: canceled_invoices.append(inv.id) data = {'nfse_status': NFSE_STATUS['cancel_ok']} else: self._show_warnings_and_errors(warnings, errors) self.pool.get('account.invoice').write( cr, uid, inv.id, data, context=context )
def check_nfse(self, cr, uid, ids, context=None): """Check one or many NFS-e""" inv_obj = self.pool.get('account.invoice') active_ids = [i.id for i in self.browse(cr, uid, ids[0]).selected_invoices] if len(active_ids) == 0: raise osv.except_osv( u'Atenção!', u'Não há notas confirmadas para efetuar a consulta.' ) conditions = [('id', 'in', active_ids)] invoices = inv_obj.search(cr, uid, conditions) for inv in inv_obj.browse(cr, uid, invoices, context=context): if not inv.nfse_numero or not inv.nfse_codigo_verificacao: raise osv.except_osv( u'Não foi possível consultar a nota fiscal', u'A nota fiscal de número {} ainda '.format(inv.number) + \ u'não foi enviada, portanto não é possível consulta-la.' ) company = self.pool.get('res.company').browse( cr, uid, inv.company_id.id ) self._check_certificate(company) cert_file_content = base64.decodestring(company.nfse_cert_file) caminho_temporario = u'/tmp/' cert_file = caminho_temporario + uuid4().hex arq_tmp = open(cert_file, 'w') arq_tmp.write(cert_file_content) arq_tmp.close() cert_password = company.nfse_cert_password processor = ProcessadorNFSeSP(cert_file, cert_password) self._check_server(cr, uid, ids, processor.servidor) try: success, res, warnings, errors = processor.consultar_nfse({ 'CPFCNPJRemetente': re.sub('[^0-9]', '', company.cnpj), 'InscricaoPrestador': company.inscr_mun, 'NumeroNFe': inv.nfse_numero, 'CodigoVerificacao': inv.nfse_codigo_verificacao, 'Versao': 1, }) except CommunicationError, e: raise osv.except_osv( u'Ocorreu um erro de comunicação.', u'Código: {}\nDescrição: {}'.format(e.status, e.reason) ) if success: nfe = res.NFe[0] if nfe.StatusNFe == 'C': raise osv.except_osv( u'Aviso', u'Nota fiscal consta como cancelada.' ) elif nfe.StatusNFe == 'E': raise osv.except_osv( u'Aviso', u'Nota fiscal consta como extraviada.' ) else: self._show_warnings_and_errors(warnings, errors)
def _send_nfse(self, cr, uid, ids, context, test=True): """Test NFS-e dispatch""" result = {} inv_obj = self.pool.get('account.invoice') active_ids = [i.id for i in self.browse(cr, uid, ids[0]).selected_invoices] if len(active_ids) == 0: raise osv.except_osv( u'Atenção!', u'Não há notas confirmadas para efetuar o envio.' ) conditions = [('id', 'in', active_ids), '|', ('nfe_status', '=', None), ('nfse_status', '!=', NFSE_STATUS['send_ok'])] invoices_to_send = inv_obj.search(cr, uid, conditions) lote_rps = [] valor_total_servicos = 0 valor_total_deducoes = 0 datas = [] invoices = inv_obj.browse(cr, uid, invoices_to_send, context=context) if not self._check_invoices_are_services(invoices): raise osv.except_osv( u'Não foi possível completar a operação.', u'Uma ou mais faturas não são de serviço.', ) invoice_rps = {} for inv in invoices: company = self.pool.get('res.company').browse( cr, uid, inv.company_id.id ) self._check_certificate(company) cert_file_content = base64.decodestring(company.nfse_cert_file) caminho_temporario = u'/tmp/' cert_file = caminho_temporario + uuid4().hex arq_tmp = open(cert_file, 'w') arq_tmp.write(cert_file_content) arq_tmp.close() cert_password = company.nfse_cert_password company_addr_ids = self.pool.get('res.partner').address_get(cr, uid, [company.partner_id.id], ['default']) company_addr = self.pool.get('res.partner.address').browse(cr, uid, [company_addr_ids['default']])[0] partner_addr_ids = self.pool.get('res.partner').address_get(cr, uid, [inv.partner_id.id], ['default']) partner_addr = self.pool.get('res.partner.address').browse(cr, uid, [partner_addr_ids['default']])[0] proc = ProcessadorNFSeSP( cert_file, cert_password, ) if self._check_server(cr, uid, ids, proc.servidor): data_emissao = inv.date_invoice if partner_addr.l10n_br_city_id and partner_addr.state_id: city_ibge_code = str(partner_addr.state_id.ibge_code) + \ str(partner_addr.l10n_br_city_id.ibge_code) else: city_ibge_code = None valor_servicos = inv.amount_untaxed valor_deducoes = 0 if inv.amount_tax < 0: valor_deducoes = inv.amount_tax * -1 valor_total_servicos += valor_servicos valor_total_deducoes += valor_deducoes impostos = ('pis', 'cofins', 'inss', 'ir', 'csll', 'iss', 'iss_retido') valores = {x: 0 for x in impostos} aliquota = 0 for inv_tax in inv.tax_line: if inv_tax.tax_code_id.domain in impostos: valores[inv_tax.tax_code_id.domain] += \ round(inv_tax.amount, 2) if inv_tax.tax_code_id.domain == 'iss': aliquota = round(inv_tax.aliquota, 2) iss_retido = valores['iss_retido'] < 0 discriminacoes = [] for inv_line in inv.invoice_line: discriminacoes.append(inv_line.name) discriminacao = '|'.join(discriminacoes) inscricao_municipal_tomador = inv.partner_id.inscr_mun # São Paulo if company_addr.l10n_br_city_id.ibge_code == '50308': if partner_addr.l10n_br_city_id.ibge_code == '50308' and \ not inscricao_municipal_tomador: raise osv.except_osv( u'Faltam dados no cadastro do tomador.', u'Informe a inscrição municipal do parceiro %s.' % inv.partner_id.name, ) elif partner_addr.l10n_br_city_id.ibge_code != '50308': inscricao_municipal_tomador = None service_code = inv.fiscal_operation_id.code if inv.partner_id.cnpj_cpf: cnpj_tomador = re.sub('[^0-9]', '', inv.partner_id.cnpj_cpf) else: raise osv.except_osv( u'Faltam dados no cadastro do cliente.', u'O CNPJ do cliente %s é obrigatório.' % inv.partner_id.name, ) lote_rps.append({ # FIXME: por enquanto somente RPS suportado 'TipoRPS': 'RPS', 'DataEmissao': data_emissao, # TODO: tpStatusNFe 'StatusRPS': 'N', 'TributacaoRPS': company.tributacao or 'T', 'ValorServicos': valor_servicos, 'ValorDeducoes': valor_deducoes, 'ValorPIS': valores['pis'], 'ValorCOFINS': valores['cofins'], 'ValorINSS': valores['inss'], 'ValorIR': valores['ir'], 'ValorCSLL': valores['csll'], 'CodigoServico': int(service_code), 'AliquotaServicos': aliquota, 'ISSRetido': iss_retido, 'CPFCNPJTomador': cnpj_tomador, 'TipoInscricaoTomador': inv.partner_id.tipo_pessoa, 'InscricaoMunicipalTomador': inscricao_municipal_tomador, 'InscricaoEstadualTomador': inv.partner_id.inscr_est or None, 'RazaoSocialTomador': inv.partner_id.legal_name, 'Logradouro': partner_addr.street, 'NumeroEndereco': partner_addr.number, 'ComplementoEndereco': partner_addr.street2, 'Bairro': partner_addr.district, 'Cidade': city_ibge_code, 'UF': partner_addr.state_id and \ partner_addr.state_id.code or None, 'CEP': partner_addr.zip, 'EmailTomador': partner_addr.email, 'Discriminacao': discriminacao, 'SerieRPS': int(inv.document_serie_id.code), 'NumeroRPS': inv.internal_number, }) datas.append(data_emissao) invoice_rps[inv.internal_number] = inv if len(lote_rps): datas.sort() if company.cnpj: cnpj_remetente = re.sub('[^0-9]', '', company.cnpj) else: raise osv.except_osv( u'Faltam dados no cadastro da empresa.', u'O CNPJ da empresa %s é obrigatório.' % company.name, ) cabecalho = { 'CPFCNPJRemetente': cnpj_remetente, 'InscricaoMunicipalPrestador': re.sub( '[^0-9]', '', company.inscr_mun ), 'transacao': True, 'dtInicio': datas[0], 'dtFim': datas[-1], 'QtdRPS': len(lote_rps), 'ValorTotalServicos': valor_total_servicos, 'ValorTotalDeducoes': valor_total_deducoes, 'Versao': 1, } try: if test: success, res, warnings, errors = proc.testar_envio_lote_rps( cabecalho=cabecalho, lote_rps=lote_rps ) else: success, res, warnings, errors = proc.enviar_lote_rps( cabecalho=cabecalho, lote_rps=lote_rps ) except CommunicationError, e: raise osv.except_osv( u'Ocorreu um erro de comunicação.', u'Código: {}\nDescrição: {}'.format(e.status, e.reason) ) if len(warnings) == 0 and success and test: raise osv.except_osv( u'Aviso', u'Os dados foram validados com sucesso.' ) elif not test and success: chave_nfe_rps = res.ChaveNFeRPS for chave in chave_nfe_rps: chave_nfe = chave.ChaveNFe chave_rps = chave.ChaveRPS numero_rps = chave_rps.NumeroRPS invoice = invoice_rps[numero_rps] numero_nfe = chave_nfe.NumeroNFe codigo_ver = chave_nfe.CodigoVerificacao data = { 'nfse_status': NFSE_STATUS['send_ok'], 'nfse_numero': int(numero_nfe), 'nfse_codigo_verificacao': codigo_ver, } inv_obj.write(cr, uid, invoice.id, data, context=context) result = {'state': 'done'} for chave in warnings: for code, warning in warnings[chave]: if code == '208': invoice = invoice_rps[ chave.NumeroRPS ] data = {'nfse_retorno': warning} inv_obj.write( cr, uid, invoice.id, data, context=context ) self.write(cr, uid, ids, result) cr.commit() raise osv.except_osv( u'Alíquotas divergentes!', u'Para evitar a inconsistência dos ' + \ u'dados no sistema, cancele a NFS-e ' + \ u'(número {}) '.format(invoice.number) + \ u'e corrija a alíquota.\nRetorno do ' + \ u'sistema da prefeitura:\n\n"' + \ warning + '"' ) if len(warnings): self._show_warnings_and_errors( invoice_rps, warnings, errors ) else: self._show_warnings_and_errors(invoice_rps, warnings, errors)