[IMP] account: edi export/import review

bzr revid: odo@openerp.com-20111005003409-7umxxyebrh6jf8r2
This commit is contained in:
Olivier Dony 2011-10-05 02:34:09 +02:00
parent 77180a5bcc
commit 05497056de
6 changed files with 189 additions and 241 deletions

View File

@ -35,5 +35,5 @@ import product
import sequence
import company
import res_currency
import edi_invoice
import edi
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -53,7 +53,7 @@ module named account_voucher.
'website': 'http://www.openerp.com',
'images' : ['images/accounts.jpeg','images/bank_statement.jpeg','images/cash_register.jpeg','images/chart_of_accounts.jpeg','images/customer_invoice.jpeg','images/journal_entries.jpeg'],
'init_xml': [],
"depends" : ["base_setup", "product", "analytic", "process","board", "email_template"],
"depends" : ["base_setup", "product", "analytic", "process", "board", "edi", "email_template"],
'update_xml': [
'security/account_security.xml',
'security/ir.model.access.csv',
@ -124,7 +124,7 @@ module named account_voucher.
'board_account_view.xml',
"wizard/account_report_profit_loss_view.xml",
"wizard/account_report_balance_sheet_view.xml",
"edi_invoice_action_data.xml",
"edi/invoice_action_data.xml",
"account_bank_view.xml",
],
'demo_xml': [

View File

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Business Applications
# Copyright (c) 2011 OpenERP S.A. <http://openerp.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import invoice

View File

@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
# OpenERP, Open Source Business Applications
# Copyright (c) 2011 OpenERP S.A. <http://openerp.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@ -20,10 +20,10 @@
##############################################################################
from osv import fields, osv, orm
from base.ir import ir_edi
from edi import EDIMixin
from tools.translate import _
class account_invoice(osv.osv, ir_edi.edi):
class account_invoice(osv.osv, EDIMixin):
_inherit = 'account.invoice'
def edi_export(self, cr, uid, records, edi_struct=None, context=None):
@ -35,24 +35,19 @@ class account_invoice(osv.osv, ir_edi.edi):
'type': True, # -> reversed at import
'internal_number': True, # -> reference at import
'comment': True,
'reference': True,
'amount_untaxed': True,
'amount_tax': True,
'amount_total': True,
'reconciled': True,
'date_invoice': True,
'date_due': True,
'partner_id': True,
'address_invoice_id': True, #only one address needed
'payment_term': True,
'currency_id': True,
'currency_id': True, # TODO: should perhaps include sample rate + rounding
'invoice_line': {
'name': True,
'origin': True,
'uos_id': True,
'product_id': True,
'price_unit': True,
'price_subtotal': True,
#'price_subtotal': True,
'quantity': True,
'discount': True,
'note': True,
@ -66,40 +61,20 @@ class account_invoice(osv.osv, ir_edi.edi):
'base_amount': True,
'tax_amount': True,
},
#'paid': True,
}
company_pool = self.pool.get('res.company')
res_company = self.pool.get('res.company')
edi_doc_list = []
for invoice in records:
# Get EDI doc based on struct. The result will also contain all metadata fields and attachments.
edi_doc = super(account_invoice,self).edi_export(cr, uid, [invoice], edi_struct, context)
if not edi_doc:
continue
edi_doc = edi_doc[0]
# Add company info and address
edi_company_document = company_pool.edi_export_address(cr, uid, [invoice.company_id], context=context)[invoice.company_id.id]
edi_doc = super(account_invoice,self).edi_export(cr, uid, [invoice], edi_struct, context)[0]
edi_doc.update({
'company_address': edi_company_document['company_address'],
#'company_logo': edi_company_document['company_logo'],#TODO
'company_address': res_company.edi_export_address(cr, uid, invoice.company_id, context=context),
#'company_logo': #TODO
})
edi_doc_list.append(edi_doc)
return edi_doc_list
def get_invoice_journal(self, cr, uid, invoice_type, context=None):
if context is None:
context = {}
account_journal_pool = self.pool.get('account.journal')
journal_context = context.copy()
journal_context.update({'type':invoice_type})
journal_id = self._get_journal(cr, uid, context=journal_context)
journal = False
if journal_id:
journal = account_journal_pool.browse(cr, uid, journal_id, context=context)
return journal
def get_tax_account(self, cr, uid, invoice_type='out_invoice', context=None):
#TOCHECK: should select account of output VAT for Customer Invoice and Input VAT for Supplier Invoice
def _edi_tax_account(self, cr, uid, invoice_type='out_invoice', context=None):
#TODO/FIXME: should select proper Tax Account
account_pool = self.pool.get('account.account')
account_ids = account_pool.search(cr, uid, [('type','<>','view'),('type','<>','income'), ('type', '<>', 'closed')])
tax_account = False
@ -107,7 +82,7 @@ class account_invoice(osv.osv, ir_edi.edi):
tax_account = account_pool.browse(cr, uid, account_ids[0])
return tax_account
def get_invoice_account(self, cr, uid, partner_id, invoice_type, context=None):
def _edi_invoice_account(self, cr, uid, partner_id, invoice_type, context=None):
partner_pool = self.pool.get('res.partner')
partner = partner_pool.browse(cr, uid, partner_id, context=context)
if invoice_type in ('out_invoice', 'out_refund'):
@ -116,45 +91,47 @@ class account_invoice(osv.osv, ir_edi.edi):
invoice_account = partner.property_account_payable
return invoice_account
def get_product_account(self, cr, uid, product_id, invoice_type, context=None):
def _edi_product_account(self, cr, uid, product_id, invoice_type, context=None):
product_pool = self.pool.get('product.product')
product = product_pool.browse(cr, uid, product_id, context=context)
account = False
if invoice_type in ('out_invoice','out_refund'):
account = product.product_tmpl_id.property_account_income
if not account:
account = product.categ_id.property_account_income_categ
account = product.property_account_income or product.categ_id.property_account_income_categ
else:
account = product.product_tmpl_id.property_account_expense
if not account:
account = product.categ_id.property_account_expense_categ
account = product.property_account_expense or product.categ_id.property_account_expense_categ
return account
def edi_import_company(self, cr, uid, edi_document, context=None):
partner_address_pool = self.pool.get('res.partner.address')
partner_pool = self.pool.get('res.partner')
company_pool = self.pool.get('res.company')
def _edi_import_company(self, cr, uid, edi_document, context=None):
self._edi_requires_attributes(('company_id','company_address','type'), edi_document)
res_partner_address = self.pool.get('res.partner.address')
res_partner = self.pool.get('res.partner')
# import company as a new partner, if type==in then supplier=1, else customer=1
# company_address data used to add address to new partner
# imported company = new partner
company_id, company_name = edi_document['company_id']
partner_id = self.edi_import_relation(cr, uid, 'res.partner', company_name,
company_id, context=context)
invoice_type = edi_document['type']
partner_value = {}
if invoice_type in ('out_invoice', 'in_refund'):
if invoice_type in ('out_invoice', 'out_refund'):
partner_value.update({'customer': True})
if invoice_type in ('in_invoice', 'out_refund'):
if invoice_type in ('in_invoice', 'in_refund'):
partner_value.update({'supplier': True})
partner_id = company_pool.edi_import_as_partner(cr, uid, edi_document, values=partner_value, context=context)
partner_id = res_partner.write(cr, uid, [partner_id], partner_value, context=context)
# partner_id field is modified to point to the new partner
res = partner_pool.address_get(cr, uid, [partner_id], ['contact', 'invoice'])
address_id = res['invoice']
partner = partner_pool.browse(cr, uid, partner_id, context=context)
partner_address = partner_address_pool.browse(cr, uid, address_id, context=context)
edi_document['partner_id'] = self.edi_m2o(cr, uid, partner, context=context)
edi_document['address_invoice_id'] = self.edi_m2o(cr, uid, partner_address, context=context)
# imported company_address = new partner address
address_info = edi_document['company_address']
address_info['partner_id'] = (company_id, company_name)
address_info['type'] = 'invoice'
address_id = res_partner_address.edi_import(cr, uid, address_info, context=context)
# modify edi_document to refer to new partner
del edi_document['company_id']
del edi_document['company_address']
partner_address = res_partner_address.browse(cr, uid, address_id, context=context)
edi_document['partner_id'] = (company_id, company_name)
edi_document['address_invoice_id'] = self.edi_m2o(cr, uid, partner_address, context=context)
return partner_id
def edi_import(self, cr, uid, edi_document, context=None):
""" During import, invoices will import the company that is provided in the invoice as
@ -168,7 +145,7 @@ class account_invoice(osv.osv, ir_edi.edi):
- reference: should contain the value of the 'internal_number'
- reference_type: 'none'
- internal number: reset to False, auto-generated
- journal_id: should be selected based on type: simply put the 'type'
- journal_id: should be selected based on type: simply put the 'type'
in the context when calling create(), will be selected correctly
- payment_term: if set, create a default one based on name...
- for invoice lines, the account_id value should be taken from the
@ -176,21 +153,22 @@ class account_invoice(osv.osv, ir_edi.edi):
be provided.
- for tax lines, we disconnect from the invoice.line, so all tax lines
will be of type 'manual', and default accounts should be picked based
on the tax config of the DB where it is imported.
on the tax config of the DB where it is imported.
"""
if context is None:
context = {}
#import company as a new partner
partner_id = self.edi_import_company(cr, uid, edi_document, context=context)
self._edi_requires_attributes(('company_id','company_address','type','invoice_line'), edi_document)
# change type: out_invoice'<->'in_invoice','out_refund'<->'in_refund'
invoice_type = edi_document['type']
invoice_type = invoice_type.startswith('in_') and invoice_type.replace('in_','out_') or invoice_type.replace('out_','in_')
edi_document['type'] = invoice_type
#import company as a new partner
partner_id = self._edi_import_company(cr, uid, edi_document, context=context)
# Set Account
invoice_account = self.get_invoice_account(cr, uid, partner_id, invoice_type, context=context)
invoice_account = self._edi_invoice_account(cr, uid, partner_id, invoice_type, context=context)
edi_document['account_id'] = invoice_account and self.edi_m2o(cr, uid, invoice_account, context=context) or False
# reference: should contain the value of the 'internal_number'
@ -200,44 +178,34 @@ class account_invoice(osv.osv, ir_edi.edi):
# internal number: reset to False, auto-generated
edi_document['internal_number'] = False
# journal_id: should be selected based on type: simply put the 'type' in the context when calling create(), will be selected correctly
journal = self.get_invoice_journal(cr, uid, invoice_type, context=context)
edi_document['journal_id'] = journal and self.edi_m2o(cr, uid, journal, context=context) or False
context.update(type=invoice_type)
# for invoice lines, the account_id value should be taken from the product's default, i.e. from the default category, as it will not be provided.
for edi_invoice_line in edi_document.get('invoice_line', []):
product_id = edi_invoice_line.get('product_id', False)
account = False
if product_id:
product_name = product_id and product_id[1]
product_id = self.edi_import_relation(cr, uid, 'product.product', product_name, context=context)
account = self.get_product_account(cr, uid, product_id, invoice_type, context=context)
# TODO: add effect of fiscal position
for edi_invoice_line in edi_document['invoice_line']:
product_info = edi_invoice_line['product_id']
product_id = self.edi_import_relation(cr, uid, 'product.product', product_info[1],
product_info[0], context=context)
account = self._edi_product_account(cr, uid, product_id, invoice_type, context=context)
# TODO: could be improved with fiscal positions perhaps
# account = fpos_obj.map_account(cr, uid, fiscal_position_id, account.id)
edi_invoice_line['account_id'] = account and self.edi_m2o(cr, uid, account, context=context) or False
edi_invoice_line['account_id'] = self.edi_m2o(cr, uid, account, context=context) if account else False
# for tax lines, we disconnect from the invoice.line, so all tax lines will be of type 'manual', and default accounts should be picked based
# on the tax config of the DB where it is imported.
tax_account = self._edi_tax_account(cr, uid, context=context)
tax_account_info = self.edi_m2o(cr, uid, tax_account, context=context)
for edi_tax_line in edi_document.get('tax_line', []):
tax_account = self.get_tax_account(cr, uid, context=context)
if tax_account:
edi_tax_line['account_id'] = self.edi_m2o(cr, uid, tax_account, context=context)
edi_tax_line['account_id'] = tax_account_info
edi_tax_line['manual'] = True
# TODO :=> payment_term: if set, create a default one based on name...
return super(account_invoice,self).edi_import(cr, uid, edi_document, context=context)
account_invoice()
class account_invoice_line(osv.osv, ir_edi.edi):
class account_invoice_line(osv.osv, EDIMixin):
_inherit='account.invoice.line'
account_invoice_line()
class account_invoice_tax(osv.osv, ir_edi.edi):
class account_invoice_tax(osv.osv, EDIMixin):
_inherit = "account.invoice.tax"
account_invoice_tax()

View File

@ -3,7 +3,7 @@
<data>
<!-- EDI Export + Send email Action -->
<record id="ir_actions_server_edi_invoice" model="ir.actions.server">
<field name="code">
<field name="code"><![CDATA[
try:
if not object.partner_id.opt_out:
web_root_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url', default="<WEB_ROOT_URL>")
@ -12,11 +12,11 @@ try:
tmpl = self.pool.get('ir.model.data').get_object(cr, uid, 'account', 'email_template_edi_invoice')[1]
edi_token = self.pool.get('ir.edi.document').export_edi(cr, uid, [object], context = context)[0]
context.update(edi_web_invoice_url_view='%s/web/view_edi?db=%s&token=%s' %(web_root_url,cr.dbname, edi_token))
context.update(edi_web_invoice_url_view='%s/web/view_edi?db=%s&token=%s' %(web_root_url, cr.dbname, edi_token))
self.pool.get('email.template').send_mail(cr, uid,tmpl.id,object.id,context=context)
except:
pass
</field>
]]></field>
<field eval="6" name="sequence"/>
<field name="state">code</field>
<field name="type">ir.actions.server</field>
@ -41,75 +41,75 @@ except:
<field name="subject">${object.company_id.name} Invoice (Ref ${object.number or 'n/a' })</field>
<field name="email_to">${object.address_invoice_id.email or ''}</field>
<field name="model_id" ref="account.model_account_invoice"/>
<field name="body_html">
&lt;div style="font-family: 'Lucica Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: rgb(255, 255, 255); "&gt;
<field name="body_html"><![CDATA[
<div style="font-family: 'Lucica Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: rgb(255, 255, 255); ">
&lt;p&gt;Hello${object.address_invoice_id.name and ' ' or ''}${object.address_invoice_id.name or ''},&lt;/p&gt;
<p>Hello${object.address_invoice_id.name and ' ' or ''}${object.address_invoice_id.name or ''},</p>
&lt;p&gt;A new invoice is available for ${object.partner_id.name}: &lt;/p&gt;
<p>A new invoice is available for ${object.partner_id.name}: </p>
&lt;p style="border-left: 1px solid #8e0000; margin-left: 30px;"&gt;
&nbsp;&nbsp;&lt;strong&gt;REFERENCES&lt;/strong&gt;&lt;br /&gt;
&nbsp;&nbsp;Invoice number: &lt;strong&gt;${object.number}&lt;/strong&gt;&lt;br /&gt;
&nbsp;&nbsp;Invoice amount: &lt;strong&gt;${object.amount_total} ${object.currency_id.name}&lt;/strong&gt;&lt;br /&gt;
&nbsp;&nbsp;Invoice date: ${object.date_invoice or 'n/a'}&lt;br /&gt;
&nbsp;&nbsp;Order reference: ${object.origin or 'n/a'}&lt;br /&gt;
&nbsp;&nbsp;Your contact: &lt;a href="mailto:${object.user_id.user_email or ''}?subject=Invoice%20${object.number}"&gt;${object.user_id.name}&lt;/a&gt;
&lt;/p&gt;
<p style="border-left: 1px solid #8e0000; margin-left: 30px;">
&nbsp;&nbsp;<strong>REFERENCES</strong><br />
&nbsp;&nbsp;Invoice number: <strong>${object.number}</strong><br />
&nbsp;&nbsp;Invoice amount: <strong>${object.amount_total} ${object.currency_id.name}</strong><br />
&nbsp;&nbsp;Invoice date: ${object.date_invoice or 'n/a'}<br />
&nbsp;&nbsp;Order reference: ${object.origin or 'n/a'}<br />
&nbsp;&nbsp;Your contact: <a href="mailto:${object.user_id.user_email or ''}?subject=Invoice%20${object.number}">${object.user_id.name}</a>
</p>
&lt;p&gt;
<p>
You can view the invoice document, download it and pay online using the following link:
&lt;/p&gt;
&lt;a style="display:block; width: 150px; height:20px; margin-left: 120px; color: #FFF; font-family: 'Lucida Grande', Helvetica, Arial, sans-serif; font-size: 13px; font-weight: bold; text-align: center; text-decoration: none !important; line-height: 1; padding: 5px 0px 0px 0px; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(142, 0, 0); border-radius: 2px 2px; background-position: 0% 0%; background-repeat: repeat no-repeat;"
href="${ctx.get('edi_web_invoice_url_view') or ''}"&gt;View Invoice&lt;/a&gt;
</p>
<a style="display:block; width: 150px; height:20px; margin-left: 120px; color: #FFF; font-family: 'Lucida Grande', Helvetica, Arial, sans-serif; font-size: 13px; font-weight: bold; text-align: center; text-decoration: none !important; line-height: 1; padding: 5px 0px 0px 0px; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(142, 0, 0); border-radius: 2px 2px; background-position: 0% 0%; background-repeat: repeat no-repeat;"
href="${ctx.get('edi_web_invoice_url_view') or ''}">View Invoice</a>
% if object.company_id.paypal_account:
&lt;br/&gt;
&lt;p&gt;It is also possible to directly pay with Paypal:&lt;/p&gt;
&lt;a style="display:block; width: 150px; height:20px; margin-left: 120px; color: #FFF; font-family: 'Lucida Grande', Helvetica, Arial, sans-serif; font-size: 13px; font-weight: bold; text-align: center; text-decoration: none !important; line-height: 1; padding: 5px 0px 0px 0px; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(142, 0, 0); border-radius: 2px 2px; background-position: 0% 0%; background-repeat: repeat no-repeat;"
<br/>
<p>It is also possible to directly pay with Paypal:</p>
<a style="display:block; width: 150px; height:20px; margin-left: 120px; color: #FFF; font-family: 'Lucida Grande', Helvetica, Arial, sans-serif; font-size: 13px; font-weight: bold; text-align: center; text-decoration: none !important; line-height: 1; padding: 5px 0px 0px 0px; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(142, 0, 0); border-radius: 2px 2px; background-position: 0% 0%; background-repeat: repeat no-repeat;"
href="${"https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&amp;business=%s&amp;item_name=OpenERP%%20Invoice%%20%s&amp;invoice=%s&amp;amount=%s&amp;currency_code=%s&amp;button_subtype=services&amp;no_note=1&amp;bn=OpenERP_Invoice_PayNow_%s"%(object.company_id.paypal_account,object.number and object.number.replace('/','%2f') or '', object.number and object.number.replace('/','%2f') or '', object.amount_total, object.currency_id.name, object.currency_id.name)}"
&gt;Pay with Paypal&lt;/a&gt;
>Pay with Paypal</a>
% endif
&lt;br/&gt;
&lt;p&gt;If you have any question, do not hesitate to contact us.&lt;/p&gt;
&lt;p&gt;Thank you for choosing ${object.company_id.name or 'us'}!&lt;/p&gt;
&lt;br/&gt;
&lt;br/&gt;
&lt;div style="width: 375px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; overflow-x: hidden; overflow-y: hidden; zoom: 1; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(142, 0, 0); border-top-left-radius: 5px 5px; border-top-right-radius: 5px 5px; border-bottom-right-radius: 0px 0px; border-bottom-left-radius: 0px 0px; background-position: 0% 0%; background-repeat: repeat no-repeat; "&gt;
&lt;h3 style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 9px; padding-right: 14px; padding-bottom: 9px; padding-left: 14px; font-size: 12px; font-weight: normal; font-style: normal; color: rgb(255, 255, 255); "&gt;
&lt;strong style="text-transform:uppercase;"&gt;${object.company_id.name}&lt;/strong&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;div style="width: 347px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 12px; padding-right: 14px; padding-bottom: 12px; padding-left: 14px; overflow-x: hidden; overflow-y: hidden; zoom: 1; line-height: 16px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(242, 242, 242); "&gt;
&lt;span style="color: rgb(38, 72, 149); margin-bottom: 5px; display: block; "&gt;
<br/>
<p>If you have any question, do not hesitate to contact us.</p>
<p>Thank you for choosing ${object.company_id.name or 'us'}!</p>
<br/>
<br/>
<div style="width: 375px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; overflow-x: hidden; overflow-y: hidden; zoom: 1; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(142, 0, 0); border-top-left-radius: 5px 5px; border-top-right-radius: 5px 5px; border-bottom-right-radius: 0px 0px; border-bottom-left-radius: 0px 0px; background-position: 0% 0%; background-repeat: repeat no-repeat; ">
<h3 style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 9px; padding-right: 14px; padding-bottom: 9px; padding-left: 14px; font-size: 12px; font-weight: normal; font-style: normal; color: rgb(255, 255, 255); ">
<strong style="text-transform:uppercase;">${object.company_id.name}</strong></h3>
</div>
<div style="width: 347px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 12px; padding-right: 14px; padding-bottom: 12px; padding-left: 14px; overflow-x: hidden; overflow-y: hidden; zoom: 1; line-height: 16px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(242, 242, 242); ">
<span style="color: rgb(38, 72, 149); margin-bottom: 5px; display: block; ">
% if object.company_id.street:
${object.company_id.street}&lt;br/&gt;
${object.company_id.street}<br/>
% endif
% if object.company_id.street2:
${object.company_id.street2}&lt;br/&gt;
${object.company_id.street2}<br/>
% endif
% if object.company_id.city or object.company_id.zip:
${object.company_id.zip} ${object.company_id.city}&lt;br/&gt;
${object.company_id.zip} ${object.company_id.city}<br/>
% endif
% if object.company_id.country_id:
${object.company_id.state_id and ('%s, ' % object.company_id.state_id.name) or ''} ${object.company_id.country_id.name or ''}&lt;br/&gt;
${object.company_id.state_id and ('%s, ' % object.company_id.state_id.name) or ''} ${object.company_id.country_id.name or ''}<br/>
% endif
&lt;/span&gt;
</span>
% if object.company_id.phone:
&lt;div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "&gt;
<div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">
Phone:&nbsp; ${object.company_id.phone}
&lt;/div&gt;
</div>
% endif
% if object.company_id.website:
&lt;div&gt;
Web :&nbsp;&lt;a href="${object.company_id.website}"&gt;${object.company_id.website}&lt;/a&gt;
&lt;/div&gt;
<div>
Web :&nbsp;<a href="${object.company_id.website}">${object.company_id.website}</a>
</div>
%endif
&lt;p&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</field>
<field name="body_text">
<p></p>
</div>
</div>
]]></field>
<field name="body_text"><![CDATA[
Hello${object.address_invoice_id.name and ' ' or ''}${object.address_invoice_id.name or ''},
A new invoice is available for ${object.partner_id.name}:
@ -154,7 +154,7 @@ Phone: ${object.company_id.phone}
% if object.company_id.website:
${object.company_id.website or ''}
% endif
</field>
]]></field>
</record>
</data>
</openerp>

View File

@ -1,38 +1,20 @@
-
I create a company for Customer
In order to test the EDI export features of Invoices
-
!record {model: res.company, id: res_company_test11}:
name: Thomson pvt. ltd.
partner_id: 1
rml_header: 1
rml_header2: 1
rml_header3: 1
currency_id: 1
First I create a draft customer invoice
-
I create a partner which is a my customer
-
!record {model: res.partner, id: res_partner_test20}:
name: Junjun wala
supplier: False
company_id: res_company_test11
opt_out: True
-
I create one customer invoice
-
!record {model: account.invoice, id: customer_invoice_test}:
!record {model: account.invoice, id: invoice_edi_1}:
journal_id: 1
partner_id: res_partner_test20
partner_id: base.res_partner_agrolait
currency_id: base.EUR
address_invoice_id: base.res_partner_address_11
company_id: res_company_test11
address_invoice_id: base.res_partner_address_8invoice
company_id: 1
account_id: account.a_pay
date_invoice: '2011-06-22'
name: selling product
type: 'out_invoice'
invoice_line:
- product_id: product.product_product_pc1
partner_id: res_partner_test20
uos_id: 1
quantity: 1.0
price_unit: 10.0
@ -40,117 +22,93 @@
account_id: account.a_pay
invoice_line:
- product_id: product.product_product_pc3
partner_id: res_partner_test20
uos_id: 1
quantity: 5.0
price_unit: 100.0
name: 'Medium PC'
account_id: account.a_pay
tax_line:
- name: sale tax
account_id: account.a_pay
manual: True
amount: 1000.00
-
I Open the Invoice
I confirm and open the invoice
-
!workflow {model: account.invoice, ref: invoice_edi_1, action: invoice_open}
-
Then I export the customer invoice
-
!python {model: edi.document}: |
invoice_pool = self.pool.get('account.invoice')
invoice = invoice_pool.browse(cr, uid, ref("invoice_edi_1"))
token = self.export_edi(cr, uid, [invoice])
assert token, 'Invalid EDI Token'
-
Then I import a sample EDI document of another customer invoice
-
!python {model: account.invoice}: |
invoices = self.browse(cr, uid, ref("customer_invoice_test"))
import netsvc
wf_service = netsvc.LocalService("workflow")
wf_service.trg_validate(uid, 'account.invoice',invoices.id,'invoice_open', cr)
-
I Testing of EDI functionality. First I export customer invoice from my company than import that invoice into customer company
-
!python {model: ir.edi.document}: |
invoice_pool = self.pool.get('account.invoice')
invoice = invoice_pool.browse(cr, uid, ref("customer_invoice_test"))
tokens = self.export_edi(cr, uid, [invoice])
assert tokens, 'Token is not generated'
-
I import of EDI document of custmer invoice
-
!python {model: ir.edi.document}: |
invoice_pool = self.pool.get('account.invoice')
edi_document = {
"__id": "account:b22acf7a-ddcd-11e0-a4db-701a04e25543.random_invoice_763jsms",
"__module": "account",
"__model": "account.invoice",
"__version": [6,1,0],
"internal_number": "SAJ/2011/002",
"company_address": {
"__id": "base:b22acf7a-ddcd-11e0-a4db-701a04e25543.main_address",
"__module": "base",
"__model": "res.partner.address",
"city": "Gerompont",
"zip": "1367",
"__last_update": False,
"country_id": ["b22acf7a-ddcd-11e0-a4db-701a04e25543:base.be", "Belgium"],
"__id": "b22acf7a-ddcd-11e0-a4db-701a04e25543:base.main_address",
"country_id": ["base:b22acf7a-ddcd-11e0-a4db-701a04e25543.be", "Belgium"],
"phone": "(+32).81.81.37.00",
"street": "Chaussee de Namur 40"
},
"company_id": ["b22acf7a-ddcd-11e0-a4db-701a04e25543:account.res_company_test11", "Thomson pvt. ltd."],
"currency_id": ["b22acf7a-ddcd-11e0-a4db-701a04e25543:base.EUR", "EUR (\u20ac)"],
"address_invoice_id": ["b22acf7a-ddcd-11e0-a4db-701a04e25543:base.res_partner_address_11", "Sebastien LANGE, France, Alencon, 1 place de l'\u00c9glise"],
"partner_id": ["b22acf7a-ddcd-11e0-a4db-701a04e25543:account.res_partner_test20", "Junjun wala"],
"__attachments": [],
"__module": "account",
"amount_total": 1010.0,
"company_id": ["account:b22acf7a-ddcd-11e0-a4db-701a04e25543.res_company_test11", "Thomson pvt. ltd."],
"currency_id": ["base:b22acf7a-ddcd-11e0-a4db-701a04e25543.EUR", "EUR (€)"],
"address_invoice_id": ["base:b22acf7a-ddcd-11e0-a4db-701a04e25543.res_partner_address_11", "Sebastien LANGE, France, Alencon, 1 place de l'\u00c9glise"],
"partner_id": ["account:b22acf7a-ddcd-11e0-a4db-701a04e25543.res_partner_test20", "Junjun wala"],
"date_invoice": "2011-06-22",
"amount_untaxed": 10.0,
"name": "selling product",
"__model": "account.invoice",
"__last_update": False,
"name": "sample invoice",
"tax_line": [{
"__id": "account:b22acf7a-ddcd-11e0-a4db-701a04e25543.account_invoice_tax-4g4EutbiEMVl",
"__module": "account",
"__model": "account.invoice.tax",
"amount": 1000.0,
"manual": True,
"__id": "b22acf7a-ddcd-11e0-a4db-701a04e25543:b22acf7a-ddcd-11e0-a4db-701a04e25543:account.account_invoice_tax-4g4EutbiEMVl",
"name": "sale tax",
"__last_update": False
}],
"__id": "b22acf7a-ddcd-11e0-a4db-701a04e25543:account.customer_invoice_test",
"amount_tax": 1000.0,
"__version": [6, 1],
"type": "out_invoice",
"invoice_line": [{
"uos_id": ["b22acf7a-ddcd-11e0-a4db-701a04e25543:product.product_uom_unit", "PCE"],
"name": "basic pc",
"__last_update": False,
"__module": "account",
"__model": "account.invoice.line",
"__id": "account:b22acf7a-ddcd-11e0-a4db-701a04e25543.account_invoice_line-1RP3so",
"uos_id": ["product:b22acf7a-ddcd-11e0-a4db-701a04e25543.product_uom_unit", "PCE"],
"name": "Basic PC",
"price_unit": 10.0,
"price_subtotal": 10.0,
"__id": "b22acf7a-ddcd-11e0-a4db-701a04e25543:b22acf7a-ddcd-11e0-a4db-701a04e25543:account.account_invoice_line-1RP3so-u2vV4",
"product_id": ["b22acf7a-ddcd-11e0-a4db-701a04e25543:product.product_product_pc1", "[PC1] Basic PC"],
"product_id": ["product:b22acf7a-ddcd-11e0-a4db-701a04e25543.product_product_pc1", "[PC1] Basic PC"],
"quantity": 1.0
},
{
"uos_id": ["b22acf7a-ddcd-11e0-a4db-701a04e25543:product.product_uom_unit", "PCE"],
"name": "Medim PC",
"__last_update": False,
"__module": "account",
"__model": "account.invoice.line",
"__id": "account:b22acf7a-ddcd-11e0-a4db-701a04e25543.account_invoice_line-u2XV5",
"uos_id": ["product:b22acf7a-ddcd-11e0-a4db-701a04e25543.product_uom_unit", "PCE"],
"name": "Medium PC",
"price_unit": 100.0,
"price_subtotal": 100.0,
"__id": "b22acf7a-ddcd-11e0-a4db-701a04e25543:b22acf7a-ddcd-11e0-a4db-701a04e25543:account.account_invoice_line-1RP3so-u2vV4",
"product_id": ["b22acf7a-ddcd-11e0-a4db-701a04e25543:product.product_product_pc3", "[PC3] Medium PC"],
"product_id": ["product:b22acf7a-ddcd-11e0-a4db-701a04e25543.product_product_pc3", "[PC3] Medium PC"],
"quantity": 5.0
}]
}
invoice_id = invoice_pool.edi_import(cr, uid, edi_document, context=context)
invoice_new = invoice_pool.browse(cr, uid, invoice_id, context=context)
assert invoice_id, 'Invoice is not imported'
-
I Checking the out invoice become in invoice or not after import
-
!python {model: account.invoice}: |
new_partner_id = self.pool.get('res.partner').name_search(cr, uid, "Thomson pvt. ltd.")
assert new_partner_id, 'Partner is not created of Supplier'
ids = self.search(cr, uid, [('partner_id','=',new_partner_id[0][0]),('reference','=',"SAJ/2011/002")])
assert ids, 'Invoice does not have created of party'
invoice_new = self.browse(cr, uid, ids[0])
invoice_id = self.edi_import(cr, uid, edi_document, context=context)
assert invoice_id, 'EDI import failed'
invoice_new = self.browse(cr, uid, invoice_id)
assert invoice_new.partner_id.supplier, 'Imported Partner is not marked as supplier'
assert invoice_new.reference == "SAJ/2011/002", "internal number is not stored in reference"
assert invoice_new.reference_type == 'none', "reference type is not set to 'None'"
assert invoice_new.reference_type == 'none', "reference type is not set to 'none'"
assert invoice_new.internal_number == False, "internal number is not reset"
assert invoice_new.journal_id.id, "journal id is not selected"
assert invoice_new.type == 'in_invoice', "Imported in voice is not supplier invoice"
assert invoice_new.type == 'in_invoice', "Invoice type was not set properly"
assert len(invoice_new.invoice_line) == 2, "invoice lines are not same"
for inv_line in invoice_new.invoice_line:
if inv_line.name == 'basic pc':
@ -162,7 +120,7 @@
assert inv_line.uos_id.name == "PCE" , "uom is not same"
assert inv_line.price_unit == 100 , "price unit is not same"
assert inv_line.quantity == 5 , "product qty is not same"
assert inv_line.price_subtotal == 100, "price sub total is not same"
assert inv_line.price_subtotal == 500, "price sub total is not same"
else:
assert 'wrong product imported in invoice lines'
for inv_tax in invoice_new.tax_line: