diff --git a/addons/sale/__init__.py b/addons/sale/__init__.py index 379c2bec5b8..683113d63a3 100644 --- a/addons/sale/__init__.py +++ b/addons/sale/__init__.py @@ -29,5 +29,6 @@ import sale_installer import wizard import report import company -#import edi_sale_order +import edi + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale/__openerp__.py b/addons/sale/__openerp__.py index abb1f719158..56ceb0f5ff4 100644 --- a/addons/sale/__openerp__.py +++ b/addons/sale/__openerp__.py @@ -85,11 +85,11 @@ Dashboard for Sales Manager that includes: 'stock_view.xml', 'board_sale_view.xml', 'process/sale_process.xml', - #'edi_sale_order_data.xml', + 'edi/sale_order_action_data.xml', ], 'demo_xml': ['sale_demo.xml'], 'test': [ - #'test/edi_sale_order.yml', + 'test/edi_sale_order.yml', 'test/data_test.yml', 'test/manual_order_policy.yml', 'test/prepaid_order_policy.yml', diff --git a/addons/sale/edi/__init__.py b/addons/sale/edi/__init__.py new file mode 100644 index 00000000000..566b1714ffd --- /dev/null +++ b/addons/sale/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 sale_order \ No newline at end of file diff --git a/addons/sale/edi/sale_order.py b/addons/sale/edi/sale_order.py new file mode 100644 index 00000000000..958dd1f70ec --- /dev/null +++ b/addons/sale/edi/sale_order.py @@ -0,0 +1,173 @@ +# -*- 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 + +SALE_ORDER_LINE_EDI_STRUCT = { + 'sequence': True, + #SO: yes + #PO: No + 'name': True, + #custom: 'planned_date' + 'product_id': True, + 'product_uom': True, + 'price_unit': True, + #custom: 'product_qty' + 'discount': True, + #SO: yes + #PO: No + 'notes': True, +} + +SALE_ORDER_EDI_STRUCT = { + 'name': True, + 'origin': True, + 'company_id': True, # -> to be changed into partner + #custom: 'partner_ref' + 'date_order': True, + 'partner_id': True, + #custom: 'partner_address' + #custom: 'notes' + 'order_line': SALE_ORDER_LINE_EDI_STRUCT +} + +class sale_order(osv.osv, EDIMixin): + _inherit = 'sale.order' + + def edi_export(self, cr, uid, records, edi_struct=None, context=None): + """Exports a Sale order""" + edi_struct = dict(edi_struct or SALE_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(sale_order,self).edi_export(cr, uid, [order], edi_struct, context)[0] + edi_doc.update({ + # force trans-typing to purchase.order upon import + '__import_model': 'purchase', + '__import_module': 'purchase', + + '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_order_id], context=context)[0], + + 'currency_id': self.edi_m2o(cr, uid, order.company_id.currency_id, context=context), + 'partner_ref': order.client_order_ref or False, + 'notes': order.note or False, + #TODO: company_logo + }) + 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 = {'supplier': 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 + address_edi_m2o = self.edi_m2o(cr, uid, partner_address, context=context) + edi_document['partner_order_id'] = address_edi_m2o + edi_document['partner_invoice_id'] = address_edi_m2o + edi_document['partner_shipping_id'] = address_edi_m2o + + return partner_id + + def edi_get_pricelist(self, cr, uid, partner_id, context=None): + # 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 + if not pricelist: + pricelist = self.pool.get('ir.model.data').get_object(cr, uid, 'product', 'list0', context=context) + return self.edi_m2o(cr, uid, pricelist, context=context) + + def edi_import(self, cr, uid, edi_document, context=None): + self._edi_requires_attributes(('company_id','company_address','order_line','date_order'), edi_document) + + #import company as a new partner + partner_id = self._edi_import_company(cr, uid, edi_document, context=context) + + date_order = edi_document['date_order'] + edi_document['client_order_ref'] = edi_document.pop('partner_ref', False) + edi_document['note'] = edi_document.pop('notes', False) + edi_document['pricelist_id'] = self.edi_get_pricelist(cr, uid, partner_id, context=context) + order_lines = edi_document['order_line'] + for order_line in order_lines: + order_line['product_uom_qty'] = order_line['product_qty'] + del order_line['product_qty'] + date_planned = order_line.pop('date_planned') + delay = 0 + if date_order and date_planned: + # no security_days buffer, this is the promised date given by supplier + delay = (datetime.strptime(date_planned, DEFAULT_SERVER_DATE_FORMAT) - \ + datetime.strptime(date_order, DEFAULT_SERVER_DATE_FORMAT)).days + order_line['delay'] = delay + return super(sale_order,self).edi_import(cr, uid, edi_document, context=context) + +class sale_order_line(osv.osv, EDIMixin): + _inherit='sale.order.line' + + def edi_export(self, cr, uid, records, edi_struct=None, context=None): + edi_struct = dict(edi_struct or SALE_ORDER_LINE_EDI_STRUCT) + edi_doc_list = [] + for line in records: + edi_doc = super(sale_order_line,self).edi_export(cr, uid, [line], edi_struct, context)[0] + edi_doc['product_qty'] = line.product_uom_qty + if line.product_uos: + edi_doc.update(product_uom=line.product_uos, + product_qty=line.product_uos_qty) + + # company.security_days is for internal use, so customer should only + # see the expected date_planned based on line.delay + date_planned = datetime.strptime(line.order_id.date_order, DEFAULT_SERVER_DATE_FORMAT) + \ + relativedelta(days=line.delay or 0.0) + edi_doc['date_planned'] = date_planned.strftime(DEFAULT_SERVER_DATE_FORMAT) + edi_doc_list.append(edi_doc) + return edi_doc_list + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file diff --git a/addons/sale/edi/sale_order_action_data.xml b/addons/sale/edi/sale_order_action_data.xml new file mode 100644 index 00000000000..6d46006f384 --- /dev/null +++ b/addons/sale/edi/sale_order_action_data.xml @@ -0,0 +1,172 @@ + + + + + + ") + + # 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, 'sale', 'email_template_edi_sale') + + 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 sale orders + + + + + + + + + + + + + + + Automated Sale Order Notification Mail + ${object.user_id.user_email or ''} + ${object.company_id.name} Order (Ref ${object.name or 'n/a' }) + ${object.partner_invoice_id.email} + + + +

Hello${object.partner_order_id.name and ' ' or ''}${object.partner_order_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.client_order_ref: +   Your reference: ${object.client_order_ref}
+ % endif +   Your contact: ${object.user_id.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.user_id.name} ${object.user_id.user_email and '<%s>'%(object.user_id.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.user_id.name} ${object.user_id.user_email and '<%s>'%(object.user_id.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 + ]]> +
+
+
diff --git a/addons/sale/edi_sale_order.py b/addons/sale/edi_sale_order.py deleted file mode 100644 index 7cec8f39374..00000000000 --- a/addons/sale/edi_sale_order.py +++ /dev/null @@ -1,144 +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 - -class sale_order(osv.osv, ir_edi.edi): - _inherit = 'sale.order' - - def edi_export(self, cr, uid, records, edi_struct=None, context=None): - """Exports a Sale order""" - edi_struct = { - 'company_id': True, # -> to be changed into partner - 'name': True, - 'client_order_ref': True, - 'origin': True, - 'date_order': True, - 'partner_id': True, - 'partner_order_id': True, #only one address needed - #SO: 'partner_order_id' - #PO: 'partner_address_id' - 'pricelist_id': True, - 'note': True, - #SO: 'note' - #PO: 'notes' - 'amount_total': True, - 'amount_tax': True, - 'amount_untaxed': True, - 'order_line': { - 'sequence': True, - #SO: yes - #PO: No - 'name': True, - 'delay': True, - #SO: 'delay' : 'date_order' - 'date_planned' - #PO: 'date_planned': 'date_order' + 'delay' - - 'product_id': True, - 'product_uom': True, - 'price_unit': True, - 'product_uom_qty': True, - #SO: 'product_uom_qty' - #PO: 'product_qty' - 'price_subtotal': True, - 'discount': True, - #SO: yes - #PO: No - 'notes': True, - } - } - res_company = 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(sale_order,self).edi_export(cr, uid, [order], edi_struct, context)[0] - currency = order.company_id.currency_id - edi_address = res_company.edi_export_address(cr, uid, [order.company_id], context=context)[0] - edi_doc.update(company_address=edi_address, - currency_id=(currency and self.edi_m2o(cr, uid, currency, context=context) or False)) - #TODO: company_logo - 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 = {'supplier': 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_order_id'] = self.edi_m2o(cr, uid, partner_address, context=context) - edi_document['partner_invoice_id'] = edi_document['partner_order_id'] - edi_document['partner_shipping_id'] = edi_document['partner_order_id'] - del edi_document['company_id'] - return partner_id - - def edi_get_pricelist(self, cr, uid, partner_id, context=None): - # 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 - if not pricelist: - pricelist = self.pool.get('ir.model.data').get_object(cr, uid, 'product', 'list0', context=context) - return self.edi_m2o(cr, uid, pricelist, 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) - - date_order = edi_document.get('date_order', False) - edi_document['client_order_ref'] = edi_document['name'] - edi_document['note'] = edi_document.get('notes', False) - edi_document['pricelist_id'] = self.edi_get_pricelist(cr, uid, partner_id, context=context) - order_lines = edi_document['order_line'] - for order_line in order_lines: - order_line['product_uom_qty'] = order_line['product_qty'] - date_planned = order_line['date_planned'] - delay = 0 - if date_order and date_planned: - delay = (datetime.strptime(date_planned, "%Y-%m-%d") - datetime.strptime(date_order, "%Y-%m-%d")).days - order_line['delay'] = delay - return super(sale_order,self).edi_import(cr, uid, edi_document, context=context) - -sale_order() - -class sale_order_line(osv.osv, ir_edi.edi): - _inherit='sale.order.line' - -sale_order_line() -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale/edi_sale_order_data.xml b/addons/sale/edi_sale_order_data.xml deleted file mode 100644 index 33b65b4c031..00000000000 --- a/addons/sale/edi_sale_order_data.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - context.update({'edi_web_sale_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, 'sale', 'email_template_edi_sale')[1], - object.id, - context=context) - - code - ir.actions.server - - True - EDI Document - Sale Order - - - - - - - - - - - - Mail Template of Sale Order For EDI Document - ${object.user_id.user_email or ''} - ${object.user_id.user_email or ''} - ${object.company_id.name} - Sale Order ${object.name} - ${object.partner_invoice_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_invoice_id.name and ' ' or ''},</p> -<p> You can click on the following link to preview sale order : <br/> - <a href="${object._context.get('edi_web_sale_url_view')}">${object._context.get('edi_web_sale_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.user_id.user_email or ''}?subject=Order%20${object.name}">${object.user_id.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.user_id.user_email or ''}?subject=Order%20${object.name}">${object.user_id.name}</a></div> <div> </div> </div> </div> <p> </p> - - -Hello ${object.partner_invoice_id.name and ' ' or ''}, - -You can click on the following link to preview sale order: - - ${object._context.get('edi_web_sale_url_view') or 'n/a'} - -Order Number: *${object.name}* -Amount: *${object.amount_total}* -Order date: ${object.date_order or 'n/a'} -Your contact: ${object.user_id.name} ${object.user_id.user_email and '<%s>'%(object.user_id.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.user_id.name} ${object.user_id.user_email and '<%s>'%(object.user_id.user_email) or ''} - - - - diff --git a/addons/sale/test/edi_sale_order.yml b/addons/sale/test/edi_sale_order.yml index cf8da5f1efb..d7a8f4806f3 100644 --- a/addons/sale/test/edi_sale_order.yml +++ b/addons/sale/test/edi_sale_order.yml @@ -1,127 +1,117 @@ - - I create a partner which is a my customer + I create a draft Sale Order - - !record {model: res.partner, id: res_partner_test22}: - name: Junjun wala - supplier: False - customer: True - opt_out: True -- - I create one Sale Order -- - !record {model: sale.order, id: sale_order_test}: - partner_id: res_partner_test22 - partner_invoice_id: base.res_partner_address_3 - partner_order_id: base.res_partner_address_3 - partner_shipping_id: base.res_partner_address_3 + !record {model: sale.order, id: sale_order_edi_1}: + partner_id: base.res_partner_agrolait + partner_invoice_id: base.res_partner_address_8invoice + partner_order_id: base.res_partner_address_8invoice + partner_shipping_id: base.res_partner_address_8invoice pricelist_id: 1 order_line: - product_id: product.product_product_pc1 product_uom_qty: 1.0 product_uom: 1 price_unit: 150.0 - name: 'basic pc' + name: 'Basic pc' order_line: - product_id: product.product_product_pc3 product_uom_qty: 10.0 product_uom: 1 price_unit: 200.0 - name: 'medium pc' + name: 'Medium pc' - - I Open the sale order + I confirm the sale order - - !python {model: sale.order}: | - - orders = self.browse(cr, uid, ref("sale_order_test")) - import netsvc - wf_service = netsvc.LocalService("workflow") - wf_service.trg_validate(uid, 'sale.order',orders.id,'order_confirm', cr) - + !workflow {model: sale.order, ref: sale_order_edi_1, action: order_confirm} - - I Tesing of EDI functionality. First I export Sale Order from my company than import that Order into customer company + Then I export the sale order via EDI - - !python {model: ir.edi.document}: | - sale_order_pool = self.pool.get('sale.order') - orders = sale_order_pool.browse(cr, uid, ref("sale_order_test")) - - tokens = self.export_edi(cr, uid, [orders]) - assert tokens, 'Token is not generated' - + !python {model: edi.document}: | + sale_order = self.pool.get('sale.order') + so = sale_order.browse(cr, uid, ref("sale_order_edi_1")) + token = self.export_edi(cr, uid, [so]) + assert token, 'Invalid EDI Token' - - I import Sale order from EDI Document of purchase order + Then I import a sample EDI document of a purchase order - - !python {model: ir.edi.document}: | + !python {model: edi.document}: | sale_order_pool = self.pool.get('sale.order') edi_document = { - "order_line": [{ - "name": "basic pc", - "product_uom": ["5af1272e-dd26-11e0-b65e-701a04e25543:product.product_uom_unit", "PCE"], - "date_planned": "2011-09-30", - "price_unit": 150.0, - "__last_update": False, - "__id": "5af1272e-dd26-11e0-b65e-701a04e25543:purchase.purchase_order_line-AlhsVDZGoKvJ", - "product_qty": 1.0, - "product_id": ["5af1272e-dd26-11e0-b65e-701a04e25543:product.product_product_pc1", "[PC1] Basic PC"] - }, - { - "name": "medium pc", - "product_uom": ["5af1272e-dd26-11e0-b65e-701a04e25543:product.product_uom_unit", "PCE"], - "date_planned": "2011-09-15", - "price_unit": 100.0, - "__last_update": False, - "__id": "5af1272e-dd26-11e0-b65e-701a04e25543:purchase.purchase_order_line-AlhsVDZGoKvJ", - "product_qty": 2.0, - "product_id": ["5af1272e-dd26-11e0-b65e-701a04e25543:product.product_product_pc3", "[PC3] Medium PC"] - }], - "partner_address_id": ["5af1272e-dd26-11e0-b65e-701a04e25543:base.res_partner_address_11", "Sebastien LANGE, France, Alencon, 1 place de l'\u00c9glise"], - "__id": "5af1272e-dd26-11e0-b65e-701a04e25543:purchase.purchase_order_test", - "date_order": "2011-09-12", - "partner_id": ["5af1272e-dd26-11e0-b65e-701a04e25543:purchase.res_partner_test20", "jones white"], - "__attachments": [], - "__module": "sale", - "amount_total": 350.0, + "__id": "purchase:5af1272e-dd26-11e0-b65e-701a04e25543.purchase_order_test", + "__module": "purchase", + "__model": "purchase.order", + "__import_module": "sale", + "__import_model": "sale.order", + "__version": [6,1,0], + "name": "PO00011", + "date_order": "2011-09-12", + "company_id": ["base:5af1272e-dd26-11e0-b65e-701a04e25543.main_company", "Client S.A."], "company_address": { + "__id": "base:5af1272e-dd26-11e0-b65e-701a04e25543.some_address", + "__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": ["5af1272e-dd26-11e0-b65e-701a04e25543:base.be", "Belgium"], - "__id": "5af1272e-dd26-11e0-b65e-701a04e25543:base.main_address", + "country_id": ["base:5af1272e-dd26-11e0-b65e-701a04e25543.be", "Belgium"], }, - "amount_untaxed": 350.0, - "name": "PO00011", - "__model": "sale.order", - "__last_update": False, - "company_id": ["5af1272e-dd26-11e0-b65e-701a04e25543:base.main_company", "Client S.A."], - "__version": [6, 1], - "pricelist_id": ["5af1272e-dd26-11e0-b65e-701a04e25543:product.list0", "Public Pricelist (EUR)"] + "partner_id": ["purchase:5af1272e-dd26-11e0-b65e-701a04e25543.res_partner_test20", "jones white"], + "partner_address": { + "__id": "base:5af1272e-dd26-11e0-b65e-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", + "country_id": ["base:5af1272e-dd26-11e0-b65e-701a04e25543.be", "Belgium"], + }, + "order_line": [{ + "__id": "purchase:5af1272e-dd26-11e0-b65e-701a04e25543.purchase_order_line-AlhsVDZGoKvJ", + "__module": "purchase", + "__model": "purchase.order.line", + "__import_module": "sale", + "__import_model": "sale.order.line", + "name": "Basic PC", + "date_planned": "2011-09-30", + "price_unit": 150.0, + "product_id": ["product:5af1272e-dd26-11e0-b65e-701a04e25543.product_product_pc1", "[PC1] Basic PC"], + "product_qty": 1.0, + "product_uom": ["product:5af1272e-dd26-11e0-b65e-701a04e25543.product_uom_unit", "PCE"], + }, + { + "__id": "purchase:5af1272e-dd26-11e0-b65e-701a04e25543.purchase_order_line-Alsads33e", + "__module": "purchase", + "__model": "purchase.order.line", + "__import_module": "sale", + "__import_model": "sale.order.line", + "name": "Medium PC", + "date_planned": "2011-09-15", + "price_unit": 100.0, + "product_id": ["product:5af1272e-dd26-11e0-b65e-701a04e25543.product_product_pc3", "[PC3] Medium PC"], + "product_qty": 2.0, + "product_uom": ["product:5af1272e-dd26-11e0-b65e-701a04e25543.product_uom_unit", "PCE"], + }], } new_sale_order_id = sale_order_pool.edi_import(cr, uid, edi_document, context=context) - assert new_sale_order_id, 'Sale order is not imported' + assert new_sale_order_id, 'Sale order import failed' + order_new = sale_order_pool.browse(cr, uid, new_sale_order_id) -- - I Checking the sale order become purchase order or not after import -- - !python {model: sale.order}: | - - ids = self.search(cr, uid, [('partner_id','=','Client S.A.'), ('client_order_ref', '=', 'PO00011')]) - 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 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, "sale lines are not same" + assert order_new.pricelist_id.name == 'Public Pricelist' , "Public Price list was not automatically assigned" + assert order_new.amount_total == 350, "Amount total is wrong" + assert order_new.amount_untaxed == 350, "Untaxed amount is wrong" + assert len(order_new.order_line) == 2, "Sale order lines mismatch" for sale_line in order_new.order_line: - if sale_line.name == 'basic pc': - assert sale_line.delay == 18 , "delay is not same" + if sale_line.name == 'Basic PC': + assert sale_line.delay == 18 , "incorrect delay: got %s, expected 18"%(sale_line.delay,) assert sale_line.product_uom.name == "PCE" , "uom is not same" - assert sale_line.price_unit == 150 , "price unit is not same" + assert sale_line.price_unit == 150 , "unit price is not same, got %s, expected 150"%(sale_line.price_unit,) assert sale_line.product_uom_qty == 1 , "product qty is not same" - elif sale_line.name == 'medium pc': - assert sale_line.delay == 3 , "delay is not same" + elif sale_line.name == 'Medium PC': + assert sale_line.delay == 3 , "incorrect delay: got %s, expected 3"%(sale_line.delay,) assert sale_line.product_uom.name == "PCE" , "uom is not same" - assert sale_line.price_unit == 100 , "price unit is not same" + assert sale_line.price_unit == 100 , "unit price is not same, got %s, expected 100"%(sale_line.price_unit,) assert sale_line.product_uom_qty == 2 , "product qty is not same" else: - assert 'wrong product imported in sale lines' + raise AssertionError('unknown order line: %s' % sale_line) \ No newline at end of file