diff --git a/addons/purchase/__init__.py b/addons/purchase/__init__.py index 623eae1d6a9..66f92a60831 100644 --- a/addons/purchase/__init__.py +++ b/addons/purchase/__init__.py @@ -26,6 +26,7 @@ import wizard import report import stock import company -#import edi_purchase_order +import edi + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/purchase/__openerp__.py b/addons/purchase/__openerp__.py index d8415fc17c2..2953e8e3d89 100644 --- a/addons/purchase/__openerp__.py +++ b/addons/purchase/__openerp__.py @@ -58,7 +58,7 @@ Dashboard for purchase management that includes: 'process/purchase_process.xml', 'report/purchase_report_view.xml', 'board_purchase_view.xml', - #'edi_purchase_order_data.xml', + 'edi/purchase_order_action_data.xml', ], 'test': [ 'test/purchase_from_order.yml', @@ -67,7 +67,7 @@ Dashboard for purchase management that includes: 'purchase_unit_test.xml', 'test/procurement_buy.yml', 'test/purchase_report.yml', - #'test/edi_purchase_order.yml', + 'test/edi_purchase_order.yml', ], 'demo': ['purchase_demo.xml'], 'installable': True, diff --git a/addons/purchase/edi/__init__.py b/addons/purchase/edi/__init__.py new file mode 100644 index 00000000000..cfac0182d76 --- /dev/null +++ b/addons/purchase/edi/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Business Applications +# Copyright (c) 2011 OpenERP S.A. +# +# 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 . +# +############################################################################## + +import purchase_order \ No newline at end of file diff --git a/addons/purchase/edi/purchase_order.py b/addons/purchase/edi/purchase_order.py new file mode 100644 index 00000000000..4ac25adf23b --- /dev/null +++ b/addons/purchase/edi/purchase_order.py @@ -0,0 +1,180 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Business Applications +# Copyright (c) 2011 OpenERP S.A. +# +# 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 . +# +############################################################################## + +from datetime import datetime, timedelta +from dateutil.relativedelta import relativedelta + +from osv import fields, osv, orm +from edi import EDIMixin +from tools import DEFAULT_SERVER_DATE_FORMAT +from tools.translate import _ + +PURCHASE_ORDER_LINE_EDI_STRUCT = { + 'name': True, + 'date_planned': True, + 'product_id': True, + 'product_uom': True, + 'price_unit': True, + 'product_qty': True, + 'notes': True, +} + +PURCHASE_ORDER_EDI_STRUCT = { + 'company_id': True, # -> to be changed into partner + 'name': True, + 'partner_ref': True, + 'origin': True, + 'date_order': True, + 'partner_id': True, + #custom: 'partner_address', + 'notes': True, + 'order_line': PURCHASE_ORDER_LINE_EDI_STRUCT, + #custom: currency_id +} + +class purchase_order(osv.osv, EDIMixin): + _inherit = 'purchase.order' + + def edi_export(self, cr, uid, records, edi_struct=None, context=None): + """Exports a purchase order""" + edi_struct = dict(edi_struct or PURCHASE_ORDER_EDI_STRUCT) + res_company = self.pool.get('res.company') + res_partner_address = self.pool.get('res.partner.address') + edi_doc_list = [] + for order in records: + # Get EDI doc based on struct. The result will also contain all metadata fields and attachments. + edi_doc = super(purchase_order,self).edi_export(cr, uid, [order], edi_struct, context)[0] + edi_doc.update({ + # force trans-typing to purchase.order upon import + '__import_model': 'sale', + '__import_module': 'sale', + + 'company_address': res_company.edi_export_address(cr, uid, order.company_id, context=context), + 'company_paypal_account': order.company_id.paypal_account, + 'partner_address': res_partner_address.edi_export(cr, uid, [order.partner_address_id], context=context)[0], + + 'currency_id': self.edi_m2o(cr, uid, order.pricelist_id.currency_id, context=context), + #'company_logo': #TODO + }) + edi_doc_list.append(edi_doc) + return edi_doc_list + + def edi_import_company(self, cr, uid, edi_document, context=None): + # TODO: for multi-company setups, we currently import the document in the + # user's current company, but we should perhaps foresee a way to select + # the desired company among the user's allowed companies + + self._edi_requires_attributes(('company_id','company_address'), edi_document) + res_partner_address = self.pool.get('res.partner.address') + res_partner = self.pool.get('res.partner') + + # imported company = as a new partner + src_company_id, src_company_name = edi_document.pop('company_id') + partner_id = self.edi_import_relation(cr, uid, 'res.partner', src_company_name, + src_company_id, context=context) + partner_value = {'customer': True} + res_partner.write(cr, uid, [partner_id], partner_value, context=context) + + # imported company_address = new partner address + address_info = edi_document.pop('company_address') + address_info['partner_id'] = (src_company_id, src_company_name) + address_info['type'] = 'default' + address_id = res_partner_address.edi_import(cr, uid, address_info, context=context) + + # modify edi_document to refer to new partner/address + partner_address = res_partner_address.browse(cr, uid, address_id, context=context) + edi_document['partner_id'] = (src_company_id, src_company_name) + edi_document.pop('partner_address', False) # ignored + edi_document['partner_address_id'] = self.edi_m2o(cr, uid, partner_address, context=context) + + return partner_id + + def _edi_get_pricelist(self, cr, uid, partner_id, currency, context=None): + # TODO: refactor into common place for purchase/sale, e.g. into product module + partner_model = self.pool.get('res.partner') + partner = partner_model.browse(cr, uid, partner_id, context=context) + pricelist = partner.property_product_pricelist_purchase + if not pricelist: + pricelist = self.pool.get('ir.model.data').get_object(cr, uid, 'purchase', 'list0', context=context) + + if not pricelist.currency_id == currency: + # look for a pricelist with the right type and currency, or make a new one + pricelist_type = 'purchase' + product_pricelist = self.pool.get('product.pricelist') + match_pricelist_ids = product_pricelist.search(cr, uid,[('type','=',pricelist_type), + ('currency_id','=',currency.id)]) + if match_pricelist_ids: + pricelist_id = match_pricelist_ids[0] + else: + pricelist_name = _('EDI Pricelist (%s)') % (currency.name,) + pricelist_id = product_pricelist.create(cr, uid, {'name': pricelist_name, + 'type': pricelist_type, + 'currency_id': currency.id, + }) + self.pool.get('product.pricelist.version').create(cr, uid, {'name': pricelist_name, + 'pricelist_id': pricelist_id}) + pricelist = product_pricelist.browse(cr, uid, pricelist_id) + + return self.edi_m2o(cr, uid, pricelist, context=context) + + def _edi_get_location(self, cr, uid, partner_id, context=None): + partner_model = self.pool.get('res.partner') + partner = partner_model.browse(cr, uid, partner_id, context=context) + location = partner.property_stock_customer + if not location: + location = self.pool.get('ir.model.data').get_object(cr, uid, 'stock', 'stock_location_stock', context=context) + return self.edi_m2o(cr, uid, location, context=context) + + def edi_import(self, cr, uid, edi_document, context=None): + self._edi_requires_attributes(('company_id','company_address','order_line','date_order','currency_id'), edi_document) + + #import company as a new partner + partner_id = self.edi_import_company(cr, uid, edi_document, context=context) + + # currency for rounding the discount calculations and for the pricelist + currency_id, currency_name = edi_document.pop('currency_id') + currency_id = self.edi_import_relation(cr, uid, 'res.currency', currency_name, currency_id, context=context) + res_currency = self.pool.get('res.currency') + order_currency = res_currency.browse(cr, uid, currency_id) + + partner_ref = edi_document.pop('partner_ref', False) + edi_document['partner_ref'] = edi_document['name'] + edi_document['name'] = partner_ref or edi_document['name'] + edi_document['pricelist_id'] = self._edi_get_pricelist(cr, uid, partner_id, order_currency, context=context) + edi_document['location_id'] = self._edi_get_location(cr, uid, partner_id, context=context) + + for order_line in edi_document['order_line']: + self._edi_requires_attributes(('date_planned', 'product_id', 'product_uom', 'product_qty', 'price_unit'), order_line) + # original sale order contains unit price and discount, but not final line price + discount = order_line.pop('discount', 0.0) + if discount: + order_line['price_unit'] = res_currency.round(cr, uid, order_currency, + (order_line['price_unit'] * (1 - (discount or 0.0) / 100.0))) + # sale order lines have sequence numbers, not purchase order lines + order_line.pop('sequence', None) + + return super(purchase_order,self).edi_import(cr, uid, edi_document, context=context) + +class purchase_order_line(osv.osv, EDIMixin): + _inherit='purchase.order.line' + + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file diff --git a/addons/purchase/edi/purchase_order_action_data.xml b/addons/purchase/edi/purchase_order_action_data.xml new file mode 100644 index 00000000000..68e95dbad66 --- /dev/null +++ b/addons/purchase/edi/purchase_order_action_data.xml @@ -0,0 +1,169 @@ + + + + + + ") + + # accessing the template will fail if it has been deleted - so we'll skip everything + tmpl = self.pool.get('ir.model.data').get_object(cr, uid, 'purchase', 'email_template_edi_purchase') + + edi_token = self.pool.get('edi.document').export_edi(cr, uid, [object], context = context)[0] + context.update(edi_web_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 + ]]> + code + ir.actions.server + + True + Auto-email confirmed purchase orders + + + + + + + + + + + + + Automated Purchase Order Notification Mail + ${object.validator.user_email or ''} + ${object.company_id.name} Order (Ref ${object.name or 'n/a' }) + ${object.partner_address_id.email} + + + +

Hello${object.partner_address_id.name and ' ' or ''}${object.partner_address_id.name or ''},

+ +

Your order for ${object.partner_id.name} has just been validated:

+ +

+   REFERENCES
+   Order number: ${object.name}
+   Order total: ${object.amount_total} ${object.pricelist_id.currency_id.name}
+   Order date: ${object.date_order}
+ % if object.origin: +   Order reference: ${object.origin}
+ % endif + % if object.partner_ref: +   Your reference: ${object.partner_ref}
+ % endif +   Your contact: ${object.validator.name} +

+ +

+ You can view the order confirmation document, download it and pay online using the following link: +

+ View Order + + % if object.company_id.paypal_account: +
+

It is also possible to directly pay with Paypal:

+ Pay with Paypal + % endif + +
+

If you have any question, do not hesitate to contact us.

+

Thank you for choosing ${object.company_id.name or 'us'}!

+
+
+
+

+ ${object.company_id.name}

+
+
+ + % if object.company_id.street: + ${object.company_id.street}
+ % endif + % if object.company_id.street2: + ${object.company_id.street2}
+ % endif + % if object.company_id.city or object.company_id.zip: + ${object.company_id.zip} ${object.company_id.city}
+ % 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 ''}
+ % endif +
+ % if object.company_id.phone: +
+ Phone:  ${object.company_id.phone} +
+ % endif + % if object.company_id.website: + + %endif +

+
+ + ]]>
+ + % endif + | Your contact: ${object.validator.name} ${object.validator.user_email and '<%s>'%(object.validator.user_email) or ''} + +You can view the order confirmation, download it and even pay online using the following link: + ${ctx.get('edi_web_url_view') or 'n/a'} + +% if object.company_id.paypal_account: +It is also possible to directly pay with Paypal: + ${"https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=%s&item_name=OpenERP%%20Order%%20%s&invoice=%s&amount=%s¤cy_code=%s&button_subtype=services&no_note=1&bn=OpenERP_Order_PayNow_%s"%(object.company_id.paypal_account,object.name and object.name.replace('/','%2f') or '', object.name and object.name.replace('/','%2f') or '', object.amount_total, object.pricelist_id.currency_id.name, object.pricelist_id.currency_id.name)} +% endif + +If you have any question, do not hesitate to contact us. + + +Thank you for choosing ${object.company_id.name}! + + +-- +${object.validator.name} ${object.validator.user_email and '<%s>'%(object.validator.user_email) or ''} +${object.company_id.name} +% if object.company_id.street: +${object.company_id.street or ''} +% endif +% if object.company_id.street2: +${object.company_id.street2} +% endif +% if object.company_id.city or object.company_id.zip: +${object.company_id.zip or ''} ${object.company_id.city or ''} +% 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 ''} +% endif +% if object.company_id.phone: +Phone: ${object.company_id.phone} +% endif +% if object.company_id.website: +${object.company_id.website or ''} +% endif + ]]> +
+
+
\ No newline at end of file diff --git a/addons/purchase/edi_purchase_order.py b/addons/purchase/edi_purchase_order.py deleted file mode 100644 index 9119485bffc..00000000000 --- a/addons/purchase/edi_purchase_order.py +++ /dev/null @@ -1,157 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2009 Tiny SPRL (). -# -# 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 . -# -############################################################################## - -from osv import fields, osv, orm -from base.ir import ir_edi -from tools.translate import _ -from datetime import date, datetime, timedelta - -class purchase_order(osv.osv, ir_edi.edi): - _inherit = 'purchase.order' - - def edi_export(self, cr, uid, records, edi_struct=None, context=None): - """Exports a purchase order""" - edi_struct = { - 'company_id': True, # -> to be changed into partner - 'name': True, - 'partner_ref': True, - 'origin': True, - 'date_order': True, - 'partner_id': True, - 'partner_address_id': True, #only one address needed - #SO: 'partner_order_id' - #PO: 'partner_address_id' - - 'pricelist_id': True, - 'notes': True, - #SO: 'note' - #PO: 'notes' - - 'amount_total': True, - 'amount_tax': True, - 'amount_untaxed': True, - 'order_line': { - 'name': True, - 'date_planned': True, - #SO: 'delay' : 'date_order' - 'date_planned' - #PO: 'date_planned': 'date_order' + 'delay' - - 'product_id': True, - 'product_uom': True, - 'price_unit': True, - 'price_subtotal': True, - 'product_qty': True, - #SO: 'product_uom_qty' - #PO: 'product_qty' - - 'notes': True, - } - } - company_pool = self.pool.get('res.company') - edi_doc_list = [] - for order in records: - # Get EDI doc based on struct. The result will also contain all metadata fields and attachments. - edi_doc = super(purchase_order,self).edi_export(cr, uid, [order], edi_struct, context) - if not edi_doc: - continue - edi_doc = edi_doc[0] - currency = order.company_id.currency_id - - # Add company info and address - edi_company_document = company_pool.edi_export_address(cr, uid, [order.company_id], context=context)[order.company_id.id] - edi_doc.update({ - 'company_address': edi_company_document['company_address'], - 'currency_id': currency and self.edi_m2o(cr, uid, currency, context=context) or False, - #'company_logo': edi_company_document['company_logo'],#TODO - }) - edi_doc_list.append(edi_doc) - return edi_doc_list - - 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') - - # import company as a new partner, supplier=1. - # company_address data used to add address to new partner - partner_value = {'customer': True} - partner_id = company_pool.edi_import_as_partner(cr, uid, edi_document, values=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['partner_address_id'] = self.edi_m2o(cr, uid, partner_address, context=context) - del edi_document['company_id'] - return partner_id - - def edi_get_pricelist(self, cr, uid, partner_id, context=None): - # return value = ["724f93ec-ddd0-11e0-88ec-701a04e25543:product.list0", "Public Pricelist (EUR)"] - partner_model = self.pool.get('res.partner') - partner = partner_model.browse(cr, uid, partner_id, context=context) - pricelist = partner.property_product_pricelist_purchase - if not pricelist: - pricelist = self.pool.get('ir.model.data').get_object(cr, uid, 'purchase', 'list0', context=context) - return self.edi_m2o(cr, uid, pricelist, context=context) - - def edi_get_location(self, cr, uid, partner_id, context=None): - # return value = ["724f93ec-ddd0-11e0-88ec-701a04e25543:stock.stock_location_stock", "Stock"] - partner_model = self.pool.get('res.partner') - partner = partner_model.browse(cr, uid, partner_id, context=context) - location = partner.property_stock_customer - if not location: - location = self.pool.get('ir.model.data').get_object(cr, uid, 'stock', 'stock_location_stock', context=context) - return self.edi_m2o(cr, uid, location, context=context) - - def edi_import(self, cr, uid, edi_document, context=None): - if context is None: - context = {} - - #import company as a new partner - partner_id = self.edi_import_company(cr, uid, edi_document, context=context) - - edi_document['partner_ref'] = edi_document['name'] - edi_document['notes'] = edi_document.get('note', False) - edi_document['pricelist_id'] = self.edi_get_pricelist(cr, uid, partner_id, context=context) - edi_document['location_id'] = self.edi_get_location(cr, uid, partner_id, context=context) - for order_line in edi_document['order_line']: - order_line['product_qty'] = order_line['product_uom_qty'] - date_order = datetime.strptime(edi_document['date_order'], "%Y-%m-%d") - delay = order_line.get('delay', 0.0) - order_line['date_planned'] = (date_order + timedelta(days=delay)).strftime("%Y-%m-%d") - # price_unit = price_unit - discount - discount = order_line.get('discount', 0.0) - price_unit = order_line['price_unit'] - if discount: - price_unit = price_unit * (1 - (discount or 0.0) / 100.0) - order_line['price_unit'] = price_unit - - return super(purchase_order,self).edi_import(cr, uid, edi_document, context=context) -purchase_order() - -class purchase_order_line(osv.osv, ir_edi.edi): - _inherit='purchase.order.line' - -purchase_order_line() -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/purchase/edi_purchase_order_data.xml b/addons/purchase/edi_purchase_order_data.xml deleted file mode 100644 index 02ecb24b9ba..00000000000 --- a/addons/purchase/edi_purchase_order_data.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - context.update({'edi_web_purchase_url_view': '%s/web/view_edi?db=%s&token=%s' %(self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url'),cr.dbname, self.pool.get('ir.edi.document').export_edi(cr, uid, [object], context = context)[0])}) -if not object.partner_id.opt_out: self.pool.get('email.template').send_mail(cr, - uid, - self.pool.get('ir.model.data').get_object_reference(cr, uid, 'purchase', 'email_template_edi_purchase')[1], - object.id, - context=context) - - code - ir.actions.server - - True - EDI Document - Purchase Order - - - - - - - - - - - - Mail Template of Purchase Order For EDI Document - ${object.validator.user_email or ''} - ${object.validator.user_email or ''} - ${object.company_id.name} - Purchase Order ${object.name} - ${object.partner_address_id.email} - - -<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); "> - -<p> Hello ${object.partner_address_id.name and ' ' or ''},</p> -<p> You can click on the following link to preview purchase order: <br/> - <a href="${object._context.get('edi_web_purchase_url_view')}">${object._context.get('edi_web_purchase_url_view')} </a> -</p> - - -<p style="border-left: 1px solid #8e0000; margin-left: 30px;"> <strong>REFERENCES</strong><br /> Order number: <strong>${object.name}</strong><br /> Order amount: <strong>${object.amount_total} </strong><br /> Order date: ${object.date_order or 'n/a'}<br /> Your contact: <a href="mailto:${object.validator.user_email or ''}?subject=Order%20${object.name}">${object.validator.name}</a></p> - - -<p> If you have any question, do not hesitate to reply directly to this e-mail.</p> <p> Thank you for choosing OpenERP!<br /> </p> <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-image: url(http://www.openerp.com/sites/default/files/red_gradient_bg.png); 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>${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); "> <div> Contact:<a href="mailto:${object.validator.user_email or ''}?subject=Order%20${object.name}">${object.validator.name}</a></div> <div> </div> </div> </div> <p> </p> - - -Hello ${object.partner_address_id.name and ' ' or ''}, - -You can click on the following link to preview Purchase Order: - - ${object._context.get('edi_web_purchase_url_view') or 'n/a'} - -Order Number: *${object.name}* -Amount: *${object.amount_total}* -Order date: ${object.date_order or 'n/a'} -Your contact: ${object.validator.name} ${object.validator.user_email and '<%s>'%(object.validator.user_email) or ''} - - -If you have any question, do not hesitate to reply directly to this e-mail. - -Thank you for choosing our service! - --- -${object.company_id.name} -Contact: ${object.validator.name} ${object.validator.user_email and '<%s>'%(object.validator.user_email) or ''} - - - - - diff --git a/addons/purchase/test/edi_purchase_order.yml b/addons/purchase/test/edi_purchase_order.yml index a5d06329bb5..68519fd0313 100644 --- a/addons/purchase/test/edi_purchase_order.yml +++ b/addons/purchase/test/edi_purchase_order.yml @@ -1,17 +1,9 @@ - - I create a partner which is a my customer + I create a draft Purchase Order - - !record {model: res.partner, id: res_partner_test20}: - name: jones white - supplier: False - customer: True - opt_out: True -- - I create one Purchase Order -- - !record {model: purchase.order, id: purchase_order_test}: - partner_id: res_partner_test20 - partner_address_id: base.res_partner_address_11 + !record {model: purchase.order, id: purchase_order_edi_1}: + partner_id: base.res_partner_agrolait + partner_address_id: base.res_partner_address_8invoice location_id: stock.stock_location_3 pricelist_id: 1 order_line: @@ -19,108 +11,111 @@ product_qty: 1.0 product_uom: 1 price_unit: 150.0 - name: 'basic pc' + name: 'Basic PC' date_planned: '2011-08-31' order_line: - product_id: product.product_product_pc3 product_qty: 10.0 product_uom: 1 price_unit: 20.0 - name: 'medium pc' + name: 'Medium PC' date_planned: '2011-08-31' + - - I Open the Purchase order + I confirm the purchase order - - !python {model: purchase.order}: | - - orders = self.browse(cr, uid, ref("purchase_order_test")) - import netsvc - wf_service = netsvc.LocalService("workflow") - wf_service.trg_validate(uid, 'purchase.order',orders.id,'approved', cr) + !workflow {model: purchase.order, ref: purchase_order_edi_1, action: purchase_confirm} - - I Tesing of EDI functionality. First I export Purchase Order from my company than import that Order into customer company + Then I export the purchase order via EDI - - !python {model: ir.edi.document}: | + !python {model: edi.document}: | order_pool = self.pool.get('purchase.order') - order = order_pool.browse(cr, uid, ref("purchase_order_test")) - - tokens = self.export_edi(cr, uid, [order]) - assert tokens, 'Token is not generated' + order = order_pool.browse(cr, uid, ref("purchase_order_edi_1")) + token = self.export_edi(cr, uid, [order]) + assert token, 'Invalid EDI Token' - - I import purchase order from EDI Document of sale order + Then I import a sample EDI document of a sale order - - !python {model: ir.edi.document}: | + !python {model: edi.document}: | purchase_order_pool = self.pool.get('purchase.order') edi_document = { - "order_line": [{ - "product_uom_qty": 1.0, - "name": "basic pc", - "product_uom": ["724f93ec-ddd0-11e0-88ec-701a04e25543:product.product_uom_unit", "PCE"], - "sequence": 10, - "price_unit": 150.0, - "__last_update": False, - "__id": "724f93ec-ddd0-11e0-88ec-701a04e25543:724f93ec-ddd0-11e0-88ec-701a04e25543:sale.sale_order_line-LXEqeuI-SSP0", - "product_id": ["724f93ec-ddd0-11e0-88ec-701a04e25543:product.product_product_pc1", "[PC1] Basic PC"] - }, - { - "product_uom_qty": 10.0, - "name": "medium pc", - "product_uom": ["724f93ec-ddd0-11e0-88ec-701a04e25543:product.product_uom_unit", "PCE"], - "sequence": 11, - "price_unit": 20.0, - "__last_update": False, - "__id": "724f93ec-ddd0-11e0-88ec-701a04e25543:724f93ec-ddd0-11e0-88ec-701a04e25543:sale.sale_order_line-LXEqeuI-SSP0", - "product_id": ["724f93ec-ddd0-11e0-88ec-701a04e25543:product.product_product_pc3", "[PC3] Medim PC"] - }], - "order_policy": "manual", - "company_address": { + "__id": "sale:724f93ec-ddd0-11e0-88ec-701a04e25543.sale_order_test", + "__module": "sale", + "__model": "sale.order", + "__import_module": "purchase", + "__import_model": "purchase.order", + "__version": [6,1,0], + "name": "SO008", + "currency_id": ["base:724f93ec-ddd0-11e0-88ec-701a04e25543.EUR", "EUR (€)"], + "date_order": "2011-09-13", + "partner_id": ["sale:724f93ec-ddd0-11e0-88ec-701a04e25543.res_partner_test22", "Junjun wala"], + "partner_address": { + "__id": "base:724f93ec-ddd0-11e0-88ec-701a04e25543.res_partner_address_7wdsjasdjh", + "__module": "base", + "__model": "res.partner.address", + "phone": "(+32).81.81.37.00", + "street": "Chaussee de Namur 40", "city": "Gerompont", "zip": "1367", - "__last_update": False, - "country_id": ["724f93ec-ddd0-11e0-88ec-701a04e25543:base.be", "Belgium"], - "__id": "724f93ec-ddd0-11e0-88ec-701a04e25543:base.main_address", + "country_id": ["base:5af1272e-dd26-11e0-b65e-701a04e25543.be", "Belgium"], + }, + "company_id": ["base:724f93ec-ddd0-11e0-88ec-701a04e25543.main_company", "Supplier S.A."], + "company_address": { + "__id": "base:724f93ec-ddd0-11e0-88ec-701a04e25543.main_address", + "__module": "base", + "__model": "res.partner.address", + "city": "Gerompont", + "zip": "1367", + "country_id": ["base:724f93ec-ddd0-11e0-88ec-701a04e25543.be", "Belgium"], "phone": "(+32).81.81.37.00", - "street": "Chaussee de Namur 40" + "street": "Chaussee de Namur 40", + "street2": "mailbox 34", }, - "partner_order_id": ["724f93ec-ddd0-11e0-88ec-701a04e25543:base.res_partner_address_3", "Thomas Passot, Belgium, Louvain-la-Neuve, Rue de l'Angelique, 1"], - "__id": "724f93ec-ddd0-11e0-88ec-701a04e25543:sale.sale_order_test", - "date_order": "2011-09-13", - "partner_id": ["724f93ec-ddd0-11e0-88ec-701a04e25543:sale.res_partner_test22", "Junjun wala"], - "__attachments": [], - "__module": "purchase", - "amount_total": 350.0, - "amount_untaxed": 350.0, - "name": "SO008", - "__model": "purchase.order", - "__last_update": False, - "company_id": ["724f93ec-ddd0-11e0-88ec-701a04e25543:base.main_company", "Supplier S.A."], - "__version": [6, 1], - "pricelist_id": ["724f93ec-ddd0-11e0-88ec-701a04e25543:product.list0", "Public Pricelist (EUR)"] + "order_line": [{ + "__id": "sale:724f93ec-ddd0-11e0-88ec-701a04e25543.sale_order_line-LXEqeuI-SSP0", + "__module": "sale", + "__model": "sale.order.line", + "__import_module": "purchase", + "__import_model": "purchase.order.line", + "name": "Basic PC", + "product_uom": ["product:724f93ec-ddd0-11e0-88ec-701a04e25543.product_uom_unit", "PCE"], + "product_qty": 1.0, + "date_planned": "2011-09-30", + "sequence": 10, + "price_unit": 150.0, + "product_id": ["product:724f93ec-ddd0-11e0-88ec-701a04e25543.product_product_pc1", "[PC1] Basic PC"], + }, + { + "__id": "sale:724f93ec-ddd0-11e0-88ec-701a04e25543.sale_order_line-LXEqeadasdad", + "__module": "sale", + "__model": "sale.order.line", + "__import_module": "purchase", + "__import_model": "purchase.order.line", + "name": "Medium PC", + "product_uom": ["product:724f93ec-ddd0-11e0-88ec-701a04e25543.product_uom_unit", "PCE"], + "product_qty": 10.0, + "sequence": 11, + "date_planned": "2011-09-15", + "price_unit": 20.0, + "product_id": ["product:724f93ec-ddd0-11e0-88ec-701a04e25543.product_product_pc3", "[PC3] Medium PC"], + }], } new_purchase_order_id = purchase_order_pool.edi_import(cr, uid, edi_document, context=context) - assert new_purchase_order_id, 'Purchase order is not imported' - -- - I Checking the sale order become purchase order or not after import -- - !python {model: purchase.order}: | - - ids = self.search(cr, uid, [('partner_id','=','Supplier S.A.'), ('partner_ref', '=', 'SO008')]) - assert ids, 'Order does not have created of party' - order_new = self.browse(cr, uid, ids[0]) - assert order_new.pricelist_id.name == 'Public Pricelist' , "Public Price list is not imported" + assert new_purchase_order_id, 'Purchase order import failed' + order_new = purchase_order_pool.browse(cr, uid, new_purchase_order_id) + assert order_new.pricelist_id.name == 'Default Purchase Pricelist' , "Default Purchase Pricelist was not automatically assigned" assert order_new.amount_total == 350, "Amount total is not same" assert order_new.amount_untaxed == 350, "untaxed amount is not same" - assert len(order_new.order_line) == 2, "Purchase lines are not same" + assert len(order_new.order_line) == 2, "Purchase order lines number mismatch" for purchase_line in order_new.order_line: - if purchase_line.name == 'basic pc': + if purchase_line.name == 'Basic PC': assert purchase_line.product_uom.name == "PCE" , "uom is not same" - assert purchase_line.price_unit == 150 , "price unit is not same" + assert purchase_line.price_unit == 150 , "unit price is not same, got %s, expected 150"%(purchase_line.price_unit,) assert purchase_line.product_qty == 1 , "product qty is not same" - elif purchase_line.name == 'medium pc': + elif purchase_line.name == 'Medium PC': assert purchase_line.product_uom.name == "PCE" , "uom is not same" - assert purchase_line.price_unit == 20 , "price unit is not same" + assert purchase_line.price_unit == 20 , "unit price is not same, got %s, expected 20"%(purchase_line.price_unit,) assert purchase_line.product_qty == 10 , "product qty is not same" else: - assert 'wrong product imported in purchase lines' + raise AssertionError('unknown order line: %s' % purchase_line)