Example #1
0
    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
Example #2
0
    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
Example #3
0
    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
                )
Example #4
0
    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)
Example #5
0
    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)