Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inicio do modo de contingência #848

Open
wants to merge 24 commits into
base: 11.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
2bf8d2d
Corrigindo a geração do QR Code
maiconkkl Jul 2, 2019
384c7a1
Merge branch '11.0' of https://github.com/Trust-Code/odoo-brasil into…
maiconkkl Jul 2, 2019
f7f1e54
Criando paramentros fixo para contingência
maiconkkl Jul 2, 2019
58080a0
Correções
maiconkkl Jul 4, 2019
a46782b
.
maiconkkl Jul 4, 2019
246ae7b
Alterado pra usar tradução
maiconkkl Jul 4, 2019
3c6bcba
.
maiconkkl Jul 4, 2019
1f5c935
.
maiconkkl Jul 4, 2019
fff7ca6
desfazendo alteração
maiconkkl Jul 4, 2019
6e1538c
Ultilizando a função de gerar qr
maiconkkl Jul 22, 2019
044485e
Merge branch '11.0' into 11.0
ImplantiSolucoes Jul 22, 2019
c259e88
Merge branch '11.0' into 11.0
ImplantiSolucoes Jul 26, 2019
273bd69
Merge branch '11.0' into 11.0
ImplantiSolucoes Aug 3, 2019
629ee3c
Merge branch '11.0' into 11.0
ImplantiSolucoes Aug 13, 2019
fabfd65
Ajuste na tabela de NCM
maiconkkl Aug 14, 2019
df3fb85
Merge branch '11.0' into 11.0
ImplantiSolucoes Aug 16, 2019
31cc368
Merge branch '11.0' into 11.0
ImplantiSolucoes Aug 21, 2019
ab53f33
Merge branch '11.0' of https://github.com/Trust-Code/odoo-brasil into…
maiconkkl Sep 30, 2019
d72ccb4
Merge branch '11.0' into 11.0
ImplantiSolucoes Oct 3, 2019
1393840
Merge branch '11.0' into 11.0
ImplantiSolucoes Oct 5, 2019
b683583
Chamando função para carregar o QRCode
maiconkkl Oct 9, 2019
26e4b7e
Correção tipo de dados
maiconkkl Oct 9, 2019
e91c399
Merge branch '11.0' into 11.0
ImplantiSolucoes Oct 16, 2019
db81f14
Merge branch '11.0' into 11.0
ImplantiSolucoes Jan 16, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion br_account/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
{ # pylint: disable=C8101,C8103
'name': 'Brazilian Localization Account',
'description': """Brazilian Localization Account""",
'version': '11.0.1.0.0',
'version': '11.0.1.0.1',
'category': 'account',
'author': 'Trustcode',
'license': 'AGPL-3',
Expand Down
1 change: 1 addition & 0 deletions br_account_einvoice/models/invoice_eletronic.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class InvoiceEletronic(models.Model):
[('draft', u'Provisório'),
('edit', 'Editar'),
('error', 'Erro'),
('contingencia', 'Contingência'),
('done', 'Enviado'),
('cancel', 'Cancelado')],
string=u'State', default='draft', readonly=True, states=STATE,
Expand Down
2 changes: 1 addition & 1 deletion br_data_account_product/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
'license': 'AGPL-3',
'author': 'Akretion, OpenERP Brasil',
'website': 'http://openerpbrasil.org',
'version': '11.0.1.0.0',
'version': '11.0.1.0.1',
'depends': [
'br_data_account',
],
Expand Down
28 changes: 28 additions & 0 deletions br_nfe/i18n/pt_BR.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * br_nfe
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 11.0+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-07-03 22:16+0000\n"
"PO-Revision-Date: 2019-07-03 22:16+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"

#. module: br_nfe
#: code:br_nfe/models/invoice_eletronic.py:780
#, python-format
msgid "Adicione um contato para o responsável técnico!"
msgstr "Adicione um contato para o responsável técnico!"

#. module: br_nfe
#: code:br_nfe/models/invoice_eletronic.py:1100
#, python-format
msgid "A NFe não está validada"
msgstr "A NFe não está validada"
115 changes: 66 additions & 49 deletions br_nfe/models/invoice_eletronic.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import base64
import logging
import hashlib
from lxml import etree
from lxml import etree, objectify
from datetime import datetime
from pytz import timezone
from odoo import api, fields, models, _
Expand All @@ -22,6 +22,7 @@
from pytrustnfe.nfe import retorno_autorizar_nfe
from pytrustnfe.nfe import recepcao_evento_cancelamento
from pytrustnfe.nfe import consultar_protocolo_nfe
from pytrustnfe.nfe import gerar_qrcode
from pytrustnfe.certificado import Certificado
from pytrustnfe.utils import ChaveNFe, gerar_chave, gerar_nfeproc, \
gerar_nfeproc_cancel
Expand Down Expand Up @@ -209,6 +210,15 @@ def generate_correction_letter(self):
string="Forma de Pagamento", default="01")
valor_pago = fields.Monetary(string='Valor pago')
troco = fields.Monetary(string='Troco')
digest_value = fields.Char(
string="Digest Value da NF-e", size=40, readonly=True, states=STATE,
help=u"Corresponde ao algoritmo SHA1 sobre o arquivo XML"
u"da NFC-e, convertido para formato hexadecimal. Ao"
u"se efetuar a assinatura digital da NFC-e emitida em"
u"contingência off-line, o campo digestvalue constante"
u"da XML Signature deve obrigatoriamente ser idêntico"
u"ao encontrado quando da geração do digestvalue"
u"para a montagem QR Code.")

# Documentos Relacionados
fiscal_document_related_ids = fields.One2many(
Expand Down Expand Up @@ -263,7 +273,7 @@ def _hook_validation(self):
if not self.fiscal_position_id:
errors.append(u'Configure a posição fiscal')
if self.company_id.accountant_id and not \
self.company_id.accountant_id.cnpj_cpf:
self.company_id.accountant_id.cnpj_cpf:
errors.append(u'Emitente / CNPJ do escritório contabilidade')
# NFC-e
if self.model == '65':
Expand Down Expand Up @@ -305,7 +315,7 @@ def _prepare_eletronic_invoice_item(self, item, invoice):
'uCom': '{:.6}'.format(item.uom_id.name or ''),
'qCom': qty_frmt.format(item.quantidade),
'vUnCom': price_frmt.format(item.preco_unitario),
'vProd': "%.02f" % item.valor_bruto,
'vProd': "%.02f" % item.valor_bruto,
'cEANTrib': item.product_id.barcode or 'SEM GTIN',
'uTrib': '{:.6}'.format(item.uom_id.name or ''),
'qTrib': qty_frmt.format(item.quantidade),
Expand Down Expand Up @@ -384,8 +394,10 @@ def _prepare_eletronic_invoice_item(self, item, invoice):
'vBC': "%.02f" % item.issqn_base_calculo,
'vAliq': "%.02f" % item.issqn_aliquota,
'vISSQN': "%.02f" % item.issqn_valor,
'cMunFG': "%s%s" % (invoice.company_id.state_id.ibge_code,
invoice.company_id.city_id.ibge_code),
'cMunFG': "%s%s" % (
invoice.company_id.state_id.ibge_code,
invoice.company_id.city_id.ibge_code
),
'cListServ': item.issqn_codigo,
'vDeducao': '',
'vOutro': "%.02f" % retencoes if retencoes else '',
Expand All @@ -401,7 +413,7 @@ def _prepare_eletronic_invoice_item(self, item, invoice):
else:
imposto.update({
'ICMS': {
'orig': item.origem,
'orig': item.origem,
'CST': item.icms_cst,
'modBC': item.icms_tipo_base,
'vBC': "%.02f" % item.icms_base_calculo,
Expand Down Expand Up @@ -476,6 +488,12 @@ def _prepare_eletronic_invoice_values(self):
'procEmi': 0,
'verProc': 'Odoo 11 - Trustcode',
}
if int(self.tipo_emissao) != 1:
ide['dhCont'] = dt_emissao
ide['xJust'] = u'Falha na transmissão devido a ' \
u'conexão do provedor de internet ou ' \
u'comunicação com a sefaz'

# Documentos Relacionados
documentos = []
for doc in self.fiscal_document_related_ids:
Expand Down Expand Up @@ -575,7 +593,7 @@ def _prepare_eletronic_invoice_values(self):
'fone': re.sub('[^0-9]', '', partner.phone or '')
},
'indIEDest': self.ind_ie_dest,
'IE': re.sub('[^0-9]', '', partner.inscr_est or ''),
'IE': re.sub('[^0-9]', '', partner.inscr_est or ''),
}
if self.model == '65':
dest.update(
Expand Down Expand Up @@ -678,10 +696,13 @@ def _prepare_eletronic_invoice_values(self):
transp = {
'modFrete': self.modalidade_frete,
'transporta': {
'xNome': self.transportadora_id.legal_name or
self.transportadora_id.name or '',
'IE': re.sub('[^0-9]', '',
self.transportadora_id.inscr_est or ''),
'xNome':
self.transportadora_id.legal_name or
self.transportadora_id.name or '',
'IE': re.sub(
'[^0-9]', '',
self.transportadora_id.inscr_est or ''
),
'xEnder': end_transp
if self.transportadora_id else '',
'xMun': self.transportadora_id.city_id.name or '',
Expand Down Expand Up @@ -727,14 +748,16 @@ def _prepare_eletronic_invoice_values(self):
vencimento = fields.Datetime.from_string(dup.data_vencimento)
duplicatas.append({
'nDup': dup.numero_duplicata,
'dVenc': vencimento.strftime('%Y-%m-%d'),
'dVenc': vencimento.strftime('%Y-%m-%d'),
'vDup': "%.02f" % dup.valor
})
cobr = {
'fat': {
'nFat': self.numero_fatura or '',
'vOrig': "%.02f" % (
self.fatura_liquido + self.fatura_desconto),
self.fatura_liquido +
self.fatura_desconto
),
'vDesc': "%.02f" % self.fatura_desconto,
'vLiq': "%.02f" % self.fatura_liquido,
},
Expand All @@ -745,7 +768,7 @@ def _prepare_eletronic_invoice_values(self):
'tPag': self.payment_mode_id.tipo_pagamento or '90',
'vPag': '0.00',
}
self.informacoes_complementares = self.informacoes_complementares.\
self.informacoes_complementares = self.informacoes_complementares. \
replace('\n', '<br />')
self.informacoes_legais = self.informacoes_legais.replace(
'\n', '<br />')
Expand All @@ -765,7 +788,8 @@ def _prepare_eletronic_invoice_values(self):
if responsavel_tecnico:
if len(responsavel_tecnico.child_ids) == 0:
raise UserError(
"Adicione um contato para o responsável técnico!")
_('Adicione um contato para o responsável técnico!')
)

cnpj = re.sub('[^0-9]', '', responsavel_tecnico.cnpj_cpf)
fone = re.sub('[^0-9]', '', responsavel_tecnico.phone or '')
Expand Down Expand Up @@ -798,7 +822,7 @@ def _prepare_eletronic_invoice_values(self):
'ISSQNtot': issqn_total,
'retTrib': tributos_retidos,
})
if len(duplicatas) > 0 and\
if len(duplicatas) > 0 and \
self.fiscal_position_id.finalidade_emissao not in ('2', '4'):
vals['cobr'] = cobr
pag['tPag'] = '01' if pag['tPag'] == '90' else pag['tPag']
Expand All @@ -808,23 +832,6 @@ def _prepare_eletronic_invoice_values(self):
vals['pag'][0]['tPag'] = self.metodo_pagamento
vals['pag'][0]['vPag'] = "%.02f" % self.valor_pago
vals['pag'][0]['vTroco'] = "%.02f" % self.troco or '0.00'

chave_nfe = self.chave_nfe
ambiente = 1 if self.ambiente == 'producao' else 2
estado = self.company_id.state_id.ibge_code

cid_token = int(self.company_id.id_token_csc)
csc = self.company_id.csc

c_hash_QR_code = "{0}|2|{1}|{2}{3}".format(
chave_nfe, ambiente, int(cid_token), csc)
c_hash_QR_code = hashlib.sha1(c_hash_QR_code.encode()).hexdigest()

QR_code_url = "p={0}|2|{1}|{2}|{3}".format(
chave_nfe, ambiente, int(cid_token), c_hash_QR_code)
qr_code_server = url_qrcode(estado, str(ambiente))
vals['qrCode'] = qr_code_server + QR_code_url
vals['urlChave'] = url_qrcode_exibicao(estado, str(ambiente))
return vals

@api.multi
Expand All @@ -842,28 +849,28 @@ def _prepare_lote(self, lote, nfe_values):

def _find_attachment_ids_email(self):
atts = super(InvoiceEletronic, self)._find_attachment_ids_email()
if self.model not in ('55'):
if self.model not in '55':
return atts

attachment_obj = self.env['ir.attachment']
nfe_xml = base64.decodestring(self.nfe_processada)
logo = base64.decodestring(self.invoice_id.company_id.logo)

tmpLogo = io.BytesIO()
tmpLogo.write(logo)
tmpLogo.seek(0)
tmp_logo = io.BytesIO()
tmp_logo.write(logo)
tmp_logo.seek(0)

xml_element = etree.fromstring(nfe_xml)
oDanfe = danfe(list_xml=[xml_element], logo=tmpLogo)
o_danfe = danfe(list_xml=[xml_element], logo=tmp_logo)

tmpDanfe = io.BytesIO()
oDanfe.writeto_pdf(tmpDanfe)
tmp_danfe = io.BytesIO()
o_danfe.writeto_pdf(tmp_danfe)

if danfe:
danfe_id = attachment_obj.create(dict(
name="Danfe-%08d.pdf" % self.numero,
datas_fname="Danfe-%08d.pdf" % self.numero,
datas=base64.b64encode(tmpDanfe.getvalue()),
datas=base64.b64encode(tmp_danfe.getvalue()),
mimetype='application/pdf',
res_model='account.invoice',
res_id=self.invoice_id.id,
Expand Down Expand Up @@ -906,25 +913,35 @@ def action_post_validate(self):
cert_pfx, self.company_id.nfe_a1_password)

nfe_values = self._prepare_eletronic_invoice_values()

lote = self._prepare_lote(self.id, nfe_values)

xml_enviar = xml_autorizar_nfe(certificado, **lote)

if self.model == '65':
xml_enviar = gerar_qrcode(
id_csc=int(self.company_id.id_token_csc),
csc=self.company_id.csc,
xml_send=xml_enviar)
nfe = objectify.fromstring(xml_enviar)
data_write = {
'xml_to_send': base64.encodestring(
xml_enviar.encode('utf-8')),
'xml_to_send_name': 'nfse-enviar-%s.xml' % self.numero
}
if self.model == '65':
data_write['qrcode_hash'] = nfe.find(
'.//{http://www.portalfiscal.inf.br/nfe}qrCode').text
data_write['qrcode_url'] = nfe.find(
'.//{http://www.portalfiscal.inf.br/nfe}urlChave').text
mensagens_erro = valida_nfe(xml_enviar)
if mensagens_erro:
raise UserError(mensagens_erro)

self.xml_to_send = base64.encodestring(
xml_enviar.encode('utf-8'))
self.xml_to_send_name = 'nfse-enviar-%s.xml' % self.numero
self.write(data_write)

@api.multi
def action_send_eletronic_invoice(self):
super(InvoiceEletronic, self).action_send_eletronic_invoice()

if self.model not in ('55', '65') or self.state in (
'done', 'denied', 'cancel'):
'done', 'denied', 'cancel'):
return

_logger.info('Sending NF-e (%s) (%.2f) - %s' % (
Expand Down