summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorwan <wan@odoo.com>2019-06-18 14:43:07 +0000
committerwan <wan@odoo.com>2019-07-19 09:34:59 +0000
commitf722ef0cb079ab2368d4f4075e4c42c0ab9c376a (patch)
treed110cb3bec6b6b62c9a61c6b615b8cb7b74cbd7b /addons
parent4b66aa58b9daf83bd72b0e1830d25fcf074320c6 (diff)
[IMP] account, _facturx, l10n[be,it]_edi: remove account.invoice.import.wizard
Since the wizard is not shown anymore (skipped to go right to file selection), we can remove it. Small refactoring had to be done for l10n_it in order to upload files with multiple invoices inside and to detect format closes odoo/odoo#34145 Signed-off-by: Quentin De Paoli (qdp) <qdp@openerp.com>
Diffstat (limited to 'addons')
-rw-r--r--addons/account/__manifest__.py1
-rw-r--r--addons/account/models/account.py29
-rw-r--r--addons/account/static/src/js/bills_tree_upload.js12
-rw-r--r--addons/account/static/src/xml/bills_tree_upload_views.xml11
-rw-r--r--addons/account/wizard/__init__.py1
-rw-r--r--addons/account/wizard/account_invoice_import.py47
-rw-r--r--addons/account/wizard/account_invoice_import_view.xml29
-rw-r--r--addons/account_facturx/models/account_move.py12
-rw-r--r--addons/l10n_be_edi/models/account_invoice.py2
-rw-r--r--addons/l10n_it_edi/models/account_invoice.py49
-rw-r--r--addons/l10n_it_edi/models/ir_mail_server.py9
11 files changed, 73 insertions, 129 deletions
diff --git a/addons/account/__manifest__.py b/addons/account/__manifest__.py
index f7ab4fcac79..bdbefa57126 100644
--- a/addons/account/__manifest__.py
+++ b/addons/account/__manifest__.py
@@ -24,7 +24,6 @@ You could use this simplified accounting in case you work with an (external) acc
'data/digest_data.xml',
'views/account_menuitem.xml',
'views/account_payment_view.xml',
- 'wizard/account_invoice_import_view.xml',
'wizard/account_unreconcile_view.xml',
'wizard/account_move_reversal_view.xml',
'views/account_move_views.xml',
diff --git a/addons/account/models/account.py b/addons/account/models/account.py
index 5f591c991b9..d99559672c3 100644
--- a/addons/account/models/account.py
+++ b/addons/account/models/account.py
@@ -9,6 +9,7 @@ from odoo.tools.float_utils import float_round as round, float_compare
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
from odoo.exceptions import UserError, ValidationError
from odoo import api, fields, models, _
+from odoo.tests.common import Form
class AccountAccountType(models.Model):
@@ -953,6 +954,34 @@ class AccountJournal(models.Model):
# We simply call the setup bar function.
return self.env['res.company'].setting_init_bank_account_action()
+ def create_invoice_from_attachment(self, attachment_ids=[]):
+ ''' Create the invoices from files.
+ :return: A action redirecting to account.move tree/form view.
+ '''
+ attachments = self.env['ir.attachment'].browse(attachment_ids)
+ if not attachments:
+ raise UserError(_("No attachment was provided"))
+
+ invoices = self.env['account.move']
+ for attachment in attachments:
+ invoice = self.env['account.move'].create({})
+ attachment.write({'res_model': 'account.move', 'res_id': invoice.id})
+ invoice.message_post(attachment_ids=[attachment.id])
+ invoices += invoice
+
+ action_vals = {
+ 'name': _('Generated Documents'),
+ 'domain': [('id', 'in', invoices.ids)],
+ 'res_model': 'account.move',
+ 'views': [[False, "tree"], [False, "form"]],
+ 'type': 'ir.actions.act_window',
+ }
+ if len(invoices) == 1:
+ action_vals.update({'res_id': invoices[0].id, 'view_mode': 'form'})
+ else:
+ action_vals['view_mode'] = 'tree,form'
+ return action_vals
+
class ResPartnerBank(models.Model):
_inherit = "res.partner.bank"
diff --git a/addons/account/static/src/js/bills_tree_upload.js b/addons/account/static/src/js/bills_tree_upload.js
index 835dc42b7d9..2287ca09d7c 100644
--- a/addons/account/static/src/js/bills_tree_upload.js
+++ b/addons/account/static/src/js/bills_tree_upload.js
@@ -32,15 +32,12 @@ odoo.define('account.upload.bill.mixin', function (require) {
var attachent_ids = attachments.reduce(function(filtered, record) {
if (record.id) {
filtered.push(record.id);
- }
+ }
return filtered;
}, []);
- if (!attachent_ids.length) {
- return self.do_notify(_t("Error"), _t("An error occurred during the upload"));
- }
return this._rpc({
- model: 'account.invoice.import.wizard',
- method: 'create_invoices',
+ model: 'account.journal',
+ method: 'create_invoice_from_attachment',
args: ["", attachent_ids],
context: this.initialState.context,
}).then(function(result) {
@@ -50,9 +47,6 @@ odoo.define('account.upload.bill.mixin', function (require) {
_onUpload: function (event) {
var self = this;
- if (!this.initialState.context.journal_type) {
- this.initialState.context.journal_type = event.currentTarget.attributes['journal_type'].value;
- }
// If hidden upload form don't exists, create it
var $formContainer = this.$('.o_content').find('.o_vendor_bill_upload');
if (!$formContainer.length) {
diff --git a/addons/account/static/src/xml/bills_tree_upload_views.xml b/addons/account/static/src/xml/bills_tree_upload_views.xml
index af9385a5780..93502ee9136 100644
--- a/addons/account/static/src/xml/bills_tree_upload_views.xml
+++ b/addons/account/static/src/xml/bills_tree_upload_views.xml
@@ -4,6 +4,7 @@
<t t-name="account.BillsHiddenUploadForm">
<div class="d-none o_vendor_bill_upload">
<t t-call="HiddenInputFile">
+ <t t-set="multi_upload" t-value="true"/>
<t t-set="fileupload_id" t-value="widget.fileUploadID"/>
<t t-set="fileupload_action" t-translation="off">/web/binary/upload_attachment</t>
<input type="hidden" name="model" t-att-value="'account.move'"/>
@@ -19,11 +20,9 @@
r.push(context.engine.tools.call(context, 'ImportView.import_button', dict));
};
</t>
- <t t-if="widget.initialState.context.journal_type === 'purchase'">
- <button type="button" class="btn btn-secondary o_button_upload_bill">
- Upload
- </button>
- </t>
+ <button type="button" class="btn btn-secondary o_button_upload_bill">
+ Upload
+ </button>
</t>
</t>
-</templates> \ No newline at end of file
+</templates>
diff --git a/addons/account/wizard/__init__.py b/addons/account/wizard/__init__.py
index f61453de267..c23f76b521b 100644
--- a/addons/account/wizard/__init__.py
+++ b/addons/account/wizard/__init__.py
@@ -3,7 +3,6 @@
from . import account_unreconcile
-from . import account_invoice_import
from . import account_validate_account_move
from . import pos_box
from . import account_move_reversal
diff --git a/addons/account/wizard/account_invoice_import.py b/addons/account/wizard/account_invoice_import.py
deleted file mode 100644
index 4ce6675bc81..00000000000
--- a/addons/account/wizard/account_invoice_import.py
+++ /dev/null
@@ -1,47 +0,0 @@
-# -*- coding: utf-8 -*-
-from odoo import api, fields, models, _
-from odoo.tests.common import Form
-from odoo.exceptions import UserError
-
-
-class ImportInvoiceImportWizard(models.TransientModel):
- _name = 'account.invoice.import.wizard'
- _description = 'Import Your Vendor Bills from Files.'
-
- attachment_ids = fields.Many2many('ir.attachment', string='Files')
-
- def _create_invoice_from_file(self, attachment):
- invoice = self.env['account.move'].create({})
- attachment.write({'res_model': 'account.move', 'res_id': invoice.id})
- invoice.message_post(attachment_ids=[attachment.id])
- return invoice
-
- def _create_invoice(self, attachment):
- return self._create_invoice_from_file(attachment)
-
- def create_invoices(self, attachment_ids=[]):
- ''' Create the invoices from files.
- :return: A action redirecting to account.invoice tree/form view.
- '''
- attachments = self.attachment_ids or self.env['ir.attachment'].browse(attachment_ids)
- if not attachments:
- raise UserError(_("No attachment was provided"))
-
- invoices = self.env['account.move']
- for attachment in attachments:
- invoices += self._create_invoice(attachment)
-
- action_vals = {
- 'name': _('Generated Documents'),
- 'domain': [('id', 'in', invoices.ids)],
- 'view_type': 'form',
- 'res_model': 'account.move',
- 'views': [[False, "tree"], [False, "form"]],
- 'type': 'ir.actions.act_window',
- 'context': self.env.context,
- }
- if len(invoices) == 1:
- action_vals.update({'res_id': invoices[0].id, 'view_mode': 'form'})
- else:
- action_vals['view_mode'] = 'tree,form'
- return action_vals
diff --git a/addons/account/wizard/account_invoice_import_view.xml b/addons/account/wizard/account_invoice_import_view.xml
deleted file mode 100644
index 9e9a2cd3b69..00000000000
--- a/addons/account/wizard/account_invoice_import_view.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<odoo>
- <data>
- <record id="account_invoice_import_wizard_form_view" model="ir.ui.view">
- <field name="name">account.invoice.import.wizard.form</field>
- <field name="model">account.invoice.import.wizard</field>
- <field name="arch" type="xml">
- <form>
- <group>
- <field name="attachment_ids" widget="many2many_binary" colspan="2"
- string="Upload Files" nolabel="1"/>
- </group>
- <footer>
- <button string="Import" name="create_invoices" type="object" class="oe_highlight"/>
- <button string="Cancel" class="btn btn-secondary" special="cancel"/>
- </footer>
- </form>
- </field>
- </record>
-
- <record id="account_invoice_import_wizard_action" model="ir.actions.act_window">
- <field name="name">Import Vendor Bills</field>
- <field name="res_model">account.invoice.import.wizard</field>
- <field name="view_mode">form</field>
- <field name="target">new</field>
- <field name="context">{'default_type': 'in_invoice', 'default_journal_id': active_id}</field>
- </record>
- </data>
-</odoo>
diff --git a/addons/account_facturx/models/account_move.py b/addons/account_facturx/models/account_move.py
index 844068b684e..cc8b53dc45d 100644
--- a/addons/account_facturx/models/account_move.py
+++ b/addons/account_facturx/models/account_move.py
@@ -291,7 +291,7 @@ class AccountMove(models.Model):
:return: a list of triplet (xml_type, check_func, decode_func)
* xml_type: The format name, e.g 'UBL 2.1'
- * check_func: A function taking an etree as parameter and returning a dict:
+ * check_func: A function taking an etree and a file name as parameter and returning a dict:
* flag: The etree is part of this format.
* error: Error message.
* decode_func: A function taking an etree as parameter and returning an invoice record.
@@ -310,20 +310,20 @@ class AccountMove(models.Model):
raise UserError(_('The xml file is badly formatted : {}').format(attachment.name))
for xml_type, check_func, decode_func in decoders:
- check_res = check_func(tree)
+ check_res = check_func(tree, attachment.name)
if check_res.get('flag') and not check_res.get('error'):
- invoice = decode_func(tree)
- if invoice:
+ invoice_ids = decode_func(tree)
+ if invoice_ids:
try:
# don't propose to send to ocr
- invoice.extract_state = 'done'
+ invoice_ids.write({'extract_state': 'done'})
except AttributeError:
# account_invoice_exctract not installed
pass
break
try:
- return invoice
+ return invoice_ids
except UnboundLocalError:
raise UserError(_('No decoder was found for the xml file: {}. The file is badly formatted, not supported or the decoder is not installed').format(attachment.name))
diff --git a/addons/l10n_be_edi/models/account_invoice.py b/addons/l10n_be_edi/models/account_invoice.py
index 0429b630f91..e70ab5fddb1 100644
--- a/addons/l10n_be_edi/models/account_invoice.py
+++ b/addons/l10n_be_edi/models/account_invoice.py
@@ -25,7 +25,7 @@ class AccountMove(models.Model):
return namespaces
@api.model
- def _detect_ubl_2_1(self, tree):
+ def _detect_ubl_2_1(self, tree, file_name):
# Quick check the tree looks like an UBL 2.1 file.
flag = tree.tag == '{urn:oasis:names:specification:ubl:schema:xsd:Invoice-2}Invoice'
error = None
diff --git a/addons/l10n_it_edi/models/account_invoice.py b/addons/l10n_it_edi/models/account_invoice.py
index bc0dbc4a838..4b4457c042e 100644
--- a/addons/l10n_it_edi/models/account_invoice.py
+++ b/addons/l10n_it_edi/models/account_invoice.py
@@ -290,23 +290,22 @@ class AccountMove(models.Model):
)
self.l10n_it_send_state = 'invalid'
- def _import_xml_invoice(self, content, attachment):
+ def _import_xml_invoice(self, tree):
''' Extract invoice values from the E-Invoice xml tree passed as parameter.
:param content: The tree of the xml file.
:return: A dictionary containing account.invoice values to create/update it.
'''
- try:
- tree = etree.fromstring(content)
- except:
- _logger.info('Error during decoding XML file')
- return self.env['account.move']
-
invoices = self.env['account.move']
+ multi = False
# possible to have multiple invoices in the case of an invoice batch, the batch itself is repeated for every invoice of the batch
for body_tree in tree.xpath('//FatturaElettronicaBody', namespaces=tree.nsmap):
+ if multi:
+ # make sure all the iterations create a new invoice record (except the first which could have already created one)
+ self = self.env['account.move']
+ multi = True
elements = tree.xpath('//DatiGeneraliDocumento/TipoDocumento', namespaces=tree.nsmap)
if elements and elements[0].text and elements[0].text == 'TD01':
@@ -654,7 +653,8 @@ class AccountMove(models.Model):
})
# default_res_id is had to context to avoid facturx to import his content
- new_invoice.with_context(default_res_id=new_invoice.id).message_post(
+ # no_new_invoice to prevent from looping on the message_post that would create a new invoice without it
+ new_invoice.with_context(no_new_invoice=True, default_res_id=new_invoice.id).message_post(
body=(_("Attachment from XML")),
attachment_ids=[attachment_64.id]
)
@@ -662,10 +662,6 @@ class AccountMove(models.Model):
for message in message_to_log:
new_invoice.message_post(body=message)
- if attachment:
- new_invoice.l10n_it_einvoice_name = attachment.name
- attachment.write({'res_model': 'account.move', 'res_id': new_invoice.id})
- new_invoice.message_post(attachment_ids=[attachment.id])
invoices += new_invoice
return invoices
@@ -695,6 +691,20 @@ class AccountMove(models.Model):
output_str += "<li>%s: %s</li>" % (element.tag, text)
return output_str + "</ul>"
+ @api.model
+ def _get_xml_decoders(self):
+ # Override
+ ubl_decoders = [('Italy', self._detect_italy_edi, self._import_xml_invoice)]
+ return super(AccountMove, self)._get_xml_decoders() + ubl_decoders
+
+ @api.model
+ def _detect_italy_edi(self, tree, file_name):
+ # Quick check the file name looks like the one of an Italian EDI XML.
+ flag = re.search("([A-Z]{2}[A-Za-z0-9]{2,28}_[A-Za-z0-9]{0,5}.(xml.p7m|xml))", file_name)
+ error = None
+
+ return {'flag': flag, 'error': error}
+
class AccountTax(models.Model):
_name = "account.tax"
_inherit = "account.tax"
@@ -730,18 +740,3 @@ class AccountTax(models.Model):
raise ValidationError("If the tax has exoneration, you must enter a kind of exoneration, a law reference and the amount of the tax must be 0.0.")
if tax.l10n_it_kind_exoneration == 'N6' and tax.l10n_it_vat_due_date == 'S':
raise UserError(_("'Scissione dei pagamenti' is not compatible with exoneration of kind 'N6'"))
-
-class ImportInvoiceImportWizard(models.TransientModel):
- _name = 'account.invoice.import.wizard'
- _inherit = 'account.invoice.import.wizard'
-
- def _create_invoice_from_file(self, attachment):
- if attachment.mimetype == 'application/xml' and re.search("([A-Z]{2}[A-Za-z0-9]{2,28}_[A-Za-z0-9]{0,5}.(xml.p7m|xml))", attachment.name):
- if self.env['account.move'].search([('l10n_it_einvoice_name', '=', attachment.name)], limit=1):
- # invoice already exist
- raise UserError(_('E-invoice already exist: %s') % attachment.name)
- self = self.with_context(default_journal_id= self.journal_id.id)
- invoice = self.env['account.move']._import_xml_invoice(base64.decodestring(attachment.datas), attachment)
- else:
- invoice = super(ImportInvoiceImportWizard, self)._create_invoice_from_file(attachment)
- return invoice
diff --git a/addons/l10n_it_edi/models/ir_mail_server.py b/addons/l10n_it_edi/models/ir_mail_server.py
index 8af502b2c09..f36ef683dee 100644
--- a/addons/l10n_it_edi/models/ir_mail_server.py
+++ b/addons/l10n_it_edi/models/ir_mail_server.py
@@ -19,7 +19,7 @@ from lxml import etree
from datetime import datetime
from odoo import api, fields, models, tools, _
-from odoo.exceptions import ValidationError
+from odoo.exceptions import ValidationError, UserError
_logger = logging.getLogger(__name__)
@@ -137,7 +137,12 @@ class FetchmailServer(models.Model):
'type': 'binary',
})
- invoice = self.env['account.move']._import_xml_invoice(att_content, invoice_attachment)
+ try:
+ tree = etree.fromstring(att_content)
+ except Exception:
+ raise UserError(_('The xml file is badly formatted : {}').format(att_name))
+
+ invoice = self.env['account.move']._import_xml_invoice(tree)
invoice.l10n_it_send_state = "new"
invoice.source_email = from_address
self._cr.commit()