Skip to content

Commit

Permalink
Add module base_phone_business_document_import
Browse files Browse the repository at this point in the history
Add unitests in base_business_document_import
Small code enhancements/simplifications
  • Loading branch information
alexis-via authored and adrienpeiffer committed Oct 3, 2016
1 parent b311308 commit acd75e7
Show file tree
Hide file tree
Showing 15 changed files with 458 additions and 31 deletions.
1 change: 0 additions & 1 deletion account_invoice_import/__openerp__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
'author': 'Akretion,Odoo Community Association (OCA)',
'website': 'http://www.akretion.com',
'depends': ['account', 'base_iban', 'base_business_document_import'],
'external_dependencies': {'python': ['lxml']},
'data': [
'security/ir.model.access.csv',
'account_invoice_import_config_view.xml',
Expand Down
3 changes: 3 additions & 0 deletions account_invoice_import/account_invoice.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ def name_get(self):
new_res = []
for (inv_id, name) in res:
inv = self.browse(inv_id)
# I didn't find a python method to easily display
# a float + currency symbol (before or after)
# depending on lang of context and currency
name += _(' Amount w/o tax: %s %s') % (
inv.amount_untaxed, inv.currency_id.name)
new_res.append((inv_id, name))
Expand Down
41 changes: 29 additions & 12 deletions account_invoice_import/wizard/account_invoice_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,8 @@ def _prepare_create_invoice_vals(self, parsed_inv):
il_vals = static_vals.copy()
if config.invoice_line_method == 'nline_auto_product':
product = self._match_product(
line['product'], parsed_inv['chatter_msg'], partner)
line['product'], parsed_inv['chatter_msg'],
seller=partner)
fposition_id = partner.property_account_position.id
il_vals.update(
ailo.product_id_change(
Expand Down Expand Up @@ -359,6 +360,7 @@ def import_invoice(self):
parsed_inv.get('currency'), parsed_inv['chatter_msg'])
parsed_inv['partner']['recordset'] = partner
parsed_inv['currency']['recordset'] = currency
# TODO Move to IF below : make sure we don't access self.partner_id
self.write({
'partner_id': partner.id,
'invoice_type': parsed_inv['type'],
Expand Down Expand Up @@ -482,28 +484,43 @@ def _prepare_update_invoice_vals(self, parsed_inv):
def update_invoice(self):
self.ensure_one()
iaao = self.env['ir.actions.act_window']
if not self.invoice_id:
invoice = self.invoice_id
if not invoice:
raise UserError(_(
'You must select a supplier invoice or refund to update'))
parsed_inv = self.parse_invoice()
currency = self._match_currency(
parsed_inv.get('currency'), parsed_inv['chatter_msg'])
if currency != invoice.currency_id:
raise UserError(_(
"The currency of the imported invoice (%s) is different from "
"the currency of the existing invoice (%s)") % (
currency.name, invoice.currency_id.name))
# When invoice with embedded XML files will be more widely used,
# we should also update invoice lines
vals = self._prepare_update_invoice_vals(parsed_inv)
logger.debug('Updating supplier invoice with vals=%s', vals)
self.invoice_id.write(vals)
self.env['ir.attachment'].create({
'name': self.invoice_filename,
'res_id': self.invoice_id.id,
'res_model': 'account.invoice',
'datas': self.invoice_file,
})
logger.info('Supplier invoice ID %d updated', self.invoice_id.id)
self.invoice_id.message_post(_(
"This invoice has been updated automatically via file import"))
# Attach invoice and related documents
if parsed_inv.get('attachments'):
for filename, data_base64 in parsed_inv['attachments'].iteritems():
self.env['ir.attachment'].create({
'name': filename,
'res_id': invoice.id,
'res_model': 'account.invoice',
'datas': data_base64,
'datas_fname': filename,
})
logger.info(
'Supplier invoice ID %d updated via import of file %s',
invoice.id, self.invoice_filename)
invoice.message_post(_(
"This invoice has been updated automatically via the import "
"of file %s") % self.invoice_filename)
action = iaao.for_xml_id('account', 'action_invoice_tree2')
action.update({
'view_mode': 'form,tree,calendar,graph',
'views': False,
'res_id': self.invoice_id.id,
'res_id': invoice.id,
})
return action
2 changes: 1 addition & 1 deletion base_business_document_import/__openerp__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
{
'name': 'Base Business Document Import',
'version': '8.0.1.0.0',
'category': 'Hidden',
'category': 'Tools',
'license': 'AGPL-3',
'summary': 'Provides technical tools to import sale orders or supplier '
'invoices',
Expand Down
68 changes: 57 additions & 11 deletions base_business_document_import/models/business_document_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,17 @@ class BusinessDocumentImport(models.AbstractModel):
_name = 'business.document.import'
_description = 'Common methods to import business documents'

@api.model
def _strip_cleanup_dict(self, match_dict):
if match_dict:
for key, value in match_dict.iteritems():
if value and isinstance(value, (str, unicode)):
match_dict[key] = value.strip()
if match_dict.get('country_code'):
match_dict['country_code'] = match_dict['country_code'].upper()
if match_dict.get('state_code'):
match_dict['state_code'] = match_dict['state_code'].upper()

@api.model
def _match_partner(
self, partner_dict, chatter_msg, partner_type='supplier'):
Expand All @@ -29,9 +40,14 @@ def _match_partner(
'email': '[email protected]',
'name': 'Akretion France',
'ref': 'C1242',
'phone': '01.41.98.12.42',
'fax': '01.41.98.12.43',
}
The keys 'phone' and 'fax' are used by the module
base_phone_business_document_import
"""
rpo = self.env['res.partner']
self._strip_cleanup_dict(partner_dict)
if partner_dict.get('recordset'):
return partner_dict['recordset']
if partner_dict.get('id'):
Expand Down Expand Up @@ -69,6 +85,11 @@ def _match_partner(
'|',
('state_id', '=', False),
('state_id', '=', states[0].id)]
# Hook to plug alternative matching methods
partner = self._hook_match_partner(
partner_dict, chatter_msg, domain, partner_type_label)
if partner:
return partner
if partner_dict.get('vat'):
vat = partner_dict['vat'].replace(' ', '').upper()
# use base_vat_sanitized
Expand All @@ -79,7 +100,7 @@ def _match_partner(
if partners:
return partners[0]
else:
raise UserError(_(
chatter_msg.append(_(
"The analysis of the business document returned '%s' as "
"%s VAT number. But there are no %s "
"with this VAT number in Odoo.")
Expand Down Expand Up @@ -139,14 +160,34 @@ def _match_partner(
partner_dict.get('ref'),
partner_dict.get('name')))

@api.model
def _hook_match_partner(
self, partner_dict, chatter_msg, domain, partner_type_label):
return False

@api.model
def _match_shipping_partner(self, shipping_dict, partner, chatter_msg):
"""Example:
shipping_dict = {
'partner': {
'email': '[email protected]',
'name': 'Akretion France',
},
'address': {
'zip': '69100',
'country_code': 'FR',
},
}
The partner argument is a bit special: it is a fallback in case
shipping_dict['partner'] = {}
"""
rpo = self.env['res.partner']
if shipping_dict.get('partner'):
partner = self._match_partner(
shipping_dict['partner'], chatter_msg, partner_type=False)
domain = [('parent_id', '=', partner.id)]
address_dict = shipping_dict['address']
self._strip_cleanup_dict(address_dict)
country = False
if address_dict.get('country_code'):
countries = self.env['res.country'].search([
Expand All @@ -173,7 +214,7 @@ def _match_shipping_partner(self, shipping_dict, partner, chatter_msg):
('state_id', '=', states[0].id)]
if address_dict.get('zip'):
domain.append(('zip', '=', address_dict['zip']))
# TODO: sanitize ZIP ?
# sanitize ZIP ?
partners = rpo.search(domain + [('type', '=', 'delivery')])
if partners:
partner = partners[0]
Expand All @@ -184,14 +225,15 @@ def _match_shipping_partner(self, shipping_dict, partner, chatter_msg):
return partner

@api.model
def _match_product(self, product_dict, chatter_msg, partner=False):
def _match_product(self, product_dict, chatter_msg, seller=False):
"""Example:
product_dict = {
'ean13': '5449000054227',
'code': 'COCA1L',
}
"""
ppo = self.env['product.product']
self._strip_cleanup_dict(product_dict)
if product_dict.get('recordset'):
return product_dict['recordset']
if product_dict.get('id'):
Expand All @@ -210,9 +252,9 @@ def _match_product(self, product_dict, chatter_msg, partner=False):
return products[0]
# WARNING: Won't work for multi-variant products
# because product.supplierinfo is attached to product template
if partner:
if seller:
sinfo = self.env['product.supplierinfo'].search([
('name', '=', partner.id),
('name', '=', seller.id),
('product_code', '=', product_dict['code']),
])
if (
Expand All @@ -230,7 +272,7 @@ def _match_product(self, product_dict, chatter_msg, partner=False):
"Supplier: %s\n") % (
product_dict.get('ean13'),
product_dict.get('code'),
partner and partner.name or 'None'))
seller and seller.name or 'None'))

@api.model
def _match_currency(self, currency_dict, chatter_msg):
Expand All @@ -244,6 +286,7 @@ def _match_currency(self, currency_dict, chatter_msg):
if not currency_dict:
currency_dict = {}
rco = self.env['res.currency']
self._strip_cleanup_dict(currency_dict)
if currency_dict.get('recordset'):
return currency_dict['recordset']
if currency_dict.get('id'):
Expand All @@ -262,13 +305,14 @@ def _match_currency(self, currency_dict, chatter_msg):
if currency_dict.get('symbol'):
currencies = rco.search(
[('symbol', '=', currency_dict['symbol'])])
if currencies:
if len(currencies) == 1:
return currencies[0]
else:
raise UserError(_(
chatter_msg.append(_(
"The analysis of the business document returned '%s' as "
"the currency symbol. But there are no currency "
"with that symbol in Odoo.") % currency_dict['symbol'])
"the currency symbol. But there are none or several "
"currencies with that symbol in Odoo.")
% currency_dict['symbol'])
if currency_dict.get('iso_or_symbol'):
currencies = rco.search([
'|',
Expand All @@ -283,7 +327,7 @@ def _match_currency(self, currency_dict, chatter_msg):
"currency with the symbol nor ISO code in Odoo.")
% currency_dict['iso_or_symbol'])
if currency_dict.get('country_code'):
country_code = currency_dict['country_code'].upper()
country_code = currency_dict['country_code']
countries = self.env['res.country'].search([
('code', '=', country_code)])
if countries:
Expand Down Expand Up @@ -320,6 +364,7 @@ def _match_uom(self, uom_dict, chatter_msg, product=False):
puo = self.env['product.uom']
if not uom_dict:
uom_dict = {}
self._strip_cleanup_dict(uom_dict)
if uom_dict.get('recordset'):
return uom_dict['recordset']
if uom_dict.get('id'):
Expand Down Expand Up @@ -382,6 +427,7 @@ def _match_tax(
With l10n_fr, it will return 20% VAT tax.
"""
ato = self.env['account.tax']
self._strip_cleanup_dict(tax_dict)
if tax_dict.get('recordset'):
return tax_dict['recordset']
if tax_dict.get('id'):
Expand Down
3 changes: 3 additions & 0 deletions base_business_document_import/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-

from . import test_business_document_import
Loading

0 comments on commit acd75e7

Please sign in to comment.