From 29532c645821c5f1d66d51a28d75102b1207a932 Mon Sep 17 00:00:00 2001 From: "Amit Parmar (OpenERP)" Date: Thu, 16 Jun 2011 11:37:31 +0530 Subject: [PATCH 001/265] [EDI] first revision of specific import bzr revid: aar@tinyerp.com-20110616060731-rmp0eftd3hjlm3ep --- addons/account/__init__.py | 2 +- addons/account/__openerp__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/account/__init__.py b/addons/account/__init__.py index 24129306e13..799f6fe08a5 100644 --- a/addons/account/__init__.py +++ b/addons/account/__init__.py @@ -34,5 +34,5 @@ import product import sequence import company import res_currency - +import edi_invoice # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/__openerp__.py b/addons/account/__openerp__.py index e4059896783..039a6800a98 100644 --- a/addons/account/__openerp__.py +++ b/addons/account/__openerp__.py @@ -143,7 +143,7 @@ module named account_voucher. 'test/account_bank_statement.yml', 'test/account_cash_statement.yml', 'test/account_report.yml', - + 'test/test_edi_invoice.yml', ], 'installable': True, From e26ae4e800d05e3e3045972cb234847c4e11ef82 Mon Sep 17 00:00:00 2001 From: "Amit Parmar (OpenERP)" Date: Tue, 21 Jun 2011 18:59:25 +0530 Subject: [PATCH 002/265] [EDI] refactor code of specific import bzr revid: aar@tinyerp.com-20110621132925-95jijdbuml3st9bo --- addons/account/__openerp__.py | 6 ++++-- addons/account/wizard/__init__.py | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/addons/account/__openerp__.py b/addons/account/__openerp__.py index 039a6800a98..07174e4971f 100644 --- a/addons/account/__openerp__.py +++ b/addons/account/__openerp__.py @@ -121,7 +121,9 @@ module named account_voucher. 'company_view.xml', 'board_account_view.xml', "wizard/account_report_profit_loss_view.xml", - "wizard/account_report_balance_sheet_view.xml" + "wizard/account_report_balance_sheet_view.xml", + 'test/test_edi_invoice.yml', + #'wizard/edi_import_view.xml', ], 'demo_xml': [ 'account_demo.xml', @@ -143,7 +145,7 @@ module named account_voucher. 'test/account_bank_statement.yml', 'test/account_cash_statement.yml', 'test/account_report.yml', - 'test/test_edi_invoice.yml', + ], 'installable': True, diff --git a/addons/account/wizard/__init__.py b/addons/account/wizard/__init__.py index caed6fc3977..0d888f8e712 100644 --- a/addons/account/wizard/__init__.py +++ b/addons/account/wizard/__init__.py @@ -65,6 +65,7 @@ import account_change_currency import account_report_balance_sheet import account_report_profit_loss + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: From df0bbd0650db82a82711e601128d9b2a4b6ebfe1 Mon Sep 17 00:00:00 2001 From: "Amit Parmar (OpenERP)" Date: Tue, 21 Jun 2011 19:00:26 +0530 Subject: [PATCH 003/265] [EDI] refactor code of specific import bzr revid: aar@tinyerp.com-20110621133026-ll3afhk9qhwx52is --- addons/account/edi_invoice.py | 287 +++++++++++++++++++++++ addons/account/test/test_edi_invoice.yml | 13 + 2 files changed, 300 insertions(+) create mode 100644 addons/account/edi_invoice.py create mode 100644 addons/account/test/test_edi_invoice.yml diff --git a/addons/account/edi_invoice.py b/addons/account/edi_invoice.py new file mode 100644 index 00000000000..956b0d9aa15 --- /dev/null +++ b/addons/account/edi_invoice.py @@ -0,0 +1,287 @@ + +from osv import fields, osv,orm +from base.ir import ir_edi + +class account_invoice(osv.osv,ir_edi.edi): + + _inherit = 'account.invoice' + #_name = 'edi.invoice' + + def edi_export(self, cr, uid, ids, edi_struct=None, context=None): + """Exports a supplier or customer invoice""" + rec_id = [ids[0].id] + + edi_struct = { + 'name': True, + 'origin': True, + 'company_id': True, # -> to be changed into partner + 'type': True, # -> reversed at import + 'internal_number': True, # -> reference at import + 'comment': True, + 'date_invoice': True, + 'date_due': True, + 'partner_id': True, + 'address_invoice_id': True, #only one address needed + 'payment_term': True, + 'currency_id': True, + 'invoice_line': { + 'name': True, + 'origin': True, + 'uos_id': True, + 'product_id': True, + 'price_unit': True, + 'quantity': True, + 'discount': True, + 'note': True, + }, + 'tax_line': { + 'name': True, + 'base': True, + 'amount': True, + 'manual': True, + 'sequence': True, + 'base_amount': True, + 'tax_amount': True, + }, + } + # Get EDI doc based on this struct. The result will also contain + # all metadata fields and attachments. + + edi_doc = super(account_invoice,self).edi_export(cr, uid, ids, edi_struct, context) + + + for i, invoice in enumerate(self.browse(cr, uid, rec_id, context=context)): + # add specific data for import + inv_comp = invoice.company_id + + + comp_partner = inv_comp.partner_id + + comp_partner_addr = comp_partner.address + + for address in comp_partner_addr: + + + edi_doc[i].update({ + # Add company info and address + 'company_address': { + 'street': address.street, + 'street2': address.street2, + 'zip': address.zip, + 'city': address.city, + 'state_id': self.edi_m2o(cr, uid, address.state_id), + 'country_id': self.edi_m2o(cr, uid, address.country_id), + 'email': address.email, + 'phone': address.phone + }, + # Function fields are not included in normal export + #'company_logo': inv_comp.logo,#TODO + #'paid': inv_comp.paid, #TODO + }) + + return edi_doc + def edi_import(self, cr, uid, edi_document, context=None): + + """ During import, invoices will import the company that is provided in the invoice as + a new partner (e.g. supplier company for a customer invoice will be come a supplier + record for the new invoice. + Summary of tasks that need to be done: + - import company as a new partner, if type==in then supplier=1, else customer=1 + - partner_id field is modified to point to the new partner + - company_address data used to add address to new partner + - change type: out_invoice'<->'in_invoice','out_refund'<->'in_refund' + - 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' + 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 + product's default, i.e. from the default category, as it will not + 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. + """ + # generic implementation! + + partner = self.pool.get('res.partner') + partner_add = self.pool.get('res.partner.address') + model_data = self.pool.get('ir.model.data') + product_obj = self.pool.get('product.product') + product_categ = self.pool.get('product.category') + acc_invoice = self.pool.get('account.invoice') + company = self.pool.get('res.company') + tax_id = [] + account_id = [] + partner_id = None + company_id = None + if context is None: + context = {} + for field in edi_document.keys(): + + if field == 'type': + if len(edi_document['invoice_line']): + name = edi_document['invoice_line'][0]['product_id'][1] + else: + name = None + re_ids = product_obj.search(cr,uid,[('name','=',name)]) + if edi_document['type'] == 'out_invoice' or edi_document['type'] == 'out_refund': + if re_ids: + if product_obj.browse(cr,uid,re_ids)[0].property_account_expense: + account_id = product_obj.browse(cr,uid,re_ids)[0].property_account_expense + + else: + account_id = product_categ.browse(cr,uid,re_ids)[0].property_account_expense_categ + if product_obj.browse(cr,uid,re_ids)[0].taxes_id: + tax_id = product_obj.browse(cr, uid,re_ids)[0].taxes_id + if edi_document['type'] == 'out_refund': + edi_document['type'] = 'in_refund' + else: + edi_document['type'] = 'in_invoice' + + + elif edi_document['type'] == 'in_invoice' or edi_document['type'] == 'in_refund': + if re_ids: + if product_obj.browse(cr,uid,re_ids)[0].property_account_income: + account_id = product_obj.browse(cr,uid,re_ids)[0].property_account_income + else: + account_id = product_categ.browse(cr,uid,re_ids)[0].property_account_income_categ + if product_obj.browse(cr,uid,re_ids)[0].taxes_id: + tax_id = product_obj.browse(cr, uid,re_ids)[0].taxes_id + if edi_document['type'] == 'in_refund': + edi_document['type'] = 'out_refund' + else: + edi_document['type'] = 'out_invoice' + + if account_id: + name_ids = model_data.search(cr, uid, [('model','=',account_id._name),('res_id','=',account_id.id)]) + if name_ids: + xml_id = model_data.browse(cr, uid, name_ids)[0].name + db_uuid = ir_edi.safe_unique_id(account_id._name,account_id.id) + edi_document['invoice_line'][0]['account_id'] = [db_uuid+':'+xml_id,account_id.name] + + if tax_id: + name_ids = model_data.search(cr, uid, [('model','=',tax_id[0]._name),('res_id','=',tax_id[0].id)]) + + if name_ids: + xml_id = model_data.browse(cr, uid, name_ids)[0].name + db_uuid = ir_edi.safe_unique_id(tax_id[0]._name,tax_id[0].id) + edi_document['tax_line'][0]['account_id'] = [db_uuid+':'+xml_id,tax_id[0].name] + + else: + if len(edi_document['tax_line']): + edi_document['tax_line'][0]['manual'] = True + + res = {} + part = {} + comp = {} + partner_id = partner.search(cr,uid,[('name','=',edi_document['company_id'][1])]) + + if len(partner_id): + + browse_partner = partner.browse(cr,uid,partner_id[0]) + u_id = model_data.search(cr, uid, [('res_id','=',browse_partner.id),('model','=',browse_partner._name)]) + if len(u_id): + company_id = browse_partner.company_id + xml_obj = model_data.browse(cr,uid,u_id[0]) + uuid = ir_edi.safe_unique_id(browse_partner._name,browse_partner.id) + db_uuid = '%s:%s' % (uuid,xml_obj.name) + part.update({'partner_id':[db_uuid,browse_partner.name]}) + + else: + company_id = company.create(cr, uid, {'name':edi_document['company_id'][1]}) + add_id = partner_add.create(cr,uid,edi_document['company_address']) + res.update({'name': edi_document['company_id'][1],'supplier': True, 'partner_id': edi_document['partner_id'],'address':add_id}) + partner_id = partner.create(cr,uid,res) + + browse_partner = partner.browse(cr,uid,partner_id[0]) + + u_id = model_data.search(cr, uid, [('res_id','=',browse_partner.id),('model','=',browse_partner._name)]) + + + if len(u_id): + + xml_obj = model_data.browse(cr,uid,u_id[0]) + uuid = ir_edi.safe_unique_id(browse_partner._name,browse_partner.id) + db_uuid = '%s:%s' % (uuid,xml_obj.name) + part.update({'partner_id':[db_uuid,browse_partner.name]}) + + comp_id = partner.search(cr,uid,[('name','=',edi_document['partner_id'][1])]) + + if len(comp_id): + + browse_partner = partner.browse(cr,uid,comp_id[0]) + + browse_company = company.browse(cr,uid,browse_partner.company_id.id) + + u_id = u_id = model_data.search(cr, uid, [('res_id','=',browse_company.id),('model','=',browse_company._name)]) + if len(u_id): + + xml_obj = model_data.browse(cr,uid,u_id[0]) + uuid = ir_edi.safe_unique_id(browse_company._name,browse_company.id) + db_uuid = '%s:%s' % (uuid,xml_obj.name) + comp.update({'company_id':[db_uuid,browse_company.name]}) + + del edi_document['partner_id'] + del edi_document['company_id'] + edi_document.update(part) + edi_document.update(comp) + if len(partner_id): + + + + p = self.pool.get('res.partner').browse(cr, uid, partner_id[0]) + if company_id: + if p.property_account_receivable.company_id.id != company_id.id and p.property_account_payable.company_id.id != company_id.id: + property_obj = self.pool.get('ir.property') + + rec_pro_id = property_obj.search(cr,uid,[('name','=','property_account_receivable'),('res_id','=','res.partner,'+str(partner_id)+''),('company_id','=',company_id.id)]) + pay_pro_id = property_obj.search(cr,uid,[('name','=','property_account_payable'),('res_id','=','res.partner,'+str(partner_id)+''),('company_id','=',company_id)]) + if not rec_pro_id: + rec_pro_id = property_obj.search(cr,uid,[('name','=','property_account_receivable'),('company_id','=',company_id.id)]) + if not pay_pro_id: + pay_pro_id = property_obj.search(cr,uid,[('name','=','property_account_payable'),('company_id','=',company_id.id)]) + rec_line_data = property_obj.read(cr,uid,rec_pro_id,['name','value_reference','res_id']) + pay_line_data = property_obj.read(cr,uid,pay_pro_id,['name','value_reference','res_id']) + rec_res_id = rec_line_data and rec_line_data[0].get('value_reference',False) and int(rec_line_data[0]['value_reference'].split(',')[1]) or False + pay_res_id = pay_line_data and pay_line_data[0].get('value_reference',False) and int(pay_line_data[0]['value_reference'].split(',')[1]) or False + if not rec_res_id and not pay_res_id: + raise osv.except_osv(_('Configuration Error !'), + _('Can not find account chart for this company, Please Create account.')) + account_obj = self.pool.get('account.account') + rec_obj_acc = account_obj.browse(cr, uid, [rec_res_id]) + pay_obj_acc = account_obj.browse(cr, uid, [pay_res_id]) + p.property_account_receivable = rec_obj_acc[0] + p.property_account_payable = pay_obj_acc[0] + + if edi_document['type'] in ('out_invoice', 'out_refund'): + acc_obj = p.property_account_receivable + else: + acc_obj = p.property_account_payable + res_id = model_data.search(cr,uid,[('model','=',acc_obj._name),('res_id','=',acc_obj.id)]) + if len(res_id): + xml_obj = model_data.browse(cr, uid, res_id[0]) + uuid = ir_edi.safe_unique_id(acc_obj._name,acc_obj.id) + db_uuid = '%s:%s' % (uuid,xml_obj.name) + edi_document.update({'account_id':[db_uuid,acc_obj.name]}) + print "account_id",edi_document['account_id'] + edi_document.update({'reference':edi_document['internal_number'],'reference_type' : 'none'}) + edi_document['internal_number'] = False + context['type'] = edi_document['type'] + comp + del edi_document['company_address'] + + + return super(account_invoice,self).edi_import(cr, uid, edi_document) + +account_invoice() + +class account_invoice_line(osv.osv, ir_edi.edi): + _inherit='account.invoice.line' + +account_invoice_line() +class account_invoice_tax(osv.osv, ir_edi.edi): + _inherit = "account.invoice.tax" + +account_invoice_tax() diff --git a/addons/account/test/test_edi_invoice.yml b/addons/account/test/test_edi_invoice.yml new file mode 100644 index 00000000000..af23dd3e57a --- /dev/null +++ b/addons/account/test/test_edi_invoice.yml @@ -0,0 +1,13 @@ +- + Tesing of Export functionality +- + !python {model: ir.edi.document}: | + invoice_obj = self.pool.get('account.invoice') + invoice_ids = invoice_obj.search(cr, uid, []) + print "invoices>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>",invoice_ids + if invoice_ids: + invoices = invoice_obj.browse(cr, uid, invoice_ids) + tokens = self.export_edi(cr, uid, invoices) + for token in tokens: + document = self.get_document(cr, uid, token, context=context) + a = self.import_edi(cr, uid, edi_document = document) From 7f241bd2e7db48a791a65bc0ce83fd2d7cbf34ca Mon Sep 17 00:00:00 2001 From: "Amit Parmar (OpenERP)" Date: Wed, 22 Jun 2011 14:44:25 +0530 Subject: [PATCH 004/265] [EDI] refactor code of specific edi import and export bzr revid: aar@tinyerp.com-20110622091425-b1ldh2oduyglaoa1 --- addons/account/__openerp__.py | 13 ++++++------ addons/account/edi_invoice.py | 39 ++++------------------------------- 2 files changed, 10 insertions(+), 42 deletions(-) diff --git a/addons/account/__openerp__.py b/addons/account/__openerp__.py index 07174e4971f..b2996976c50 100644 --- a/addons/account/__openerp__.py +++ b/addons/account/__openerp__.py @@ -122,14 +122,13 @@ module named account_voucher. 'board_account_view.xml', "wizard/account_report_profit_loss_view.xml", "wizard/account_report_balance_sheet_view.xml", - 'test/test_edi_invoice.yml', - #'wizard/edi_import_view.xml', + ], 'demo_xml': [ - 'account_demo.xml', - 'project/project_demo.xml', - 'project/analytic_account_demo.xml', - 'demo/account_minimal.xml', + #'account_demo.xml', + #'project/project_demo.xml', + #'project/analytic_account_demo.xml', + #'demo/account_minimal.xml', # 'account_unit_test.xml', ], 'test': [ @@ -145,7 +144,7 @@ module named account_voucher. 'test/account_bank_statement.yml', 'test/account_cash_statement.yml', 'test/account_report.yml', - + 'test/test_edi_invoice.yml', ], 'installable': True, diff --git a/addons/account/edi_invoice.py b/addons/account/edi_invoice.py index 956b0d9aa15..56d0e52df95 100644 --- a/addons/account/edi_invoice.py +++ b/addons/account/edi_invoice.py @@ -47,21 +47,13 @@ class account_invoice(osv.osv,ir_edi.edi): # Get EDI doc based on this struct. The result will also contain # all metadata fields and attachments. - edi_doc = super(account_invoice,self).edi_export(cr, uid, ids, edi_struct, context) - - + edi_doc = super(account_invoice,self).edi_export(cr, uid, ids, edi_struct, context) for i, invoice in enumerate(self.browse(cr, uid, rec_id, context=context)): # add specific data for import inv_comp = invoice.company_id - - comp_partner = inv_comp.partner_id - comp_partner_addr = comp_partner.address - for address in comp_partner_addr: - - edi_doc[i].update({ # Add company info and address 'company_address': { @@ -119,7 +111,6 @@ class account_invoice(osv.osv,ir_edi.edi): if context is None: context = {} for field in edi_document.keys(): - if field == 'type': if len(edi_document['invoice_line']): name = edi_document['invoice_line'][0]['product_id'][1] @@ -130,7 +121,6 @@ class account_invoice(osv.osv,ir_edi.edi): if re_ids: if product_obj.browse(cr,uid,re_ids)[0].property_account_expense: account_id = product_obj.browse(cr,uid,re_ids)[0].property_account_expense - else: account_id = product_categ.browse(cr,uid,re_ids)[0].property_account_expense_categ if product_obj.browse(cr,uid,re_ids)[0].taxes_id: @@ -138,9 +128,7 @@ class account_invoice(osv.osv,ir_edi.edi): if edi_document['type'] == 'out_refund': edi_document['type'] = 'in_refund' else: - edi_document['type'] = 'in_invoice' - - + edi_document['type'] = 'in_invoice' elif edi_document['type'] == 'in_invoice' or edi_document['type'] == 'in_refund': if re_ids: if product_obj.browse(cr,uid,re_ids)[0].property_account_income: @@ -163,12 +151,10 @@ class account_invoice(osv.osv,ir_edi.edi): if tax_id: name_ids = model_data.search(cr, uid, [('model','=',tax_id[0]._name),('res_id','=',tax_id[0].id)]) - if name_ids: xml_id = model_data.browse(cr, uid, name_ids)[0].name db_uuid = ir_edi.safe_unique_id(tax_id[0]._name,tax_id[0].id) edi_document['tax_line'][0]['account_id'] = [db_uuid+':'+xml_id,tax_id[0].name] - else: if len(edi_document['tax_line']): edi_document['tax_line'][0]['manual'] = True @@ -177,9 +163,7 @@ class account_invoice(osv.osv,ir_edi.edi): part = {} comp = {} partner_id = partner.search(cr,uid,[('name','=',edi_document['company_id'][1])]) - if len(partner_id): - browse_partner = partner.browse(cr,uid,partner_id[0]) u_id = model_data.search(cr, uid, [('res_id','=',browse_partner.id),('model','=',browse_partner._name)]) if len(u_id): @@ -188,20 +172,14 @@ class account_invoice(osv.osv,ir_edi.edi): uuid = ir_edi.safe_unique_id(browse_partner._name,browse_partner.id) db_uuid = '%s:%s' % (uuid,xml_obj.name) part.update({'partner_id':[db_uuid,browse_partner.name]}) - else: company_id = company.create(cr, uid, {'name':edi_document['company_id'][1]}) add_id = partner_add.create(cr,uid,edi_document['company_address']) res.update({'name': edi_document['company_id'][1],'supplier': True, 'partner_id': edi_document['partner_id'],'address':add_id}) partner_id = partner.create(cr,uid,res) - browse_partner = partner.browse(cr,uid,partner_id[0]) - u_id = model_data.search(cr, uid, [('res_id','=',browse_partner.id),('model','=',browse_partner._name)]) - - if len(u_id): - xml_obj = model_data.browse(cr,uid,u_id[0]) uuid = ir_edi.safe_unique_id(browse_partner._name,browse_partner.id) db_uuid = '%s:%s' % (uuid,xml_obj.name) @@ -210,14 +188,10 @@ class account_invoice(osv.osv,ir_edi.edi): comp_id = partner.search(cr,uid,[('name','=',edi_document['partner_id'][1])]) if len(comp_id): - browse_partner = partner.browse(cr,uid,comp_id[0]) - browse_company = company.browse(cr,uid,browse_partner.company_id.id) - u_id = u_id = model_data.search(cr, uid, [('res_id','=',browse_company.id),('model','=',browse_company._name)]) if len(u_id): - xml_obj = model_data.browse(cr,uid,u_id[0]) uuid = ir_edi.safe_unique_id(browse_company._name,browse_company.id) db_uuid = '%s:%s' % (uuid,xml_obj.name) @@ -228,9 +202,6 @@ class account_invoice(osv.osv,ir_edi.edi): edi_document.update(part) edi_document.update(comp) if len(partner_id): - - - p = self.pool.get('res.partner').browse(cr, uid, partner_id[0]) if company_id: if p.property_account_receivable.company_id.id != company_id.id and p.property_account_payable.company_id.id != company_id.id: @@ -265,14 +236,12 @@ class account_invoice(osv.osv,ir_edi.edi): uuid = ir_edi.safe_unique_id(acc_obj._name,acc_obj.id) db_uuid = '%s:%s' % (uuid,xml_obj.name) edi_document.update({'account_id':[db_uuid,acc_obj.name]}) - print "account_id",edi_document['account_id'] + edi_document.update({'reference':edi_document['internal_number'],'reference_type' : 'none'}) edi_document['internal_number'] = False context['type'] = edi_document['type'] - comp + del edi_document['company_address'] - - return super(account_invoice,self).edi_import(cr, uid, edi_document) account_invoice() From 1d98e87dcca53ad9b89007d602734ec1b629821f Mon Sep 17 00:00:00 2001 From: "Amit Parmar (OpenERP)" Date: Wed, 22 Jun 2011 15:44:47 +0530 Subject: [PATCH 005/265] [EDI] revised code of specific import and export bzr revid: aar@tinyerp.com-20110622101447-qm824uxvcedyjgd4 --- addons/account/__openerp__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/account/__openerp__.py b/addons/account/__openerp__.py index b2996976c50..651c426dc80 100644 --- a/addons/account/__openerp__.py +++ b/addons/account/__openerp__.py @@ -125,10 +125,10 @@ module named account_voucher. ], 'demo_xml': [ - #'account_demo.xml', - #'project/project_demo.xml', - #'project/analytic_account_demo.xml', - #'demo/account_minimal.xml', + 'account_demo.xml', + 'project/project_demo.xml', + 'project/analytic_account_demo.xml', + 'demo/account_minimal.xml', # 'account_unit_test.xml', ], 'test': [ From 77b2a20d81980235353b5e33f7b8897bfbe355b9 Mon Sep 17 00:00:00 2001 From: "Amit Parmar (OpenERP)" Date: Thu, 23 Jun 2011 19:12:07 +0530 Subject: [PATCH 006/265] [EDI]:customer invoice testing through yml bzr revid: aar@tinyerp.com-20110623134207-soeh9tgaknfhp6hf --- addons/account/__openerp__.py | 3 +- addons/account/test/test_edi_invoice.yml | 64 ++++++++++++++++++++++-- 2 files changed, 62 insertions(+), 5 deletions(-) diff --git a/addons/account/__openerp__.py b/addons/account/__openerp__.py index 651c426dc80..1bb1b56a476 100644 --- a/addons/account/__openerp__.py +++ b/addons/account/__openerp__.py @@ -122,8 +122,7 @@ module named account_voucher. 'board_account_view.xml', "wizard/account_report_profit_loss_view.xml", "wizard/account_report_balance_sheet_view.xml", - - ], + ], 'demo_xml': [ 'account_demo.xml', 'project/project_demo.xml', diff --git a/addons/account/test/test_edi_invoice.yml b/addons/account/test/test_edi_invoice.yml index af23dd3e57a..9d624489c8c 100644 --- a/addons/account/test/test_edi_invoice.yml +++ b/addons/account/test/test_edi_invoice.yml @@ -1,13 +1,71 @@ - - Tesing of Export functionality + create Company +- + !record {model: res.company, id: res_company_test}: + name: Thomson pvt. ltd. + partner_id: 1 + rml_header: 1 + rml_header2: 1 + rml_header3: 1 + currency_id: 1 + +- + create customer +- + !record {model: res.partner, id: res_partner_test}: + name: Junjun wala + supplier: False + company_id: res_company_test + address: + - partner_id: res_partner_test + type: default + name: ivan + street: m g road + street2: line 28 + city: paris + +- + Creating a customer invoice record +- + !record {model: account.invoice, id: account_invoice_test}: + amount_tax: 0.0 + amount_total: 83.0 + amount_untaxed: 83.0 + currency_id: base.EUR + date_invoice: '2011-06-22' + invoice_line: + name: '[CPU1] Processor AMD Athlon XP 1800+' + partner_id: res_partner_test + price_subtotal: 75.0 + price_unit: 75.0 + product_id: product.product_product_cpu1 + quantity: 1.0 + journal_id: 'False' + name: Nothing + partner_id: res_partner_test + payment_term: account.account_payment_term + reference_type: none + +- + Tesing of Export functionality and Import Functionality - !python {model: ir.edi.document}: | + invoice_obj = self.pool.get('account.invoice') - invoice_ids = invoice_obj.search(cr, uid, []) - print "invoices>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>",invoice_ids + invoice_ids = invoice_obj.search(cr, uid, [partner_id]) if invoice_ids: invoices = invoice_obj.browse(cr, uid, invoice_ids) tokens = self.export_edi(cr, uid, invoices) for token in tokens: document = self.get_document(cr, uid, token, context=context) a = self.import_edi(cr, uid, edi_document = document) + +- + Check after import of document customer become supplier or not +- + !python {model: account.invoice}: | + ids=self.search(cr, uid, [('partner_id','=',base.main_company),('company_id','=',res_company_test),('type','=','in_invoice')]) + if not ids: + raise AssertionError("Invoice is not imported") + + \ No newline at end of file From 66356f01af42f48df61064ae1fc5ff1f0453de92 Mon Sep 17 00:00:00 2001 From: "Amit Parmar (OpenERP)" Date: Fri, 24 Jun 2011 18:41:17 +0530 Subject: [PATCH 007/265] [EDI] Final Tesing Ymal bzr revid: aar@tinyerp.com-20110624131117-x517otc1yc1f2r97 --- addons/account/__openerp__.py | 1 + addons/account/edi_invoice.py | 60 ++++++++++++++++--- addons/account/test/test_edi_invoice.yml | 76 +++++++++++------------- 3 files changed, 86 insertions(+), 51 deletions(-) diff --git a/addons/account/__openerp__.py b/addons/account/__openerp__.py index 1bb1b56a476..44537ad638a 100644 --- a/addons/account/__openerp__.py +++ b/addons/account/__openerp__.py @@ -122,6 +122,7 @@ module named account_voucher. 'board_account_view.xml', "wizard/account_report_profit_loss_view.xml", "wizard/account_report_balance_sheet_view.xml", + ], 'demo_xml': [ 'account_demo.xml', diff --git a/addons/account/edi_invoice.py b/addons/account/edi_invoice.py index 56d0e52df95..189604e6306 100644 --- a/addons/account/edi_invoice.py +++ b/addons/account/edi_invoice.py @@ -1,6 +1,7 @@ -from osv import fields, osv,orm +from osv import fields, osv, orm from base.ir import ir_edi +from tools.translate import _ class account_invoice(osv.osv,ir_edi.edi): @@ -96,6 +97,7 @@ class account_invoice(osv.osv,ir_edi.edi): on the tax config of the DB where it is imported. """ # generic implementation! + "" partner = self.pool.get('res.partner') partner_add = self.pool.get('res.partner.address') @@ -104,6 +106,7 @@ class account_invoice(osv.osv,ir_edi.edi): product_categ = self.pool.get('product.category') acc_invoice = self.pool.get('account.invoice') company = self.pool.get('res.company') + country = self.pool.get('res.country') tax_id = [] account_id = [] partner_id = None @@ -168,16 +171,47 @@ class account_invoice(osv.osv,ir_edi.edi): u_id = model_data.search(cr, uid, [('res_id','=',browse_partner.id),('model','=',browse_partner._name)]) if len(u_id): company_id = browse_partner.company_id + xml_obj = model_data.browse(cr,uid,u_id[0]) uuid = ir_edi.safe_unique_id(browse_partner._name,browse_partner.id) db_uuid = '%s:%s' % (uuid,xml_obj.name) part.update({'partner_id':[db_uuid,browse_partner.name]}) + else: + + company_address = {} company_id = company.create(cr, uid, {'name':edi_document['company_id'][1]}) - add_id = partner_add.create(cr,uid,edi_document['company_address']) - res.update({'name': edi_document['company_id'][1],'supplier': True, 'partner_id': edi_document['partner_id'],'address':add_id}) - partner_id = partner.create(cr,uid,res) + + for key in edi_document['company_address'].keys(): + if type(edi_document['company_address'][key]).__name__ == 'list': + if edi_document['company_address'][key][1] is not None: + country_id = country.search(cr ,uid,[('name','=',edi_document['company_address'][key][1])]) + + if len(country_id): + company_address.update({key : country_id[0]}) + + else: + if isinstance(edi_document['company_address'][key][1],unicode): + country_name = str(edi_document['company_address'][key][1]) + country_code = country_name[:2].upper() + country_id = country.create(cr, uid, {'code': country_code,name: country_name}) + company_address.update({key : country_id[0]}) + else: + company_address.update({key : edi_document['company_address'][key][1]}) + else: + company_address.update({key:edi_document['company_address'][key]}) + + add_id = [] + partner_id = [] + + add_id = partner_add.create(cr,uid,company_address) + + res.update({'name': edi_document['company_id'][1],'supplier': True,'address': [unicode(add_id)], 'company_id': unicode(company_id),'country' : country_id}) + + partner_id.append(partner.create(cr,uid,{'name': edi_document['company_id'][1],'supplier': True,'address': unicode(add_id), 'company_id': unicode(company_id),'country' : country_id})) + browse_partner = partner.browse(cr,uid,partner_id[0]) + company_id = browse_partner.company_id u_id = model_data.search(cr, uid, [('res_id','=',browse_partner.id),('model','=',browse_partner._name)]) if len(u_id): xml_obj = model_data.browse(cr,uid,u_id[0]) @@ -200,15 +234,21 @@ class account_invoice(osv.osv,ir_edi.edi): del edi_document['partner_id'] del edi_document['company_id'] edi_document.update(part) - edi_document.update(comp) + edi_document.update(comp) + + if len(partner_id): p = self.pool.get('res.partner').browse(cr, uid, partner_id[0]) + + partner_id = int(partner_id[0]) + if company_id: if p.property_account_receivable.company_id.id != company_id.id and p.property_account_payable.company_id.id != company_id.id: property_obj = self.pool.get('ir.property') rec_pro_id = property_obj.search(cr,uid,[('name','=','property_account_receivable'),('res_id','=','res.partner,'+str(partner_id)+''),('company_id','=',company_id.id)]) - pay_pro_id = property_obj.search(cr,uid,[('name','=','property_account_payable'),('res_id','=','res.partner,'+str(partner_id)+''),('company_id','=',company_id)]) + pay_pro_id = property_obj.search(cr,uid,[('name','=','property_account_payable'),('res_id','=','res.partner,'+str(partner_id)+''),('company_id','=',company_id.id)]) + if not rec_pro_id: rec_pro_id = property_obj.search(cr,uid,[('name','=','property_account_receivable'),('company_id','=',company_id.id)]) if not pay_pro_id: @@ -218,8 +258,8 @@ class account_invoice(osv.osv,ir_edi.edi): rec_res_id = rec_line_data and rec_line_data[0].get('value_reference',False) and int(rec_line_data[0]['value_reference'].split(',')[1]) or False pay_res_id = pay_line_data and pay_line_data[0].get('value_reference',False) and int(pay_line_data[0]['value_reference'].split(',')[1]) or False if not rec_res_id and not pay_res_id: - raise osv.except_osv(_('Configuration Error !'), - _('Can not find account chart for this company, Please Create account.')) + raise osv.except_osv(_('Configuration Error !'), _('Can not find account chart for this company, Please Create account.')) + account_obj = self.pool.get('account.account') rec_obj_acc = account_obj.browse(cr, uid, [rec_res_id]) pay_obj_acc = account_obj.browse(cr, uid, [pay_res_id]) @@ -230,7 +270,9 @@ class account_invoice(osv.osv,ir_edi.edi): acc_obj = p.property_account_receivable else: acc_obj = p.property_account_payable + res_id = model_data.search(cr,uid,[('model','=',acc_obj._name),('res_id','=',acc_obj.id)]) + if len(res_id): xml_obj = model_data.browse(cr, uid, res_id[0]) uuid = ir_edi.safe_unique_id(acc_obj._name,acc_obj.id) @@ -240,7 +282,7 @@ class account_invoice(osv.osv,ir_edi.edi): edi_document.update({'reference':edi_document['internal_number'],'reference_type' : 'none'}) edi_document['internal_number'] = False context['type'] = edi_document['type'] - + del edi_document['company_address'] return super(account_invoice,self).edi_import(cr, uid, edi_document) diff --git a/addons/account/test/test_edi_invoice.yml b/addons/account/test/test_edi_invoice.yml index 9d624489c8c..ec0dead338c 100644 --- a/addons/account/test/test_edi_invoice.yml +++ b/addons/account/test/test_edi_invoice.yml @@ -1,7 +1,7 @@ - create Company - - !record {model: res.company, id: res_company_test}: + !record {model: res.company, id: res_company_test11}: name: Thomson pvt. ltd. partner_id: 1 rml_header: 1 @@ -10,62 +10,54 @@ currency_id: 1 - - create customer + create partner - - !record {model: res.partner, id: res_partner_test}: + !record {model: res.partner, id: res_partner_test20}: name: Junjun wala supplier: False - company_id: res_company_test - address: - - partner_id: res_partner_test - type: default - name: ivan - street: m g road - street2: line 28 - city: paris + company_id: res_company_test11 -- - Creating a customer invoice record -- - !record {model: account.invoice, id: account_invoice_test}: - amount_tax: 0.0 - amount_total: 83.0 - amount_untaxed: 83.0 +- + create customer invoice +- + !record {model: account.invoice, id: customer_invoice_test}: + journal_id: 1 + partner_id: res_partner_test20 currency_id: base.EUR + address_invoice_id: base.res_partner_address_11 + company_id: base.main_company + account_id: 1 date_invoice: '2011-06-22' - invoice_line: - name: '[CPU1] Processor AMD Athlon XP 1800+' - partner_id: res_partner_test - price_subtotal: 75.0 - price_unit: 75.0 - product_id: product.product_product_cpu1 - quantity: 1.0 - journal_id: 'False' name: Nothing - partner_id: res_partner_test - payment_term: account.account_payment_term - reference_type: none - + 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 + name: 'basic pc' + account_id: 1 + - Tesing of Export functionality and Import Functionality - !python {model: ir.edi.document}: | invoice_obj = self.pool.get('account.invoice') - invoice_ids = invoice_obj.search(cr, uid, [partner_id]) - if invoice_ids: - invoices = invoice_obj.browse(cr, uid, invoice_ids) - tokens = self.export_edi(cr, uid, invoices) - for token in tokens: - document = self.get_document(cr, uid, token, context=context) - a = self.import_edi(cr, uid, edi_document = document) - + #invoice_ids = invoice_obj.search(cr, uid, ['account.customer_invoice_test']) + #if invoice_ids: + invoices = invoice_obj.browse(cr, uid, [ref("customer_invoice_test")]) + tokens = self.export_edi(cr, uid, invoices) + for token in tokens: + document = self.get_document(cr, uid, token, context=context) + a = self.import_edi(cr, uid, edi_document = document) + - - Check after import of document customer become supplier or not + Check the customer invoice is exported or not - !python {model: account.invoice}: | - ids=self.search(cr, uid, [('partner_id','=',base.main_company),('company_id','=',res_company_test),('type','=','in_invoice')]) + ids=self.search(cr, uid, [('partner_id','=',ref("res_partner_test20")),('company_id','=',ref("res_company_test11")),('type','=','out_invoice')]) if not ids: raise AssertionError("Invoice is not imported") - - \ No newline at end of file + From b2f73c0010ae84da417906a28300120b3571eec6 Mon Sep 17 00:00:00 2001 From: "Harry (OpenERP)" Date: Mon, 27 Jun 2011 14:02:28 +0530 Subject: [PATCH 008/265] [REVIEW+IMP] account, EDI: clean export_edi method of account.invoice bzr revid: hmo@tinyerp.com-20110627083228-cmiuptih2y8kjlqd --- addons/account/__openerp__.py | 5 +- addons/account/edi_invoice.py | 78 ++++++++++++++---------- addons/account/test/test_edi_invoice.yml | 1 + 3 files changed, 49 insertions(+), 35 deletions(-) diff --git a/addons/account/__openerp__.py b/addons/account/__openerp__.py index 44537ad638a..5ec724ed462 100644 --- a/addons/account/__openerp__.py +++ b/addons/account/__openerp__.py @@ -143,10 +143,9 @@ module named account_voucher. 'test/account_fiscalyear_close.yml', 'test/account_bank_statement.yml', 'test/account_cash_statement.yml', - 'test/account_report.yml', 'test/test_edi_invoice.yml', - - ], + 'test/account_report.yml', + ], 'installable': True, 'active': False, 'certificate': '0080331923549', diff --git a/addons/account/edi_invoice.py b/addons/account/edi_invoice.py index 7020a8115ad..ba3675a15f4 100644 --- a/addons/account/edi_invoice.py +++ b/addons/account/edi_invoice.py @@ -23,13 +23,11 @@ from osv import fields, osv, orm from base.ir import ir_edi from tools.translate import _ -class account_invoice(osv.osv,ir_edi.edi): +class account_invoice(osv.osv, ir_edi.edi): _inherit = 'account.invoice' - def edi_export(self, cr, uid, ids, edi_struct=None, context=None): + def edi_export(self, cr, uid, records, edi_struct=None, context=None): """Exports a supplier or customer invoice""" - rec_id = [ids[0].id] - edi_struct = { 'name': True, 'origin': True, @@ -63,35 +61,51 @@ class account_invoice(osv.osv,ir_edi.edi): 'tax_amount': True, }, } - # Get EDI doc based on this struct. The result will also contain - # all metadata fields and attachments. - - edi_doc = super(account_invoice,self).edi_export(cr, uid, ids, edi_struct, context) - for i, invoice in enumerate(self.browse(cr, uid, rec_id, context=context)): - # add specific data for import - inv_comp = invoice.company_id - comp_partner = inv_comp.partner_id - comp_partner_addr = comp_partner.address - for address in comp_partner_addr: - edi_doc[i].update({ - # Add company info and address - 'company_address': { - 'street': address.street, - 'street2': address.street2, - 'zip': address.zip, - 'city': address.city, - 'state_id': self.edi_m2o(cr, uid, address.state_id), - 'country_id': self.edi_m2o(cr, uid, address.country_id), - 'email': address.email, - 'phone': address.phone - }, - # Function fields are not included in normal export + partner_pool = self.pool.get('res.partner') + partner_address_pool = self.pool.get('res.partner.address') + company_address_dict = { + 'street': True, + 'street2': True, + 'zip': True, + 'city': True, + 'state_id': True, + 'country_id': True, + 'email': True, + 'phone': True, + + } + 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] - #'company_logo': inv_comp.logo,#TODO - #'paid': inv_comp.paid, #TODO - }) - - return edi_doc + # Add company info and address + res = partner_pool.address_get(cr, uid, [invoice.company_id.partner_id.id], ['contact', 'invoice']) + contact_addr_id = res['contact'] + invoice_addr_id = res['invoice'] + + address = partner_address_pool.browse(cr, uid, invoice_addr_id, context=context) + edi_company_address_dict = {} + for key, value in company_address_dict.items(): + if not value: + continue + address_rec = getattr(address, key) + if not address_rec: + continue + if key.endswith('_id'): + address_rec = self.edi_m2o(cr, uid, address_rec, context=context) + edi_company_address_dict[key] = address_rec + + edi_doc.update({ + 'company_address': edi_company_address_dict, + #'company_logo': inv_comp.logo,#TODO + #'paid': inv_comp.paid, #TODO + }) + edi_doc_list.append(edi_doc) + return edi_doc_list def edi_import(self, cr, uid, edi_document, context=None): diff --git a/addons/account/test/test_edi_invoice.yml b/addons/account/test/test_edi_invoice.yml index 75c39d8aaf0..f66932f0464 100644 --- a/addons/account/test/test_edi_invoice.yml +++ b/addons/account/test/test_edi_invoice.yml @@ -48,6 +48,7 @@ tokens = self.export_edi(cr, uid, invoices) for token in tokens: document = self.get_document(cr, uid, token, context=context) + print document a = self.import_edi(cr, uid, edi_document = document) - From 3154cb96520b6a279e95f5cde74b5005cee472ab Mon Sep 17 00:00:00 2001 From: "Harry (OpenERP)" Date: Mon, 27 Jun 2011 17:56:16 +0530 Subject: [PATCH 009/265] [REF] account, edi: refactor code of edi_import method bzr revid: hmo@tinyerp.com-20110627122616-15e6y17d29bbricb --- addons/account/edi_invoice.py | 295 +++++++++-------------- addons/account/test/test_edi_invoice.yml | 5 +- 2 files changed, 119 insertions(+), 181 deletions(-) diff --git a/addons/account/edi_invoice.py b/addons/account/edi_invoice.py index ba3675a15f4..5d6d92df584 100644 --- a/addons/account/edi_invoice.py +++ b/addons/account/edi_invoice.py @@ -131,192 +131,131 @@ class account_invoice(osv.osv, ir_edi.edi): on the tax config of the DB where it is imported. """ - partner = self.pool.get('res.partner') - partner_add = self.pool.get('res.partner.address') - model_data = self.pool.get('ir.model.data') - product_obj = self.pool.get('product.product') - product_categ = self.pool.get('product.category') - acc_invoice = self.pool.get('account.invoice') - company = self.pool.get('res.company') - country = self.pool.get('res.country') + partner_pool = self.pool.get('res.partner') + partner_address_pool = self.pool.get('res.partner.address') + model_data_pool = self.pool.get('ir.model.data') + product_pool = self.pool.get('product.product') + product_categ_pool = self.pool.get('product.category') + company_pool = self.pool.get('res.company') + country_pool = self.pool.get('res.country') + state_pool = self.pool.get('res.country.state') + account_journal_pool = self.pool.get('account.journal') + invoice_line_pool = self.pool.get('account.invoice.line') + account_pool = self.pool.get('account.account') tax_id = [] account_id = [] partner_id = None company_id = None if context is None: context = {} - for field in edi_document.keys(): - if field == 'type': - if len(edi_document['invoice_line']): - name = edi_document['invoice_line'][0]['product_id'][1] - else: - name = None - re_ids = product_obj.search(cr,uid,[('name','=',name)]) - if edi_document['type'] == 'out_invoice' or edi_document['type'] == 'out_refund': - if re_ids: - if product_obj.browse(cr,uid,re_ids)[0].property_account_expense: - account_id = product_obj.browse(cr,uid,re_ids)[0].property_account_expense - else: - account_id = product_categ.browse(cr,uid,re_ids)[0].property_account_expense_categ - if product_obj.browse(cr,uid,re_ids)[0].taxes_id: - tax_id = product_obj.browse(cr, uid,re_ids)[0].taxes_id - if edi_document['type'] == 'out_refund': - edi_document['type'] = 'in_refund' - else: - edi_document['type'] = 'in_invoice' - elif edi_document['type'] == 'in_invoice' or edi_document['type'] == 'in_refund': - if re_ids: - if product_obj.browse(cr,uid,re_ids)[0].property_account_income: - account_id = product_obj.browse(cr,uid,re_ids)[0].property_account_income - else: - account_id = product_categ.browse(cr,uid,re_ids)[0].property_account_income_categ - if product_obj.browse(cr,uid,re_ids)[0].taxes_id: - tax_id = product_obj.browse(cr, uid,re_ids)[0].taxes_id - if edi_document['type'] == 'in_refund': - edi_document['type'] = 'out_refund' - else: - edi_document['type'] = 'out_invoice' - - if account_id: - name_ids = model_data.search(cr, uid, [('model','=',account_id._name),('res_id','=',account_id.id)]) - if name_ids: - xml_id = model_data.browse(cr, uid, name_ids)[0].name - db_uuid = ir_edi.safe_unique_id(account_id._name,account_id.id) - edi_document['invoice_line'][0]['account_id'] = [db_uuid+':'+xml_id,account_id.name] - - if tax_id: - name_ids = model_data.search(cr, uid, [('model','=',tax_id[0]._name),('res_id','=',tax_id[0].id)]) - if name_ids: - xml_id = model_data.browse(cr, uid, name_ids)[0].name - db_uuid = ir_edi.safe_unique_id(tax_id[0]._name,tax_id[0].id) - edi_document['tax_line'][0]['account_id'] = [db_uuid+':'+xml_id,tax_id[0].name] - else: - if len(edi_document['tax_line']): - edi_document['tax_line'][0]['manual'] = True - - res = {} - part = {} - comp = {} - partner_id = partner.search(cr,uid,[('name','=',edi_document['company_id'][1])]) - if len(partner_id): - browse_partner = partner.browse(cr,uid,partner_id[0]) - u_id = model_data.search(cr, uid, [('res_id','=',browse_partner.id),('model','=',browse_partner._name)]) - if len(u_id): - company_id = browse_partner.company_id - - xml_obj = model_data.browse(cr,uid,u_id[0]) - uuid = ir_edi.safe_unique_id(browse_partner._name,browse_partner.id) - db_uuid = '%s:%s' % (uuid,xml_obj.name) - part.update({'partner_id':[db_uuid,browse_partner.name]}) - - else: - - company_address = {} - company_id = company.create(cr, uid, {'name':edi_document['company_id'][1]}) - - for key in edi_document['company_address'].keys(): - if type(edi_document['company_address'][key]).__name__ == 'list': - if edi_document['company_address'][key][1] is not None: - country_id = country.search(cr ,uid,[('name','=',edi_document['company_address'][key][1])]) - - if len(country_id): - company_address.update({key : country_id[0]}) - - else: - if isinstance(edi_document['company_address'][key][1],unicode): - country_name = str(edi_document['company_address'][key][1]) - country_code = country_name[:2].upper() - country_id = country.create(cr, uid, {'code': country_code,name: country_name}) - company_address.update({key : country_id[0]}) - else: - company_address.update({key : edi_document['company_address'][key][1]}) - else: - company_address.update({key:edi_document['company_address'][key]}) - - add_id = [] - partner_id = [] - - add_id = partner_add.create(cr,uid,company_address) - - res.update({'name': edi_document['company_id'][1],'supplier': True,'address': [unicode(add_id)], 'company_id': unicode(company_id),'country' : country_id}) - - partner_id.append(partner.create(cr,uid,{'name': edi_document['company_id'][1],'supplier': True,'address': unicode(add_id), 'company_id': unicode(company_id),'country' : country_id})) - - browse_partner = partner.browse(cr,uid,partner_id[0]) - company_id = browse_partner.company_id - u_id = model_data.search(cr, uid, [('res_id','=',browse_partner.id),('model','=',browse_partner._name)]) - if len(u_id): - xml_obj = model_data.browse(cr,uid,u_id[0]) - uuid = ir_edi.safe_unique_id(browse_partner._name,browse_partner.id) - db_uuid = '%s:%s' % (uuid,xml_obj.name) - part.update({'partner_id':[db_uuid,browse_partner.name]}) - - comp_id = partner.search(cr,uid,[('name','=',edi_document['partner_id'][1])]) - - if len(comp_id): - browse_partner = partner.browse(cr,uid,comp_id[0]) - browse_company = company.browse(cr,uid,browse_partner.company_id.id) - u_id = u_id = model_data.search(cr, uid, [('res_id','=',browse_company.id),('model','=',browse_company._name)]) - if len(u_id): - xml_obj = model_data.browse(cr,uid,u_id[0]) - uuid = ir_edi.safe_unique_id(browse_company._name,browse_company.id) - db_uuid = '%s:%s' % (uuid,xml_obj.name) - comp.update({'company_id':[db_uuid,browse_company.name]}) - - del edi_document['partner_id'] - del edi_document['company_id'] - edi_document.update(part) - edi_document.update(comp) - - - if len(partner_id): - p = self.pool.get('res.partner').browse(cr, uid, partner_id[0]) - - partner_id = int(partner_id[0]) - - if company_id: - if p.property_account_receivable.company_id.id != company_id.id and p.property_account_payable.company_id.id != company_id.id: - property_obj = self.pool.get('ir.property') - - rec_pro_id = property_obj.search(cr,uid,[('name','=','property_account_receivable'),('res_id','=','res.partner,'+str(partner_id)+''),('company_id','=',company_id.id)]) - pay_pro_id = property_obj.search(cr,uid,[('name','=','property_account_payable'),('res_id','=','res.partner,'+str(partner_id)+''),('company_id','=',company_id.id)]) - - if not rec_pro_id: - rec_pro_id = property_obj.search(cr,uid,[('name','=','property_account_receivable'),('company_id','=',company_id.id)]) - if not pay_pro_id: - pay_pro_id = property_obj.search(cr,uid,[('name','=','property_account_payable'),('company_id','=',company_id.id)]) - rec_line_data = property_obj.read(cr,uid,rec_pro_id,['name','value_reference','res_id']) - pay_line_data = property_obj.read(cr,uid,pay_pro_id,['name','value_reference','res_id']) - rec_res_id = rec_line_data and rec_line_data[0].get('value_reference',False) and int(rec_line_data[0]['value_reference'].split(',')[1]) or False - pay_res_id = pay_line_data and pay_line_data[0].get('value_reference',False) and int(pay_line_data[0]['value_reference'].split(',')[1]) or False - if not rec_res_id and not pay_res_id: - raise osv.except_osv(_('Configuration Error !'), _('Can not find account chart for this company, Please Create account.')) - - account_obj = self.pool.get('account.account') - rec_obj_acc = account_obj.browse(cr, uid, [rec_res_id]) - pay_obj_acc = account_obj.browse(cr, uid, [pay_res_id]) - p.property_account_receivable = rec_obj_acc[0] - p.property_account_payable = pay_obj_acc[0] - if edi_document['type'] in ('out_invoice', 'out_refund'): - acc_obj = p.property_account_receivable - else: - acc_obj = p.property_account_payable - - res_id = model_data.search(cr,uid,[('model','=',acc_obj._name),('res_id','=',acc_obj.id)]) - - if len(res_id): - xml_obj = model_data.browse(cr, uid, res_id[0]) - uuid = ir_edi.safe_unique_id(acc_obj._name,acc_obj.id) - db_uuid = '%s:%s' % (uuid,xml_obj.name) - edi_document.update({'account_id':[db_uuid,acc_obj.name]}) - - edi_document.update({'reference':edi_document['internal_number'],'reference_type' : 'none'}) - edi_document['internal_number'] = False - context['type'] = edi_document['type'] - + + # import company as a new partner, if type==in then supplier=1, else customer=1 + # partner_id field is modified to point to the new partner + # company_address data used to add address to new partner + edi_company_address = edi_document['company_address'] + edi_partner_id = edi_document['partner_id'] + company_name = edi_document['company_id'][1] + invoice_type = edi_document['type'] + state_id = edi_company_address.get('state_id', False) + state_name = state_id and state_id[1] + country_id = edi_company_address.get('country_id', False) + country_name = country_id and country_id[1] + + country_id = country_name and self.edi_import_relation(cr, uid, 'res.country', country_name, context=context) or False + state_id = state_name and self.edi_import_relation(cr, uid, 'res.country.state', state_name, + values={'country_id': country_id, 'code': state_name}, context=context) or False + address_value = { + 'street': edi_company_address.get('street', False), + 'street2': edi_company_address.get('street2', False), + 'zip': edi_company_address.get('zip', False), + 'city': edi_company_address.get('city', False), + 'state_id': state_id, + 'country_id': country_id, + 'email': edi_company_address.get('email', False), + 'phone': edi_company_address.get('phone', False), + + } + + + partner_value = {'name': company_name} + if invoice_type in ('out_invoice', 'in_refund'): + partner_value.update({'customer': True, 'supplier': False}) + if invoice_type in ('in_invoice', 'out_refund'): + partner_value.update({'customer': False, 'supplier': True}) + + partner_id = partner_pool.create(cr, uid, partner_value, context=context) + address_value.update({'partner_id': partner_id}) + address_id = partner_address_pool.create(cr, uid, address_value, context=context) + + partner = partner_pool.browse(cr, uid, partner_id, context=context) + edi_document['partner_id'] = self.edi_m2o(cr, uid, partner, context=context) + + # change type: out_invoice'<->'in_invoice','out_refund'<->'in_refund' + invoice_type = invoice_type.startswith('in_') and invoice_type.replace('in_','out_') or invoice_type.replace('out_','in_') + edi_document['type'] = invoice_type + + # Set Account + if invoice_type in ('out_invoice', 'out_refund'): + invoice_account = partner.property_account_receivable + else: + invoice_account = partner.property_account_payable + 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' + edi_document['reference'] = edi_document.get('internal_number', False) + # reference_type: 'none' + edi_document['reference_type'] = 'none' + + # internal number: reset to False, auto-generated + edi_document['internal_number'] = False + + # company should set by default so delete company data from edi Document del edi_document['company_address'] - return super(account_invoice,self).edi_import(cr, uid, edi_document) + del edi_document['company_id'] + + # journal_id: should be selected based on type: simply put the 'type' in the context when calling create(), will be selected correctly + 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) + edi_document['journal_id'] = journal and self.edi_m2o(cr, uid, journal, context=context) or False + + # 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) + product = product_pool.browse(cr, uid, product_id, context=context) + + 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 + else: + account = product.product_tmpl_id.property_account_expense + if not account: + account = product.categ_id.property_account_expense_categ + + # TODO: add effect of fiscal position + # 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 + + # 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. + for edi_tax_line in edi_document.get('tax_line', []): + account_ids = account_pool.search(cr, uid, [('type','<>','view'),('type','<>','income'), ('type', '<>', 'closed')]) + if account_ids: + edi_tax_line['account_id'] = account_ids[0] #TODO should select account of output VAT for Customer Invoice and Input VAT for Supplier Invoice + edi_tax_line['manual'] = True + + # TODO :=> payment_term: if set, create a default one based on name... + print edi_document + return super(account_invoice,self).edi_import(cr, uid, edi_document, context=context) account_invoice() diff --git a/addons/account/test/test_edi_invoice.yml b/addons/account/test/test_edi_invoice.yml index f66932f0464..18e5a8fb9e9 100644 --- a/addons/account/test/test_edi_invoice.yml +++ b/addons/account/test/test_edi_invoice.yml @@ -28,7 +28,7 @@ company_id: base.main_company account_id: 1 date_invoice: '2011-06-22' - name: Nothing + name: selling product type: 'out_invoice' invoice_line: - product_id: product.product_product_pc1 @@ -48,14 +48,13 @@ tokens = self.export_edi(cr, uid, invoices) for token in tokens: document = self.get_document(cr, uid, token, context=context) - print document a = self.import_edi(cr, uid, edi_document = document) - Check the customer invoice is exported or not - !python {model: account.invoice}: | - ids=self.search(cr, uid, [('partner_id','=',ref("res_partner_test20")),('company_id','=',ref("res_company_test11")),('type','=','out_invoice')]) + ids=self.search(cr, uid, [('partner_id','=',ref("res_partner_test20")),('type','=','out_invoice')]) if not ids: raise AssertionError("Invoice is not imported") From 99624f6b0efe76186d1c51e26d733938c087660d Mon Sep 17 00:00:00 2001 From: "Harry (OpenERP)" Date: Mon, 27 Jun 2011 17:57:32 +0530 Subject: [PATCH 010/265] [REF] account, edi: remove print statement bzr revid: hmo@tinyerp.com-20110627122732-s2yswh7mtyaumjz9 --- addons/account/edi_invoice.py | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/account/edi_invoice.py b/addons/account/edi_invoice.py index 5d6d92df584..e37bd220d35 100644 --- a/addons/account/edi_invoice.py +++ b/addons/account/edi_invoice.py @@ -254,7 +254,6 @@ class account_invoice(osv.osv, ir_edi.edi): edi_tax_line['manual'] = True # TODO :=> payment_term: if set, create a default one based on name... - print edi_document return super(account_invoice,self).edi_import(cr, uid, edi_document, context=context) account_invoice() From 0441c97c5c8eef5809cf9a6dfc8982ca9e6f8d8b Mon Sep 17 00:00:00 2001 From: "Harry (OpenERP)" Date: Wed, 29 Jun 2011 11:14:52 +0530 Subject: [PATCH 011/265] [REVIEW] account: correct YML of EDI bzr revid: hmo@tinyerp.com-20110629054452-2e0vsmleaouos6zv --- addons/account/test/test_edi_invoice.yml | 34 ++++++++++++------------ 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/addons/account/test/test_edi_invoice.yml b/addons/account/test/test_edi_invoice.yml index dacd80e57b1..6651448c712 100644 --- a/addons/account/test/test_edi_invoice.yml +++ b/addons/account/test/test_edi_invoice.yml @@ -1,5 +1,5 @@ - - create Company + I create a company for Customer - !record {model: res.company, id: res_company_test11}: name: Thomson pvt. ltd. @@ -10,14 +10,14 @@ currency_id: 1 - - create partner + 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 - - create customer invoice + I create one customer invoice - !record {model: account.invoice, id: customer_invoice_test}: journal_id: 1 @@ -45,7 +45,7 @@ amount: 1000.00 - - I open the Invoice for the SO. + I Open the Invoice - !python {model: account.invoice}: | @@ -55,30 +55,30 @@ wf_service.trg_validate(uid, 'account.invoice',invoices.id,'invoice_open', cr) - - Tesing of EDI functionality + I Tesing of EDI functionality. First I export customer invoice from my company than import that invoice into customer company - !python {model: ir.edi.document}: | - invoice_invoice_new = self.pool.get('account.invoice') - invoices = invoice_invoice_new.browse(cr, uid, [ref("customer_invoice_test")]) - tokens = self.export_edi(cr, uid, invoices) - for token in tokens: - document = self.get_document(cr, uid, token, context=context) - a = self.import_edi(cr, uid, edi_document = 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' + document = self.get_document(cr, uid, tokens[0]) + a = self.import_edi(cr, uid, edi_document = document) + assert a, 'Invoice is not imported' - - Check the exported out_invoice become in_invoice or not + I Checking the out invoice become in invoice or not after import - !python {model: account.invoice}: | - invoice_old = self.browse(cr,uid,ref("customer_invoice_test")) + invoice_old = self.browse(cr, uid, ref("customer_invoice_test")) new_partner_id = self.pool.get('res.partner').name_search(cr, uid, invoice_old.company_id.name) - assert new_partner_id, 'Partner is not created of party' + assert new_partner_id, 'Partner is not created of Supplier' - ids = self.search(cr, uid, [('partner_id','=',new_partner_id[0]),('reference','=',invoice_old.internal_number)]) + ids = self.search(cr, uid, [('partner_id','=',new_partner_id[0][0]),('reference','=',invoice_old.internal_number)]) assert ids, 'Invoice does not have created of party' invoice_new = self.browse(cr, uid, ids[0]) assert invoice_new.reference == invoice_old.internal_number, "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" for inv_line in invoice_new.invoice_line: From d1ce89e2a5f2fb26fdc93fc461859329a9329ff0 Mon Sep 17 00:00:00 2001 From: "Hardik Ansodariy (OpenERP)" Date: Fri, 8 Jul 2011 15:00:22 +0530 Subject: [PATCH 012/265] [IMP]:Adding stock picking in edi bzr revid: han@tinyerp.com-20110708093022-qm22kull5wq1vvmi --- addons/account/__openerp__.py | 4 +- addons/account/edi_invoice_action.xml | 11 +- addons/stock/__init__.py | 3 +- addons/stock/__openerp__.py | 5 +- addons/stock/edi_stock_picking.py | 183 ++++++++++++++++++++++++++ 5 files changed, 195 insertions(+), 11 deletions(-) create mode 100644 addons/stock/edi_stock_picking.py diff --git a/addons/account/__openerp__.py b/addons/account/__openerp__.py index adc0e3ea7e2..d5818f0bf6d 100644 --- a/addons/account/__openerp__.py +++ b/addons/account/__openerp__.py @@ -122,14 +122,14 @@ 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.xml", ], 'demo_xml': [ 'account_demo.xml', 'project/project_demo.xml', 'project/analytic_account_demo.xml', 'demo/account_minimal.xml', - "edi_invoice_action.xml", + #"edi_invoice_action.xml", # 'account_unit_test.xml', ], 'test': [ diff --git a/addons/account/edi_invoice_action.xml b/addons/account/edi_invoice_action.xml index e5d7a3f5022..a7bb3d5edf7 100644 --- a/addons/account/edi_invoice_action.xml +++ b/addons/account/edi_invoice_action.xml @@ -3,7 +3,7 @@ - context.update({'token':self.pool.get('ir.edi.document').export_edi(cr, uid, [object], context = context)}) + context.update({'token':self.pool.get('ir.edi.document').export_edi(cr, uid, [object], context = context),'invoice':object.number,'company':object.company_id.name,'currency':object.currency_id.name,'amount':object.amount_total,'date_due':object.date_due}) code ir.actions.server @@ -49,15 +49,14 @@ xyz - test ${object._context.get('token')} -${object.account_id.currency_mode} + Hello, -We just registered the invoice 'INV/001' for 121 EUR for your company 'ASUSTek'. +We just registered the invoice ${object.number} for ${object.amount}, ${object.currency} for your company ${object.company}. You can click on the following link to preview, print and pay this invoice: - http://URL_ON_WEB_CLIENT + http://localhost:8080/openerp/token? ${object._context.get('token')} -Please note that this invoice has to be paid before 12/04/2011. +Please note that this invoice has to be paid before ${object.date_due} Regards, mako diff --git a/addons/stock/__init__.py b/addons/stock/__init__.py index 78abee6d31d..4c4634babc1 100644 --- a/addons/stock/__init__.py +++ b/addons/stock/__init__.py @@ -24,5 +24,6 @@ import partner import product import report import wizard +import edi_stock_picking -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock/__openerp__.py b/addons/stock/__openerp__.py index 1a33fd3012c..9e743b6ff0d 100644 --- a/addons/stock/__openerp__.py +++ b/addons/stock/__openerp__.py @@ -48,7 +48,7 @@ Thanks to the double entry management, the inventory controlling is powerful and "depends" : ["product", "account"], "category" : "Warehouse", "init_xml" : [], - "demo_xml" : ["stock_demo.xml"], + #"demo_xml" : ["stock_demo.xml"], "update_xml" : [ "security/stock_security.xml", "security/ir.model.access.csv", @@ -75,7 +75,8 @@ Thanks to the double entry management, the inventory controlling is powerful and "partner_view.xml", "report/report_stock_move_view.xml", "report/report_stock_view.xml", - "board_warehouse_view.xml" + "board_warehouse_view.xml", + "test/edi_stock_picking.yml", ], 'test': ['test/stock_test.yml', 'test/stock_report.yml', diff --git a/addons/stock/edi_stock_picking.py b/addons/stock/edi_stock_picking.py new file mode 100644 index 00000000000..d74a3ef5665 --- /dev/null +++ b/addons/stock/edi_stock_picking.py @@ -0,0 +1,183 @@ +# -*- 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 _ + +class stock_picking(osv.osv, ir_edi.edi): + _inherit = 'stock.picking' + + def edi_export(self, cr, uid, records, edi_struct=None, context=None): + """Exports a supplier or customer invoice""" + edi_struct = { + + 'origin': True, + 'type': True, + 'stock_journal_id': True, + 'move_type': True, + 'date': True, + 'date_done': True, + 'move_lines': { + 'name': True, + 'date': True, + 'date_expected': True, + 'product_id': True, + 'product_qty': True, + 'product_uom': True, + 'location_id': True, + 'location_dest_id': True, + 'company_id': True, + }, + 'invoice_state': True, + 'address_id': True, + 'company_id': True, + } + partner_pool = self.pool.get('res.partner') + partner_address_pool = self.pool.get('res.partner.address') + company_address_dict = { + 'street': True, + 'street2': True, + 'zip': True, + 'city': True, + 'state_id': True, + 'country_id': True, + 'email': True, + 'phone': True, + + } + edi_doc_list = [] + for picking in records: + # Get EDI doc based on struct. The result will also contain all metadata fields and attachments. + edi_doc = super(stock_picking,self).edi_export(cr, uid, [picking], edi_struct, context) + if not edi_doc: + continue + edi_doc = edi_doc[0] + + # Add company info and address + res = partner_pool.address_get(cr, uid, [picking.company_id.partner_id.id], ['contact', 'picking']) + contact_addr_id = res['contact'] + invoice_addr_id = res['picking'] + + address = partner_address_pool.browse(cr, uid, invoice_addr_id, context=context) + edi_company_address_dict = {} + for key, value in company_address_dict.items(): + if not value: + continue + address_rec = getattr(address, key) + if not address_rec: + continue + if key.endswith('_id'): + address_rec = self.edi_m2o(cr, uid, address_rec, context=context) + edi_company_address_dict[key] = address_rec + + edi_doc.update({ + 'company_address': edi_company_address_dict, + #'company_logo': inv_comp.logo,#TODO + #'paid': inv_comp.paid, #TODO + }) + edi_doc_list.append(edi_doc) + return edi_doc_list + + def edi_import(self, cr, uid, edi_document, context=None): + + partner_pool = self.pool.get('res.partner') + partner_address_pool = self.pool.get('res.partner.address') + model_data_pool = self.pool.get('ir.model.data') + product_pool = self.pool.get('product.product') + product_categ_pool = self.pool.get('product.category') + company_pool = self.pool.get('res.company') + country_pool = self.pool.get('res.country') + state_pool = self.pool.get('res.country.state') + account_journal_pool = self.pool.get('account.journal') + invoice_line_pool = self.pool.get('account.invoice.line') + account_pool = self.pool.get('account.account') + tax_id = [] + account_id = [] + partner_id = None + company_id = None + if context is None: + context = {} + + # import company as a new partner, if type==in then supplier=1, else customer=1 + # partner_id field is modified to point to the new partner + # company_address data used to add address to new partner + edi_company_address = edi_document['company_address'] + + company_name = edi_document['company_id'][1] + shipping_type = edi_document['type'] + state_id = edi_company_address.get('state_id', False) + state_name = state_id and state_id[1] + country_id = edi_company_address.get('country_id', False) + country_name = country_id and country_id[1] + + country_id = country_name and self.edi_import_relation(cr, uid, 'res.country', country_name, context=context) or False + state_id = state_name and self.edi_import_relation(cr, uid, 'res.country.state', state_name, + values={'country_id': country_id, 'code': state_name}, context=context) or False + address_value = { + 'street': edi_company_address.get('street', False), + 'street2': edi_company_address.get('street2', False), + 'zip': edi_company_address.get('zip', False), + 'city': edi_company_address.get('city', False), + 'state_id': state_id, + 'country_id': country_id, + 'email': edi_company_address.get('email', False), + 'phone': edi_company_address.get('phone', False), + + } + + + partner_value = {'name': company_name} + partner_id = partner_pool.search(cr, uid, [('name','=',company_name)]) + if len(partner_id): + partner_id = partner_pool.browse(cr, uid, partner_id[0], context=context) + address_id = partner_id.address[0].id + else: + partner_id = partner_pool.create(cr, uid, partner_value, context=context) + address_value.update({'partner_id': partner_id}) + address_id = partner_address_pool.create(cr, uid, address_value, context=context) + partner_address = partner_address_pool.browse(cr, uid, address_id, context=context) + edi_document.update({'address_id': self.edi_m2o(cr, uid, partner_address, context=context)}) + + + + + # change type: out'<->'in for shipping + shipping_type = shipping_type.startswith('in') and shipping_type.replace('in','out') or shipping_type.replace('out','in') + edi_document['type'] = shipping_type + company_id = edi_document['company_id'] + #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>",edi_document['move_lines'] + edi_document.update({'company_id': edi_document['move_lines'][0]['company_id']}) + edi_document['move_lines'][0].update({'company_id':company_id}) + + del edi_document['company_address'] + + + + return super(stock_picking,self).edi_import(cr, uid, edi_document, context=context) + +stock_picking() + +class stock_move(osv.osv, ir_edi.edi): + _inherit='stock.move' + +stock_move() + From 30b5f52c572e39f751227fc4301387b539c2a9b4 Mon Sep 17 00:00:00 2001 From: "Harry (OpenERP)" Date: Wed, 13 Jul 2011 15:49:07 +0530 Subject: [PATCH 013/265] [IMP] account: add some fields in EDI Dict of account.invoice which are display in Web EDI Interface bzr revid: hmo@tinyerp.com-20110713101907-oo7le07rtkwzpsdu --- addons/account/edi_invoice.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/addons/account/edi_invoice.py b/addons/account/edi_invoice.py index f8f615b40fc..7c69b52b879 100644 --- a/addons/account/edi_invoice.py +++ b/addons/account/edi_invoice.py @@ -35,6 +35,10 @@ 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, 'date_invoice': True, 'date_due': True, 'partner_id': True, @@ -47,6 +51,7 @@ class account_invoice(osv.osv, ir_edi.edi): 'uos_id': True, 'product_id': True, 'price_unit': True, + 'price_subtotal': True, 'quantity': True, 'discount': True, 'note': True, From e087243c241382e59cae48a87289fa00f501415c Mon Sep 17 00:00:00 2001 From: "Harry (OpenERP)" Date: Thu, 14 Jul 2011 16:27:16 +0530 Subject: [PATCH 014/265] [REVIEW] account: rename file name of edi_invoice_action_data bzr revid: hmo@tinyerp.com-20110714105716-xn54phkryzjuc94e --- addons/account/__openerp__.py | 3 +-- .../{edi_invoice_action.xml => edi_invoice_action_data.xml} | 0 addons/stock/__init__.py | 1 - addons/stock/__openerp__.py | 3 +-- 4 files changed, 2 insertions(+), 5 deletions(-) rename addons/account/{edi_invoice_action.xml => edi_invoice_action_data.xml} (100%) diff --git a/addons/account/__openerp__.py b/addons/account/__openerp__.py index d5818f0bf6d..a0796fcf6b8 100644 --- a/addons/account/__openerp__.py +++ b/addons/account/__openerp__.py @@ -122,14 +122,13 @@ 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.xml", + "edi_invoice_action_data.xml", ], 'demo_xml': [ 'account_demo.xml', 'project/project_demo.xml', 'project/analytic_account_demo.xml', 'demo/account_minimal.xml', - #"edi_invoice_action.xml", # 'account_unit_test.xml', ], 'test': [ diff --git a/addons/account/edi_invoice_action.xml b/addons/account/edi_invoice_action_data.xml similarity index 100% rename from addons/account/edi_invoice_action.xml rename to addons/account/edi_invoice_action_data.xml diff --git a/addons/stock/__init__.py b/addons/stock/__init__.py index 4c4634babc1..0a241209593 100644 --- a/addons/stock/__init__.py +++ b/addons/stock/__init__.py @@ -24,6 +24,5 @@ import partner import product import report import wizard -import edi_stock_picking # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock/__openerp__.py b/addons/stock/__openerp__.py index 9e743b6ff0d..f4facc9c4f7 100644 --- a/addons/stock/__openerp__.py +++ b/addons/stock/__openerp__.py @@ -48,7 +48,7 @@ Thanks to the double entry management, the inventory controlling is powerful and "depends" : ["product", "account"], "category" : "Warehouse", "init_xml" : [], - #"demo_xml" : ["stock_demo.xml"], + "demo_xml" : ["stock_demo.xml"], "update_xml" : [ "security/stock_security.xml", "security/ir.model.access.csv", @@ -76,7 +76,6 @@ Thanks to the double entry management, the inventory controlling is powerful and "report/report_stock_move_view.xml", "report/report_stock_view.xml", "board_warehouse_view.xml", - "test/edi_stock_picking.yml", ], 'test': ['test/stock_test.yml', 'test/stock_report.yml', From ced29b87a0a05c41ec8f505139b97babe636e711 Mon Sep 17 00:00:00 2001 From: "Harry (OpenERP)" Date: Thu, 14 Jul 2011 16:32:55 +0530 Subject: [PATCH 015/265] [IMP] account: add dependancy of email_template module bzr revid: hmo@tinyerp.com-20110714110255-65ny7ujd5arcxz37 --- addons/account/__openerp__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/account/__openerp__.py b/addons/account/__openerp__.py index a0796fcf6b8..6e6d1b79f99 100644 --- a/addons/account/__openerp__.py +++ b/addons/account/__openerp__.py @@ -52,7 +52,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" : ["product", "analytic", "process","board"], + "depends" : ["product", "analytic", "process","board", "email_template"], 'update_xml': [ 'security/account_security.xml', 'security/ir.model.access.csv', From 7e77228d291cddc80b52483d84931b2423a8c739 Mon Sep 17 00:00:00 2001 From: "Harry (OpenERP)" Date: Fri, 15 Jul 2011 13:14:42 +0530 Subject: [PATCH 016/265] [REVIEW] account: correct server action and email template data and add default email template bzr revid: hmo@tinyerp.com-20110715074442-w9u3y0wv3s5omoll --- addons/account/edi_invoice_action_data.xml | 63 +++++++------------ .../email_template_scheduler_data.xml | 8 +++ 2 files changed, 30 insertions(+), 41 deletions(-) diff --git a/addons/account/edi_invoice_action_data.xml b/addons/account/edi_invoice_action_data.xml index a7bb3d5edf7..75e814216e7 100644 --- a/addons/account/edi_invoice_action_data.xml +++ b/addons/account/edi_invoice_action_data.xml @@ -2,69 +2,50 @@ - - context.update({'token':self.pool.get('ir.edi.document').export_edi(cr, uid, [object], context = context),'invoice':object.number,'company':object.company_id.name,'currency':object.currency_id.name,'amount':object.amount_total,'date_due':object.date_due}) + + context.update({'edi_web_url_view': '%s/edi/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 object.partner_id.opt_out: self.pool.get('email.template').generate_mail(cr, + uid, + self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account', 'email_template_edi_invoice')[1], + [object.id], + context=context) code ir.actions.server True - invoice - - - - - - hello - invoice created - email - ir.actions.server - han@tinyerp.com - - True - invoice_send - - - - - - other - ir.actions.server - - - True - Multi_action + EDI Document - Invoice + - + + - - - invoice - xyz - + + + ${object.company_id.name} - Invoice ${object.number} + ${object.address_invoice_id.email} - xyz + True -Hello, +Hello ${object.partner_id.name}, -We just registered the invoice ${object.number} for ${object.amount}, ${object.currency} for your company ${object.company}. +We just registered the invoice ${object.number} for ${object.amount_total} ${object.currency_id.name} for your company ${object.company_id.name}. You can click on the following link to preview, print and pay this invoice: - http://localhost:8080/openerp/token? ${object._context.get('token')} + + ${object._context.get('edi_web_url_view')} Please note that this invoice has to be paid before ${object.date_due} Regards, mako - english - xyz - Invoice + Mail Template of Invoice For EDI Document account.invoice - xyz + ${object.user_id.email or ''} diff --git a/addons/email_template/email_template_scheduler_data.xml b/addons/email_template/email_template_scheduler_data.xml index 45a9be04ac7..910aa8572e6 100644 --- a/addons/email_template/email_template_scheduler_data.xml +++ b/addons/email_template/email_template_scheduler_data.xml @@ -1,6 +1,14 @@ + + + Default EMail Template Account + test@localhost + draft + + + Email Template scheduler From 17e25609ed72ebce2ce7edf33ae54d39a4f5efec Mon Sep 17 00:00:00 2001 From: "Harry (OpenERP)" Date: Fri, 15 Jul 2011 14:02:49 +0530 Subject: [PATCH 017/265] [REM] stock: EDI feature will be included later bzr revid: hmo@tinyerp.com-20110715083249-02cutonhjovv2z2k --- addons/stock/edi_stock_picking.py | 183 ------------------------------ 1 file changed, 183 deletions(-) delete mode 100644 addons/stock/edi_stock_picking.py diff --git a/addons/stock/edi_stock_picking.py b/addons/stock/edi_stock_picking.py deleted file mode 100644 index d74a3ef5665..00000000000 --- a/addons/stock/edi_stock_picking.py +++ /dev/null @@ -1,183 +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 _ - -class stock_picking(osv.osv, ir_edi.edi): - _inherit = 'stock.picking' - - def edi_export(self, cr, uid, records, edi_struct=None, context=None): - """Exports a supplier or customer invoice""" - edi_struct = { - - 'origin': True, - 'type': True, - 'stock_journal_id': True, - 'move_type': True, - 'date': True, - 'date_done': True, - 'move_lines': { - 'name': True, - 'date': True, - 'date_expected': True, - 'product_id': True, - 'product_qty': True, - 'product_uom': True, - 'location_id': True, - 'location_dest_id': True, - 'company_id': True, - }, - 'invoice_state': True, - 'address_id': True, - 'company_id': True, - } - partner_pool = self.pool.get('res.partner') - partner_address_pool = self.pool.get('res.partner.address') - company_address_dict = { - 'street': True, - 'street2': True, - 'zip': True, - 'city': True, - 'state_id': True, - 'country_id': True, - 'email': True, - 'phone': True, - - } - edi_doc_list = [] - for picking in records: - # Get EDI doc based on struct. The result will also contain all metadata fields and attachments. - edi_doc = super(stock_picking,self).edi_export(cr, uid, [picking], edi_struct, context) - if not edi_doc: - continue - edi_doc = edi_doc[0] - - # Add company info and address - res = partner_pool.address_get(cr, uid, [picking.company_id.partner_id.id], ['contact', 'picking']) - contact_addr_id = res['contact'] - invoice_addr_id = res['picking'] - - address = partner_address_pool.browse(cr, uid, invoice_addr_id, context=context) - edi_company_address_dict = {} - for key, value in company_address_dict.items(): - if not value: - continue - address_rec = getattr(address, key) - if not address_rec: - continue - if key.endswith('_id'): - address_rec = self.edi_m2o(cr, uid, address_rec, context=context) - edi_company_address_dict[key] = address_rec - - edi_doc.update({ - 'company_address': edi_company_address_dict, - #'company_logo': inv_comp.logo,#TODO - #'paid': inv_comp.paid, #TODO - }) - edi_doc_list.append(edi_doc) - return edi_doc_list - - def edi_import(self, cr, uid, edi_document, context=None): - - partner_pool = self.pool.get('res.partner') - partner_address_pool = self.pool.get('res.partner.address') - model_data_pool = self.pool.get('ir.model.data') - product_pool = self.pool.get('product.product') - product_categ_pool = self.pool.get('product.category') - company_pool = self.pool.get('res.company') - country_pool = self.pool.get('res.country') - state_pool = self.pool.get('res.country.state') - account_journal_pool = self.pool.get('account.journal') - invoice_line_pool = self.pool.get('account.invoice.line') - account_pool = self.pool.get('account.account') - tax_id = [] - account_id = [] - partner_id = None - company_id = None - if context is None: - context = {} - - # import company as a new partner, if type==in then supplier=1, else customer=1 - # partner_id field is modified to point to the new partner - # company_address data used to add address to new partner - edi_company_address = edi_document['company_address'] - - company_name = edi_document['company_id'][1] - shipping_type = edi_document['type'] - state_id = edi_company_address.get('state_id', False) - state_name = state_id and state_id[1] - country_id = edi_company_address.get('country_id', False) - country_name = country_id and country_id[1] - - country_id = country_name and self.edi_import_relation(cr, uid, 'res.country', country_name, context=context) or False - state_id = state_name and self.edi_import_relation(cr, uid, 'res.country.state', state_name, - values={'country_id': country_id, 'code': state_name}, context=context) or False - address_value = { - 'street': edi_company_address.get('street', False), - 'street2': edi_company_address.get('street2', False), - 'zip': edi_company_address.get('zip', False), - 'city': edi_company_address.get('city', False), - 'state_id': state_id, - 'country_id': country_id, - 'email': edi_company_address.get('email', False), - 'phone': edi_company_address.get('phone', False), - - } - - - partner_value = {'name': company_name} - partner_id = partner_pool.search(cr, uid, [('name','=',company_name)]) - if len(partner_id): - partner_id = partner_pool.browse(cr, uid, partner_id[0], context=context) - address_id = partner_id.address[0].id - else: - partner_id = partner_pool.create(cr, uid, partner_value, context=context) - address_value.update({'partner_id': partner_id}) - address_id = partner_address_pool.create(cr, uid, address_value, context=context) - partner_address = partner_address_pool.browse(cr, uid, address_id, context=context) - edi_document.update({'address_id': self.edi_m2o(cr, uid, partner_address, context=context)}) - - - - - # change type: out'<->'in for shipping - shipping_type = shipping_type.startswith('in') and shipping_type.replace('in','out') or shipping_type.replace('out','in') - edi_document['type'] = shipping_type - company_id = edi_document['company_id'] - #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>",edi_document['move_lines'] - edi_document.update({'company_id': edi_document['move_lines'][0]['company_id']}) - edi_document['move_lines'][0].update({'company_id':company_id}) - - del edi_document['company_address'] - - - - return super(stock_picking,self).edi_import(cr, uid, edi_document, context=context) - -stock_picking() - -class stock_move(osv.osv, ir_edi.edi): - _inherit='stock.move' - -stock_move() - From e1a12a3c434007bdc55f7854a867c039854f2294 Mon Sep 17 00:00:00 2001 From: "Harry (OpenERP)" Date: Fri, 15 Jul 2011 14:13:43 +0530 Subject: [PATCH 018/265] [FIX] account.edi_invoice: export value of reconciled field bzr revid: hmo@tinyerp.com-20110715084343-135d1hc6057j1sb4 --- addons/account/edi_invoice.py | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/account/edi_invoice.py b/addons/account/edi_invoice.py index 7c69b52b879..786fbb0b018 100644 --- a/addons/account/edi_invoice.py +++ b/addons/account/edi_invoice.py @@ -39,6 +39,7 @@ class account_invoice(osv.osv, ir_edi.edi): 'amount_untaxed': True, 'amount_tax': True, 'amount_total': True, + 'reconciled': True, 'date_invoice': True, 'date_due': True, 'partner_id': True, From a5d8abd4ada1e9f436755b66face4ba20e3b597f Mon Sep 17 00:00:00 2001 From: "Harry (OpenERP)" Date: Fri, 15 Jul 2011 16:29:13 +0530 Subject: [PATCH 019/265] [FIX] account.edi_invoice: import correct address of partner bzr revid: hmo@tinyerp.com-20110715105913-kzcidgprxczq3mao --- addons/account/edi_invoice.py | 3 +++ addons/account/edi_invoice_action_data.xml | 7 +++---- addons/email_template/email_template_scheduler_data.xml | 8 -------- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/addons/account/edi_invoice.py b/addons/account/edi_invoice.py index 786fbb0b018..22d1c793f22 100644 --- a/addons/account/edi_invoice.py +++ b/addons/account/edi_invoice.py @@ -196,6 +196,9 @@ class account_invoice(osv.osv, ir_edi.edi): partner = partner_pool.browse(cr, uid, partner_id, context=context) edi_document['partner_id'] = self.edi_m2o(cr, uid, partner, context=context) + partner_address = partner_address_pool.browse(cr, uid, address_id, context=context) + edi_document['address_invoice_id'] = self.edi_m2o(cr, uid, partner_address, context=context) + # change type: out_invoice'<->'in_invoice','out_refund'<->'in_refund' invoice_type = invoice_type.startswith('in_') and invoice_type.replace('in_','out_') or invoice_type.replace('out_','in_') edi_document['type'] = invoice_type diff --git a/addons/account/edi_invoice_action_data.xml b/addons/account/edi_invoice_action_data.xml index 75e814216e7..af778e2abe0 100644 --- a/addons/account/edi_invoice_action_data.xml +++ b/addons/account/edi_invoice_action_data.xml @@ -26,13 +26,11 @@ if object.partner_id.opt_out: self.pool.get('email.template').generate_mail(cr, - ${object.company_id.name} - Invoice ${object.number} ${object.address_invoice_id.email} True - -Hello ${object.partner_id.name}, + Hello ${object.partner_id.name}, We just registered the invoice ${object.number} for ${object.amount_total} ${object.currency_id.name} for your company ${object.company_id.name}. You can click on the following link to preview, print and pay this invoice: @@ -41,7 +39,8 @@ You can click on the following link to preview, print and pay this invoice: Please note that this invoice has to be paid before ${object.date_due} -Regards, +Regards, + mako Mail Template of Invoice For EDI Document account.invoice diff --git a/addons/email_template/email_template_scheduler_data.xml b/addons/email_template/email_template_scheduler_data.xml index 910aa8572e6..45a9be04ac7 100644 --- a/addons/email_template/email_template_scheduler_data.xml +++ b/addons/email_template/email_template_scheduler_data.xml @@ -1,14 +1,6 @@ - - - Default EMail Template Account - test@localhost - draft - - - Email Template scheduler From 1e27a50175223eb70cfbe30756125e57119a2595 Mon Sep 17 00:00:00 2001 From: "Harry (OpenERP)" Date: Fri, 15 Jul 2011 17:12:12 +0530 Subject: [PATCH 020/265] [FIX] account.edi_invoice: correct email template bzr revid: hmo@tinyerp.com-20110715114212-bh2kv0ev03dpdm6d --- addons/account/edi_invoice_action_data.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/account/edi_invoice_action_data.xml b/addons/account/edi_invoice_action_data.xml index af778e2abe0..4cf3de86489 100644 --- a/addons/account/edi_invoice_action_data.xml +++ b/addons/account/edi_invoice_action_data.xml @@ -30,14 +30,14 @@ if object.partner_id.opt_out: self.pool.get('email.template').generate_mail(cr, ${object.address_invoice_id.email} True - Hello ${object.partner_id.name}, + Hello ${object.address_invoice_id.name}, -We just registered the invoice ${object.number} for ${object.amount_total} ${object.currency_id.name} for your company ${object.company_id.name}. +We just registered the invoice ${object.number} for ${object.amount_total} ${object.currency_id.name} for your company ${object.partner_id.name}. You can click on the following link to preview, print and pay this invoice: ${object._context.get('edi_web_url_view')} -Please note that this invoice has to be paid before ${object.date_due} +Please note that this invoice has to be paid before ${object.date_due or ''} Regards, From 2357eb562e96c563793cfd4b1c34f9bfe87520dc Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Thu, 18 Aug 2011 17:36:04 +0200 Subject: [PATCH 021/265] [FIX] document_ftp: avoid calling res.users.read() with too few arguments (it's broken, pending fix) bzr revid: odo@openerp.com-20110818153604-gefze43wp1u63j02 --- addons/document_ftp/test_easyftp.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/addons/document_ftp/test_easyftp.py b/addons/document_ftp/test_easyftp.py index ac2cd722478..74890b1a333 100644 --- a/addons/document_ftp/test_easyftp.py +++ b/addons/document_ftp/test_easyftp.py @@ -36,13 +36,13 @@ def get_plain_ftp(timeout=10.0): def get_ftp_login(cr, uid, ormobj): ftp = get_plain_ftp() - user = ormobj.pool.get('res.users').read(cr, uid, uid) - passwd = user.get('password','') + user = ormobj.pool.get('res.users').browse(cr, uid, uid) + passwd = user.password or '' if passwd.startswith("$1$"): - # md5 by base crypt. We cannot decode, wild guess + # md5 by base crypt. We cannot decode, wild guess # that passwd = login - passwd = user.get('login', '') - ftp.login(user.get('login',''), passwd) + passwd = user.login + ftp.login(user.login, passwd) ftp.cwd("/" + cr.dbname) return ftp From b46c2554467b719fdef76c3a14a79878919f10bb Mon Sep 17 00:00:00 2001 From: "Harry (OpenERP)" Date: Fri, 26 Aug 2011 17:55:19 +0530 Subject: [PATCH 022/265] [FIX] account: email template of account invoice bzr revid: hmo@tinyerp.com-20110826122519-3bk1phpg3jtw5mfn --- addons/account/edi_invoice_action_data.xml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/addons/account/edi_invoice_action_data.xml b/addons/account/edi_invoice_action_data.xml index 95633aea21b..dc6cca4fade 100644 --- a/addons/account/edi_invoice_action_data.xml +++ b/addons/account/edi_invoice_action_data.xml @@ -3,7 +3,7 @@ - context.update({'edi_web_url_view': '%s/edi/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])}) + context.update({'edi_web_invoice_url_view': '%s/edi/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').generate_mail(cr, uid, self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account', 'email_template_edi_invoice')[1], @@ -34,13 +34,13 @@ if not object.partner_id.opt_out: self.pool.get('email.template').generate_mail( <p> Hello ${object.address_invoice_id.name and ' ' or ''},</p> <p> You can click on the following link to preview, print and pay invoice: - <a href="${object._context.get('edi_web_url_view')}">${object._context.get('edi_web_url_view')}</a> + <a href="${object._context.get('edi_web_invoice_url_view')}">$${object._context.get('edi_web_invoice_url_view')} </a> </p> <p style="border-left: 1px solid #8e0000; margin-left: 30px;"> <strong>REFERENCES</strong><br /> Invoice number: <strong>${object.number}</strong><br /> Invoice amount: <strong>${object.amount_total} ${object.currency_id.name}</strong><br /> Invoice date: ${object.date_invoice or 'n/a'}<br /> Order reference: ${object.origin or 'n/a'}<br /> Your contact: <a href="mailto:${object.user_id.user_email or ''}?subject=Invoice%20${object.number}">${object.user_id.name}</a></p> -${object.company_id.paypal_account and '<p>It is possible to pay with Paypal: <br/> <a href=/"https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business='+object.company_id.paypal_account+'&item_name=OpenERP%20Invoice%20'+object.number and object.number.replace('/','%2f') or ''+'&invoice='+object.number and object.number.replace('/','%2f') or ''+'&amount='+object.amount_total+'&currency_code='+object.currency_id.name+'&button_subtype=services&no_note=1&bn=OpenERP_Invoice_PayNow_'+object.currency_id.name+'/"><img src=/"https://www.paypalobjects.com/en_US/i/btn/btn_paynowCC_LG.gif/" style=/"margin-left: 100px; border: 0px; padding: 1px; text-decoration: none;/"/></a> </p>'} +${object.company_id.paypal_account and "<p>It is possible to pay with Paypal: <br/> <a href=\"https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=%s&item_name=OpenERP%%20Invoice%%20%s&invoice=%s&amount=%s&currency_code=%s&button_subtype=services&no_note=1&bn=OpenERP_Invoice_PayNow_%s\"><img src=\"https://www.paypalobjects.com/en_US/i/btn/btn_paynowCC_LG.gif\" style=\"margin-left: 100px; border: 0px; padding: 1px; text-decoration: none;\"/></a> </p>"%(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) or ''} <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=Invoice%20${object.number}">${object.user_id.name}</a></div> <div> </div> </div> </div> <p> </p> @@ -49,15 +49,15 @@ Hello ${object.address_invoice_id.name and ' ' or ''}, You can click on the following link to preview, print and pay invoice: - ${object._context.get('edi_web_url_view')} + ${object._context.get('edi_web_invoice_url_view') or 'n/a'} Invoice Number: *${object.number}* Amount: *${object.amount_total} ${object.currency_id.name}* Invoice date: ${object.date_invoice or 'n/a'} Order reference: ${object.origin or 'n/a'} -Your contact: ${object.user_id.name} <${object.user_id.user_email or ''}> +Your contact: ${object.user_id.name} ${object.user_id.user_email and '<%s>'%(object.user_id.user_email) or ''} -${object.company_id.paypal_account and 'It is possible to pay with Paypal: https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business='+object.company_id.paypal_account+'&item_name=OpenERP%20Invoice%20'+object.number and object.number.replace('/','%2f') or ''+'&invoice='+object.number and object.number.replace('/','%2f') or ''+'&amount='+object.amount_total+'&currency_code='+object.currency_id.name+'&button_subtype=services&no_note=1&bn=OpenERP_Invoice_PayNow_'+object.currency_id.name} +${object.company_id.paypal_account and "It is possible to pay with Paypal: https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=%s&item_name=OpenERP%%20Invoice%%20%s&invoice=%s&amount=%s&currency_code=%s&button_subtype=services&no_note=1&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) or ''} If you have any question, do not hesitate to reply directly to this e-mail. @@ -65,7 +65,7 @@ Thank you for choosing our service! -- ${object.company_id.name} -Contact: ${object.user_id.name} <${object.user_id.user_email or ''}> +Contact: ${object.user_id.name} ${object.user_id.user_email and '<%s>'%(object.user_id.user_email) or ''} mako Mail Template of Invoice For EDI Document From 333b5aa3e2bdcfdae54f2fcc9e9be3d0574dbd85 Mon Sep 17 00:00:00 2001 From: "Hardik Ansodariy (OpenERP)" Date: Fri, 26 Aug 2011 18:39:29 +0530 Subject: [PATCH 023/265] [IMP] edi sale order with email template bzr revid: han@tinyerp.com-20110826130929-q0n8o9gdy8a6ssf0 --- addons/sale/__init__.py | 2 +- addons/sale/__openerp__.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/sale/__init__.py b/addons/sale/__init__.py index 3c7af56e808..6361fea3a0b 100644 --- a/addons/sale/__init__.py +++ b/addons/sale/__init__.py @@ -29,5 +29,5 @@ import sale_installer import wizard import report import company - +import edi_sale_order # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale/__openerp__.py b/addons/sale/__openerp__.py index c983edc881e..4dccadc34e2 100644 --- a/addons/sale/__openerp__.py +++ b/addons/sale/__openerp__.py @@ -85,6 +85,7 @@ Dashboard for Sales Manager that includes: 'stock_view.xml', 'board_sale_view.xml', 'process/sale_process.xml', + 'edi_sale_order_data.xml', ], 'demo_xml': ['sale_demo.xml'], 'test': [ From 1ed41c0578aa05ef67709a2d9520a8eae3b25a3c Mon Sep 17 00:00:00 2001 From: "Hardik Ansodariy (OpenERP)" Date: Fri, 26 Aug 2011 18:40:37 +0530 Subject: [PATCH 024/265] [imp] edi sale order bzr revid: han@tinyerp.com-20110826131037-fr63ylzjd8ev1l5j --- addons/sale/edi_sale_order.py | 195 ++++++++++++++++++++++++++++ addons/sale/edi_sale_order_data.xml | 51 ++++++++ 2 files changed, 246 insertions(+) create mode 100644 addons/sale/edi_sale_order.py create mode 100644 addons/sale/edi_sale_order_data.xml diff --git a/addons/sale/edi_sale_order.py b/addons/sale/edi_sale_order.py new file mode 100644 index 00000000000..266727c0ae5 --- /dev/null +++ b/addons/sale/edi_sale_order.py @@ -0,0 +1,195 @@ +# -*- 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 +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 = { + 'name': True, + 'shop_id': True, + 'origin': True, + 'amount_total': True, + 'date_order': True, + 'create_date': True, + 'date_confirm': True, + 'partner_id': True, + 'partner_invoice_id': True, + 'partner_order_id': True, + 'partner_shipping_id': True, + 'incoterm': True, + 'picking_policy': True, + 'order_policy': True, + 'pricelist_id': True, + 'project_id': True, + 'invoice_quantity': True, + 'order_line': { + 'name': True, + 'sequence': True, + 'product_id': True, + 'invoiced': True, + 'procurement_id': True, + 'price_unit': True, + 'type': True, + 'price_subtotal': True, + 'tax_id': True, + 'address_allotment_id': True, + 'product_uom': True, + 'product_uom_qty': True, + 'product_uos': True, + 'notes': True, + + }, + 'shipped': True, + } + partner_pool = self.pool.get('res.partner') + partner_address_pool = self.pool.get('res.partner.address') + company_address_dict = { + 'street': True, + 'street2': True, + 'zip': True, + 'city': True, + 'state_id': True, + 'country_id': True, + 'email': True, + 'phone': True, + + } + 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) + if not edi_doc: + continue + edi_doc = edi_doc[0] + + # Add company info and address + res = partner_pool.address_get(cr, uid, [order.shop_id.company_id.partner_id.id], ['contact', 'order']) + contact_addr_id = res['contact'] + invoice_addr_id = res['order'] + + address = partner_address_pool.browse(cr, uid, invoice_addr_id, context=context) + edi_company_address_dict = {} + for key, value in company_address_dict.items(): + if not value: + continue + address_rec = getattr(address, key) + if not address_rec: + continue + if key.endswith('_id'): + address_rec = self.edi_m2o(cr, uid, address_rec, context=context) + + edi_company_address_dict[key] = address_rec + + edi_doc.update({ + 'company_address': edi_company_address_dict, + #'company_logo': inv_comp.logo,#TODO + #'paid': inv_comp.paid, #TODO + }) + edi_doc_list.append(edi_doc) + return edi_doc_list + + def edi_import(self, cr, uid, edi_document, context=None): + + partner_pool = self.pool.get('res.partner') + partner_address_pool = self.pool.get('res.partner.address') + model_data_pool = self.pool.get('ir.model.data') + product_pool = self.pool.get('product.product') + product_categ_pool = self.pool.get('product.category') + company_pool = self.pool.get('res.company') + country_pool = self.pool.get('res.country') + state_pool = self.pool.get('res.country.state') + + tax_id = [] + account_id = [] + partner_id = None + company_id = None + if context is None: + context = {} + + # import company as a new partner, if type==in then supplier=1, else customer=1 + # partner_id field is modified to point to the new partner + # company_address data used to add address to new partner + edi_company_address = edi_document['company_address'] + edi_partner_id = edi_document['partner_id'] + company_name = edi_document['company_id'][1] + state_id = edi_company_address.get('state_id', False) + state_name = state_id and state_id[1] + country_id = edi_company_address.get('country_id', False) + country_name = country_id and country_id[1] + + country_id = country_name and self.edi_import_relation(cr, uid, 'res.country', country_name, context=context) or False + state_id = state_name and self.edi_import_relation(cr, uid, 'res.country.state', state_name, + values={'country_id': country_id, 'code': state_name}, context=context) or False + address_value = { + 'street': edi_company_address.get('street', False), + 'street2': edi_company_address.get('street2', False), + 'zip': edi_company_address.get('zip', False), + 'city': edi_company_address.get('city', False), + 'state_id': state_id, + 'country_id': country_id, + 'email': edi_company_address.get('email', False), + 'phone': edi_company_address.get('phone', False), + + } + + partner_value = {'name': company_name} + partner_value.update({'customer': True, 'supplier': False}) + + partner_id = partner_pool.create(cr, uid, partner_value, context=context) + address_value.update({'partner_id': partner_id}) + address_id = partner_address_pool.create(cr, uid, address_value, context=context) + partner_address = partner_address_pool.browse(cr, uid, [address_id], context=context) + partner_address_id = self.edi_o2m(cr, uid, partner_address, context=context) + partner = partner_pool.browse(cr, uid, partner_id, context=context) + edi_document['partner_id'] = self.edi_m2o(cr, uid, partner, context=context) + edi_document.update({ + 'partner_invoice_id': partner_address_id, + 'partner_order_id': partner_address_id, + 'partner_shipping_id': partner_address_id, + #'product_uom_qty': edi_document['order_line'][0]['product_qty'], + 'delay': 10, + }) + # all fields are converted for sale order import so unnecessary fields are deleted + del edi_document['order_line'][0]['date_planned'] + del edi_document['order_line'][0]['product_qty'] + del edi_document['date_approve'] + del edi_document['validator'] + + del edi_document['location_id'] + del edi_document['partner_address_id'] + del edi_document['company_address'] + del edi_document['company_id'] + del edi_document['warehouse_id'] + 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 new file mode 100644 index 00000000000..70b6adae397 --- /dev/null +++ b/addons/sale/edi_sale_order_data.xml @@ -0,0 +1,51 @@ + + + + + + context.update({'edi_web_url_view': '%s/edi/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').generate_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 + + + + + + + + + + + + ${object.company_id.name} - Sale Order ${object.name} + ${object.partner_invoice_id.email} + + True + +Hello ${object.partner_invoice_id.name}, + +We just registered the sale order ${object.name} for ${object.amount_total} for your company ${object.partner_id.name}. +You can click on the following link to preview. + + ${object._context.get('edi_web_url_view')} + + confirmed on ${object.date_confirm} + +Regards, + + mako + Mail Template of Sale Order For EDI Document + sale.order + ${object.user_id.email or ''} + + + From 39b40d789a2d23f985923447a8ce3d9f55b8c6f8 Mon Sep 17 00:00:00 2001 From: "Harry (OpenERP)" Date: Mon, 29 Aug 2011 13:09:56 +0530 Subject: [PATCH 025/265] [IMP] account: email template of account invoice bzr revid: hmo@tinyerp.com-20110829073956-vabkylrsvnklb8hw --- addons/account/edi_invoice_action_data.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/account/edi_invoice_action_data.xml b/addons/account/edi_invoice_action_data.xml index dc6cca4fade..fb89e585195 100644 --- a/addons/account/edi_invoice_action_data.xml +++ b/addons/account/edi_invoice_action_data.xml @@ -33,8 +33,8 @@ if not object.partner_id.opt_out: self.pool.get('email.template').generate_mail( <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.address_invoice_id.name and ' ' or ''},</p> -<p> You can click on the following link to preview, print and pay invoice: - <a href="${object._context.get('edi_web_invoice_url_view')}">$${object._context.get('edi_web_invoice_url_view')} </a> +<p> You can click on the following link to preview, print and pay invoice: <br/> + <a href="${object._context.get('edi_web_invoice_url_view')}">${object._context.get('edi_web_invoice_url_view')} </a> </p> From 37263ec7accdb62e33f686c566ac4db81bdf46c3 Mon Sep 17 00:00:00 2001 From: "Hardik Ansodariy (OpenERP)" Date: Mon, 29 Aug 2011 15:51:27 +0530 Subject: [PATCH 026/265] [merge] edi sale order with yml bzr revid: han@tinyerp.com-20110829102127-nkr1muz2e1jsu6xh --- addons/purchase/__init__.py | 1 + addons/sale/__openerp__.py | 1 + addons/sale/edi_sale_order.py | 4 +-- addons/sale/test/edi_sale_order.yml | 51 +++++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 addons/sale/test/edi_sale_order.yml diff --git a/addons/purchase/__init__.py b/addons/purchase/__init__.py index 301e32ebca9..87e13840e0d 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 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale/__openerp__.py b/addons/sale/__openerp__.py index 4dccadc34e2..0e3ec9ed075 100644 --- a/addons/sale/__openerp__.py +++ b/addons/sale/__openerp__.py @@ -100,6 +100,7 @@ Dashboard for Sales Manager that includes: 'test/invoice_on_ordered_qty.yml', 'test/invoice_on_shipped_qty.yml', 'test/sale_report.yml', + 'test/edi_sale_order.yml', ], 'installable': True, 'active': False, diff --git a/addons/sale/edi_sale_order.py b/addons/sale/edi_sale_order.py index 266727c0ae5..ea1a56b1ed4 100644 --- a/addons/sale/edi_sale_order.py +++ b/addons/sale/edi_sale_order.py @@ -38,8 +38,6 @@ class sale_order(osv.osv, ir_edi.edi): 'date_confirm': True, 'partner_id': True, 'partner_invoice_id': True, - 'partner_order_id': True, - 'partner_shipping_id': True, 'incoterm': True, 'picking_policy': True, 'order_policy': True, @@ -163,7 +161,7 @@ class sale_order(osv.osv, ir_edi.edi): address_value.update({'partner_id': partner_id}) address_id = partner_address_pool.create(cr, uid, address_value, context=context) partner_address = partner_address_pool.browse(cr, uid, [address_id], context=context) - partner_address_id = self.edi_o2m(cr, uid, partner_address, context=context) + partner_address_id = self.edi_o2m(cr, uid, [partner_address], context=context) partner = partner_pool.browse(cr, uid, partner_id, context=context) edi_document['partner_id'] = self.edi_m2o(cr, uid, partner, context=context) edi_document.update({ diff --git a/addons/sale/test/edi_sale_order.yml b/addons/sale/test/edi_sale_order.yml new file mode 100644 index 00000000000..dba200f4cfa --- /dev/null +++ b/addons/sale/test/edi_sale_order.yml @@ -0,0 +1,51 @@ +- + I create a partner which is a my customer +- + !record {model: res.partner, id: res_partner_test22}: + name: Junjun wala + supplier: False + customer: True + opt_out: False +- + 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_11 + partner_order_id: base.res_partner_address_11 + partner_shipping_id: base.res_partner_address_11 + 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' +- + I Open 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) + +- + I Tesing of EDI functionality. First I export Sale Order from my company than import that Order into customer company +- + !python {model: ir.edi.document}: | + import json + invoice_pool = self.pool.get('sale.order') + orders = invoice_pool.browse(cr, uid, ref("sale_order_test")) + + tokens = self.export_edi(cr, uid, [orders]) + assert tokens, 'Token is not generated' + document = self.get_document(cr, uid, tokens[0]) + document = json.loads(document) + document[0]["__model"] = "purchase.order" + document = json.dumps(document) + a = self.import_edi(cr, uid, edi_document = document) + assert a, 'Invoice is not imported' + + From 7d33fcfa66a383b963e7c46fbd768bb07444476a Mon Sep 17 00:00:00 2001 From: "Amit Parmar (OpenERP)" Date: Mon, 29 Aug 2011 16:13:27 +0530 Subject: [PATCH 027/265] [IMP] develop a edi purchase order import and export bzr revid: aar@tinyerp.com-20110829104327-tikju8eodq6q6901 --- addons/purchase/__init__.py | 2 +- addons/purchase/__openerp__.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/addons/purchase/__init__.py b/addons/purchase/__init__.py index 301e32ebca9..ddd572d8e81 100644 --- a/addons/purchase/__init__.py +++ b/addons/purchase/__init__.py @@ -26,6 +26,6 @@ import wizard import report import stock import company - +import edi_purchase_order # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/purchase/__openerp__.py b/addons/purchase/__openerp__.py index 975754dd5fe..f360d881cf3 100644 --- a/addons/purchase/__openerp__.py +++ b/addons/purchase/__openerp__.py @@ -58,6 +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', ], 'test': [ 'test/purchase_from_order.yml', @@ -66,6 +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', ], 'demo': ['purchase_demo.xml'], 'installable': True, From d6b7e8abb72acd533e511ef0127371133ab5aee7 Mon Sep 17 00:00:00 2001 From: "Amit Parmar (OpenERP)" Date: Mon, 29 Aug 2011 16:14:21 +0530 Subject: [PATCH 028/265] [IMP] develop a edi purchase order import and export bzr revid: aar@tinyerp.com-20110829104421-6562nvcyulzl4o84 --- addons/purchase/edi_purchase_order.py | 190 ++++++++++++++++++++ addons/purchase/edi_purchase_order_data.xml | 51 ++++++ addons/purchase/test/edi_purchase_order.yml | 31 ++++ 3 files changed, 272 insertions(+) create mode 100644 addons/purchase/edi_purchase_order.py create mode 100644 addons/purchase/edi_purchase_order_data.xml create mode 100644 addons/purchase/test/edi_purchase_order.yml diff --git a/addons/purchase/edi_purchase_order.py b/addons/purchase/edi_purchase_order.py new file mode 100644 index 00000000000..1ea43afbb09 --- /dev/null +++ b/addons/purchase/edi_purchase_order.py @@ -0,0 +1,190 @@ +# -*- 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 + +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 supplier or customer invoice""" + edi_struct = { + 'name': True, + 'origin': True, + 'date_order': True, + 'date_approve': True, + 'partner_id': True, + 'partner_address_id': True, + 'dest_address_id': True, + 'warehouse_id': True, + 'location_id': True, + 'pricelist_id': True, + 'validator' : True, + 'order_line': { + 'name': True, + 'product_qty': True, + 'date_planned': True, + 'taxes_id': True, + 'product_uom': True, + 'product_id': True, + 'move_dest_id': True, + 'price_unit': True, + 'order_id': True, + 'invoiced': True, + 'price_subtotal': True, + }, + 'invoice_ids': True, + 'shipped': True, + 'company_id': True, + } + partner_pool = self.pool.get('res.partner') + partner_address_pool = self.pool.get('res.partner.address') + company_address_dict = { + 'street': True, + 'street2': True, + 'zip': True, + 'city': True, + 'state_id': True, + 'country_id': True, + 'email': True, + 'phone': True, + + } + 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] + + # Add company info and address + res = partner_pool.address_get(cr, uid, [order.company_id.partner_id.id], ['contact', 'order']) + contact_addr_id = res['contact'] + invoice_addr_id = res['order'] + + address = partner_address_pool.browse(cr, uid, invoice_addr_id, context=context) + edi_company_address_dict = {} + for key, value in company_address_dict.items(): + if not value: + continue + address_rec = getattr(address, key) + if not address_rec: + continue + if key.endswith('_id'): + address_rec = self.edi_m2o(cr, uid, address_rec, context=context) + edi_company_address_dict[key] = address_rec + + edi_doc.update({ + 'company_address': edi_company_address_dict, + #'company_logo': inv_comp.logo,#TODO + #'paid': inv_comp.paid, #TODO + }) + edi_doc_list.append(edi_doc) + return edi_doc_list + + def edi_import(self, cr, uid, edi_document, context=None): + + partner_pool = self.pool.get('res.partner') + partner_address_pool = self.pool.get('res.partner.address') + model_data_pool = self.pool.get('ir.model.data') + product_pool = self.pool.get('product.product') + product_categ_pool = self.pool.get('product.category') + company_pool = self.pool.get('res.company') + country_pool = self.pool.get('res.country') + state_pool = self.pool.get('res.country.state') + account_journal_pool = self.pool.get('account.journal') + invoice_line_pool = self.pool.get('account.invoice.line') + account_pool = self.pool.get('account.account') + stock = self.pool.get('stock.location') + + tax_id = [] + account_id = [] + partner_id = None + company_id = None + if context is None: + context = {} + + # import company as a new partner, if type==in then supplier=1, else customer=1 + # partner_id field is modified to point to the new partner + # company_address data used to add address to new partner + edi_company_address = edi_document['company_address'] + edi_partner_id = edi_document['partner_id'] + company_name = edi_document['shop_id'][1] + state_id = edi_company_address.get('state_id', False) + state_name = state_id and state_id[1] + country_id = edi_company_address.get('country_id', False) + country_name = country_id and country_id[1] + + country_id = country_name and self.edi_import_relation(cr, uid, 'res.country', country_name, context=context) or False + state_id = state_name and self.edi_import_relation(cr, uid, 'res.country.state', state_name, + values={'country_id': country_id, 'code': state_name}, context=context) or False + address_value = { + 'street': edi_company_address.get('street', False), + 'street2': edi_company_address.get('street2', False), + 'zip': edi_company_address.get('zip', False), + 'city': edi_company_address.get('city', False), + 'state_id': state_id, + 'country_id': country_id, + 'email': edi_company_address.get('email', False), + 'phone': edi_company_address.get('phone', False), + + } + partner_value = {'name': company_name} + partner_value.update({'customer': False, 'supplier': True}) + partner_id = partner_pool.create(cr, uid, partner_value, context=context) + address_value.update({'partner_id': partner_id}) + address_id = partner_address_pool.create(cr, uid, address_value, context=context) + partner_address = partner_address_pool.browse(cr, uid, address_id, context=context) + edi_document.update({'partner_address_id':self.edi_m2o(cr, uid, partner_address, context=context)}) + partner = partner_pool.browse(cr, uid, partner_id, context=context) + edi_document['partner_id'] = self.edi_m2o(cr, uid, partner, context=context) + location_id = stock.search(cr, uid,[('name','=','Stock')]) + location = stock.browse(cr, uid, location_id[0]) + edi_document.update({'dest_address_id': edi_document['partner_shipping_id'],'location_id': self.edi_m2o(cr, uid, location, context=context)}) + + for line in range(len(edi_document['order_line'])): + product_qty = edi_document['order_line'][line]['product_uom_qty'] + edi_document['order_line'][line].update({'product_qty': product_qty}) + + # all fields are converted for purchase order import so unnecessary fields are deleted + delete_key = ['sequence','procurement_id','product_uom_qty','company_address','shop_id','create_date','picking_policy','order_policy','partner_order_id','partner_shipping_id','invoice_quantity','partner_invoice_id','price_subtotal','date_confirm'] + for key in delete_key: + if edi_document.has_key(key): + del edi_document[key] + else: + for document in edi_document['order_line']: + if document.has_key(key): + del document[key] + + print edi_document + 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 new file mode 100644 index 00000000000..ab29119bed1 --- /dev/null +++ b/addons/purchase/edi_purchase_order_data.xml @@ -0,0 +1,51 @@ + + + + + + context.update({'edi_web_url_view': '%s/edi/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])}) +self.pool.get('email.template').generate_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 + + + + + + + + + + + + ${object.company_id.name} - Purchase Order ${object.name} + ${object.partner_address_id.email} + + True + +Hello ${object.partner_address_id.name}, + +We just registered the purchase order ${object.name} for ${object.amount_total} for your company ${object.partner_id.name}. +You can click on the following link to preview. + + ${object._context.get('edi_web_url_view')} + + Confirmed on ${object.date_approve} + +Regards, + + mako + Mail Template of Purchase Order For EDI Document + purchase.order + + + + diff --git a/addons/purchase/test/edi_purchase_order.yml b/addons/purchase/test/edi_purchase_order.yml new file mode 100644 index 00000000000..2901aeb5e9a --- /dev/null +++ b/addons/purchase/test/edi_purchase_order.yml @@ -0,0 +1,31 @@ +- + I Tesing of EDI functionality. First I export customer invoice from my company than import that invoice into customer company +- + !python {model: ir.edi.document}: | + import json + order_pool = self.pool.get('purchase.order') + purchase_id = order_pool.search(cr, uid, []) + orders = order_pool.browse(cr, uid, purchase_id) + + if type(orders).__name__ == 'list': + tokens = self.export_edi(cr, uid, orders) + for token in tokens: + document = self.get_document(cr, uid, token) + document = json.loads(document) + edi_doc = [] + for doc in document: + doc.update({'__model': 'sale.order'}) + edi_doc.append(doc) + a = self.import_edi(cr, uid, edi_document = json.dumps(edi_doc)) + else: + tokens = self.export_edi(cr, uid, orders) + for token in tokens: + document = self.get_document(cr, uid, token) + document = json.loads(document) + edi_doc = [] + for doc in document: + doc.update({'__model': 'sale.order'}) + edi_doc.append(doc) + a = self.import_edi(cr, uid, edi_document = json.dumps(edi_doc)) + + From 5ffef81c62fbe2bf2056d65119dadc4d30a2b0e3 Mon Sep 17 00:00:00 2001 From: "Amit Parmar (OpenERP)" Date: Tue, 30 Aug 2011 11:04:53 +0530 Subject: [PATCH 029/265] [IMP] improve the edi purchase order import and export testing bzr revid: aar@tinyerp.com-20110830053453-ecsqohdm12kp6xao --- addons/purchase/__openerp__.py | 3 +- addons/purchase/edi_purchase_order.py | 4 +- addons/purchase/edi_purchase_order_data.xml | 2 +- addons/purchase/test/edi_purchase_order.yml | 71 +++++++++++++-------- 4 files changed, 47 insertions(+), 33 deletions(-) diff --git a/addons/purchase/__openerp__.py b/addons/purchase/__openerp__.py index f360d881cf3..21a9184cbb3 100644 --- a/addons/purchase/__openerp__.py +++ b/addons/purchase/__openerp__.py @@ -59,6 +59,7 @@ Dashboard for purchase management that includes: 'report/purchase_report_view.xml', 'board_purchase_view.xml', 'edi_purchase_order_data.xml', + ], 'test': [ 'test/purchase_from_order.yml', @@ -67,7 +68,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_purchase_order.py b/addons/purchase/edi_purchase_order.py index 1ea43afbb09..8621e33f15b 100644 --- a/addons/purchase/edi_purchase_order.py +++ b/addons/purchase/edi_purchase_order.py @@ -118,14 +118,13 @@ class purchase_order(osv.osv, ir_edi.edi): invoice_line_pool = self.pool.get('account.invoice.line') account_pool = self.pool.get('account.account') stock = self.pool.get('stock.location') - tax_id = [] account_id = [] partner_id = None company_id = None if context is None: context = {} - + print edi_document # import company as a new partner, if type==in then supplier=1, else customer=1 # partner_id field is modified to point to the new partner # company_address data used to add address to new partner @@ -178,7 +177,6 @@ class purchase_order(osv.osv, ir_edi.edi): if document.has_key(key): del document[key] - print edi_document return super(purchase_order,self).edi_import(cr, uid, edi_document, context=context) purchase_order() diff --git a/addons/purchase/edi_purchase_order_data.xml b/addons/purchase/edi_purchase_order_data.xml index ab29119bed1..937045d3380 100644 --- a/addons/purchase/edi_purchase_order_data.xml +++ b/addons/purchase/edi_purchase_order_data.xml @@ -45,7 +45,7 @@ Regards, mako Mail Template of Purchase Order For EDI Document purchase.order - + ${object.user_id.user_email or ''} diff --git a/addons/purchase/test/edi_purchase_order.yml b/addons/purchase/test/edi_purchase_order.yml index 2901aeb5e9a..e6ee0c76840 100644 --- a/addons/purchase/test/edi_purchase_order.yml +++ b/addons/purchase/test/edi_purchase_order.yml @@ -1,31 +1,46 @@ - - I Tesing of EDI functionality. First I export customer invoice from my company than import that invoice into customer company + I create a partner which is a my customer +- + !record {model: res.partner, id: res_partner_test20}: + name: jones white + supplier: False + customer: True + opt_out: False +- + I create one Purchase Order +- + !record {model: purchase.order, id: purchase_order_test}: + partner_id: res_partner_test22 + partner_address_id: base.res_partner_address_11 + location_id: stock.stock_location_3 + 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' +- + I Open the sale 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) - !python {model: ir.edi.document}: | - import json - order_pool = self.pool.get('purchase.order') - purchase_id = order_pool.search(cr, uid, []) - orders = order_pool.browse(cr, uid, purchase_id) - - if type(orders).__name__ == 'list': - tokens = self.export_edi(cr, uid, orders) - for token in tokens: - document = self.get_document(cr, uid, token) - document = json.loads(document) - edi_doc = [] - for doc in document: - doc.update({'__model': 'sale.order'}) - edi_doc.append(doc) - a = self.import_edi(cr, uid, edi_document = json.dumps(edi_doc)) - else: - tokens = self.export_edi(cr, uid, orders) - for token in tokens: - document = self.get_document(cr, uid, token) - document = json.loads(document) - edi_doc = [] - for doc in document: - doc.update({'__model': 'sale.order'}) - edi_doc.append(doc) - a = self.import_edi(cr, uid, edi_document = json.dumps(edi_doc)) - - + order_pool = self.pool.get('purchase.order') + purchase_id = order_pool.search(cr, uid, ref("purchase_order_test")) + orders = order_pool.browse(cr, uid, purchase_id) + import json + + tokens = self.export_edi(cr, uid, [orders]) + assert tokens, 'Token is not generated' + document = self.get_document(cr, uid, tokens[0]) + document = json.loads(document) + document[0]["__model"] = "purchase.order" + document = json.dumps(document) + a = self.import_edi(cr, uid, edi_document = document) + From 78f10b2fe38236d6c6da452d4e2d3d00d72ef407 Mon Sep 17 00:00:00 2001 From: "Amit Parmar (OpenERP)" Date: Tue, 30 Aug 2011 18:54:31 +0530 Subject: [PATCH 030/265] [IMP] improve the email template bzr revid: aar@tinyerp.com-20110830132431-4zsut2pz3fudcb5g --- addons/purchase/edi_purchase_order.py | 4 ++ addons/purchase/edi_purchase_order_data.xml | 45 ++++++++++++++++----- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/addons/purchase/edi_purchase_order.py b/addons/purchase/edi_purchase_order.py index 8621e33f15b..2d719300b8d 100644 --- a/addons/purchase/edi_purchase_order.py +++ b/addons/purchase/edi_purchase_order.py @@ -41,6 +41,9 @@ class purchase_order(osv.osv, ir_edi.edi): 'location_id': True, 'pricelist_id': True, 'validator' : True, + 'amount_tax': True, + 'amount_total': True, + 'amount_untaxed': True, 'order_line': { 'name': True, 'product_qty': True, @@ -102,6 +105,7 @@ class purchase_order(osv.osv, ir_edi.edi): #'paid': inv_comp.paid, #TODO }) edi_doc_list.append(edi_doc) + print "??????????????????????",edi_doc_list return edi_doc_list def edi_import(self, cr, uid, edi_document, context=None): diff --git a/addons/purchase/edi_purchase_order_data.xml b/addons/purchase/edi_purchase_order_data.xml index 937045d3380..7351afe4a3f 100644 --- a/addons/purchase/edi_purchase_order_data.xml +++ b/addons/purchase/edi_purchase_order_data.xml @@ -4,7 +4,7 @@ context.update({'edi_web_url_view': '%s/edi/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])}) -self.pool.get('email.template').generate_mail(cr, +if not object.partner_id.opt_out: self.pool.get('email.template').generate_mail(cr, uid, self.pool.get('ir.model.data').get_object_reference(cr, uid, 'purchase', 'email_template_edi_purchase')[1], [object.id], @@ -30,22 +30,47 @@ self.pool.get('email.template').generate_mail(cr, ${object.partner_address_id.email} True + +<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, print and pay invoice: <br/> + <a href="${object._context.get('edi_web_url_view')}">${object._context.get('edi_web_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 /> Confirm date: ${object.date_approve or 'n/a'}<br /> Your contact: <a href="mailto:${object.validator.user_email or ''}?subject=Order%20${object.name}">${object.validator.name}</a></p> + +${object.company_id.paypal_account and "<p>It is possible to pay with Paypal: <br/> <a href=\"https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=%s&item_name=OpenERP%%20Invoice%%20%s&invoice=%s&amount=%s&button_subtype=services&no_note=1&bn=OpenERP_Invoice_PayNow_%s\"><img src=\"https://www.paypalobjects.com/en_US/i/btn/btn_paynowCC_LG.gif\" style=\"margin-left: 100px; border: 0px; padding: 1px; text-decoration: none;\"/></a> </p>"%(object.company_id.paypal_account, object.name and object.name.replace('/','%2f') or '', object.name and object.name.replace('/','%2f') or '', object.amount_total) or ''} + +<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}, +Hello ${object.partner_address_id.name and ' ' or ''}, -We just registered the purchase order ${object.name} for ${object.amount_total} for your company ${object.partner_id.name}. -You can click on the following link to preview. +You can click on the following link to preview, print and pay invoice: - ${object._context.get('edi_web_url_view')} + ${object._context.get('edi_web_url_view') or 'n/a'} - Confirmed on ${object.date_approve} - -Regards, - +Order Number: *${object.name}* +Amount: *${object.amount_total}* +Approve date: ${object.date_approve or 'n/a'} +Your contact: ${object.validator.name} ${object.validator.user_email and '<%s>'%(object.validator.user_email) or ''} + +${object.company_id.paypal_account and "It is possible to pay with Paypal: https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=%s&item_name=OpenERP%%20Invoice%%20%s&invoice=%s&amount=%s&currency_code=%s&button_subtype=services&no_note=1&bn=OpenERP_Invoice_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) 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 ''} + mako Mail Template of Purchase Order For EDI Document purchase.order - ${object.user_id.user_email or ''} + ${object.validator.user_email or ''} From 3a581f8a27a1684218c3d98688f80b8cef5bfee9 Mon Sep 17 00:00:00 2001 From: "Amit Parmar (OpenERP)" Date: Wed, 7 Sep 2011 13:09:25 +0530 Subject: [PATCH 031/265] [IMP] Develop a purchase order import and export functionality bzr revid: aar@tinyerp.com-20110907073925-p7akjs01643z4m2b --- addons/email_template/email_template.py | 4 +- addons/purchase/__openerp__.py | 4 +- addons/purchase/edi_purchase_order.py | 7 +- addons/purchase/test/edi_purchase_order.yml | 7 +- addons/sale/__init__.py | 2 +- addons/sale/__openerp__.py | 22 +-- addons/sale/edi_sale_order.py | 187 ++++++++++++++++++++ addons/sale/edi_sale_order_data.xml | 76 ++++++++ addons/sale/test/edi_sale_order.yml | 51 ++++++ 9 files changed, 340 insertions(+), 20 deletions(-) create mode 100644 addons/sale/edi_sale_order.py create mode 100644 addons/sale/edi_sale_order_data.xml create mode 100644 addons/sale/test/edi_sale_order.yml diff --git a/addons/email_template/email_template.py b/addons/email_template/email_template.py index aabc211df11..57ba74a49d4 100644 --- a/addons/email_template/email_template.py +++ b/addons/email_template/email_template.py @@ -570,7 +570,8 @@ This is useful for CRM leads for example"), # determine name of sender, either it is specified in email_id or we # use the account name - email_id = from_account['email_id'].strip() + print "////////////////////////",from_account + email_id = from_account['email_id'] email_from = re.findall(r'([^ ,<@]+@[^> ,]+)', email_id)[0] if email_from != email_id: # we should keep it all, name is probably specified in the address @@ -670,6 +671,7 @@ This is useful for CRM leads for example"), if context is None: context = {} template = self.browse(cursor, user, template_id, context=context) + print ">>>>>>>>>>>><<<<<<<<<<<<<<<<",template if not template: raise Exception("The requested template could not be loaded") result = True diff --git a/addons/purchase/__openerp__.py b/addons/purchase/__openerp__.py index 21a9184cbb3..ae4eaa3c6e6 100644 --- a/addons/purchase/__openerp__.py +++ b/addons/purchase/__openerp__.py @@ -59,7 +59,7 @@ Dashboard for purchase management that includes: 'report/purchase_report_view.xml', 'board_purchase_view.xml', 'edi_purchase_order_data.xml', - + #'test/edi_purchase_order.yml', ], 'test': [ 'test/purchase_from_order.yml', @@ -68,7 +68,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_purchase_order.py b/addons/purchase/edi_purchase_order.py index 2d719300b8d..605e29621b1 100644 --- a/addons/purchase/edi_purchase_order.py +++ b/addons/purchase/edi_purchase_order.py @@ -104,8 +104,9 @@ class purchase_order(osv.osv, ir_edi.edi): #'company_logo': inv_comp.logo,#TODO #'paid': inv_comp.paid, #TODO }) + edi_doc['__model'] = 'sale.order' edi_doc_list.append(edi_doc) - print "??????????????????????",edi_doc_list + return edi_doc_list def edi_import(self, cr, uid, edi_document, context=None): @@ -169,7 +170,7 @@ class purchase_order(osv.osv, ir_edi.edi): for line in range(len(edi_document['order_line'])): product_qty = edi_document['order_line'][line]['product_uom_qty'] - edi_document['order_line'][line].update({'product_qty': product_qty}) + edi_document['order_line'][line].update({'product_qty': product_qty,'taxes_id':edi_document['order_line'][line]['tax_id']}) # all fields are converted for purchase order import so unnecessary fields are deleted delete_key = ['sequence','procurement_id','product_uom_qty','company_address','shop_id','create_date','picking_policy','order_policy','partner_order_id','partner_shipping_id','invoice_quantity','partner_invoice_id','price_subtotal','date_confirm'] @@ -180,7 +181,7 @@ class purchase_order(osv.osv, ir_edi.edi): for document in edi_document['order_line']: if document.has_key(key): del document[key] - + print "in the edi_purchase import",edi_document return super(purchase_order,self).edi_import(cr, uid, edi_document, context=context) purchase_order() diff --git a/addons/purchase/test/edi_purchase_order.yml b/addons/purchase/test/edi_purchase_order.yml index e6ee0c76840..1fbc89db70a 100644 --- a/addons/purchase/test/edi_purchase_order.yml +++ b/addons/purchase/test/edi_purchase_order.yml @@ -10,16 +10,17 @@ I create one Purchase Order - !record {model: purchase.order, id: purchase_order_test}: - partner_id: res_partner_test22 + partner_id: res_partner_test20 partner_address_id: base.res_partner_address_11 location_id: stock.stock_location_3 pricelist_id: 1 order_line: - product_id: product.product_product_pc1 - product_uom_qty: 1.0 + product_qty: 1.0 product_uom: 1 price_unit: 150.0 name: 'basic pc' + date_planned: '2011-08-31' - I Open the sale order - @@ -40,7 +41,7 @@ assert tokens, 'Token is not generated' document = self.get_document(cr, uid, tokens[0]) document = json.loads(document) - document[0]["__model"] = "purchase.order" + document[0]["__model"] = "sale.order" document = json.dumps(document) a = self.import_edi(cr, uid, edi_document = document) diff --git a/addons/sale/__init__.py b/addons/sale/__init__.py index 3c7af56e808..6361fea3a0b 100644 --- a/addons/sale/__init__.py +++ b/addons/sale/__init__.py @@ -29,5 +29,5 @@ import sale_installer import wizard import report import company - +import edi_sale_order # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale/__openerp__.py b/addons/sale/__openerp__.py index c983edc881e..fa139377b40 100644 --- a/addons/sale/__openerp__.py +++ b/addons/sale/__openerp__.py @@ -85,20 +85,22 @@ Dashboard for Sales Manager that includes: 'stock_view.xml', 'board_sale_view.xml', 'process/sale_process.xml', + 'edi_sale_order_data.xml', ], 'demo_xml': ['sale_demo.xml'], 'test': [ 'test/data_test.yml', - 'test/manual_order_policy.yml', - 'test/prepaid_order_policy.yml', - 'test/picking_order_policy.yml', - 'test/postpaid_order_policy.yml', - 'test/advance_invoice.yml', - 'test/so_make_line_invoice.yml', - 'test/sale_procurement.yml', - 'test/invoice_on_ordered_qty.yml', - 'test/invoice_on_shipped_qty.yml', - 'test/sale_report.yml', + #'test/manual_order_policy.yml', + #'test/prepaid_order_policy.yml', + #'test/picking_order_policy.yml', + #'test/postpaid_order_policy.yml', + #'test/advance_invoice.yml', + #'test/so_make_line_invoice.yml', + #'test/sale_procurement.yml', + #'test/invoice_on_ordered_qty.yml', + #'test/invoice_on_shipped_qty.yml', + #'test/sale_report.yml', + #'test/edi_sale_order.yml', ], 'installable': True, 'active': False, diff --git a/addons/sale/edi_sale_order.py b/addons/sale/edi_sale_order.py new file mode 100644 index 00000000000..d33c4664992 --- /dev/null +++ b/addons/sale/edi_sale_order.py @@ -0,0 +1,187 @@ +# -*- 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 +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 = { + 'name': True, + 'shop_id': True, + 'origin': True, + 'amount_total': True, + 'date_order': True, + 'date_confirm': True, + 'partner_id': True, + 'partner_invoice_id': True, + 'pricelist_id': True, + 'company_id': True, + 'amount_tax': True, + 'amount_total': True, + 'amount_untaxed': True, + 'order_line': { + 'name': True, + 'product_id': True, + 'procurement_id': True, + 'price_unit': True, + 'price_subtotal': True, + 'tax_id': True, + 'product_uom': True, + 'product_uom_qty': True, + 'product_uos': True, + + }, + 'shipped': True, + } + partner_pool = self.pool.get('res.partner') + partner_address_pool = self.pool.get('res.partner.address') + company_address_dict = { + 'street': True, + 'street2': True, + 'zip': True, + 'city': True, + 'state_id': True, + 'country_id': True, + 'email': True, + 'phone': True, + + } + 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) + if not edi_doc: + continue + edi_doc = edi_doc[0] + + # Add company info and address + res = partner_pool.address_get(cr, uid, [order.shop_id.company_id.partner_id.id], ['contact', 'order']) + contact_addr_id = res['contact'] + invoice_addr_id = res['order'] + + address = partner_address_pool.browse(cr, uid, invoice_addr_id, context=context) + edi_company_address_dict = {} + for key, value in company_address_dict.items(): + if not value: + continue + address_rec = getattr(address, key) + if not address_rec: + continue + if key.endswith('_id'): + address_rec = self.edi_m2o(cr, uid, address_rec, context=context) + + edi_company_address_dict[key] = address_rec + + edi_doc.update({ + 'company_address': edi_company_address_dict, + #'company_logo': inv_comp.logo,#TODO + #'paid': inv_comp.paid, #TODO + }) + edi_doc['__model'] = 'purchase.order' + edi_doc_list.append(edi_doc) + return edi_doc_list + + def edi_import(self, cr, uid, edi_document, context=None): + partner_pool = self.pool.get('res.partner') + partner_address_pool = self.pool.get('res.partner.address') + model_data_pool = self.pool.get('ir.model.data') + product_pool = self.pool.get('product.product') + product_categ_pool = self.pool.get('product.category') + company_pool = self.pool.get('res.company') + country_pool = self.pool.get('res.country') + state_pool = self.pool.get('res.country.state') + + tax_id = [] + account_id = [] + partner_id = None + company_id = None + if context is None: + context = {} + + # import company as a new partner, if type==in then supplier=1, else customer=1 + # partner_id field is modified to point to the new partner + # company_address data used to add address to new partner + edi_company_address = edi_document['company_address'] + edi_partner_id = edi_document['partner_id'] + company_name = edi_document['company_id'][1] + state_id = edi_company_address.get('state_id', False) + state_name = state_id and state_id[1] + country_id = edi_company_address.get('country_id', False) + country_name = country_id and country_id[1] + + country_id = country_name and self.edi_import_relation(cr, uid, 'res.country', country_name, context=context) or False + state_id = state_name and self.edi_import_relation(cr, uid, 'res.country.state', state_name, + values={'country_id': country_id, 'code': state_name}, context=context) or False + address_value = { + 'street': edi_company_address.get('street', False), + 'street2': edi_company_address.get('street2', False), + 'zip': edi_company_address.get('zip', False), + 'city': edi_company_address.get('city', False), + 'state_id': state_id, + 'country_id': country_id, + 'email': edi_company_address.get('email', False), + 'phone': edi_company_address.get('phone', False), + + } + + partner_value = {'name': company_name} + partner_value.update({'customer': True, 'supplier': False}) + + partner_id = partner_pool.create(cr, uid, partner_value, context=context) + address_value.update({'partner_id': partner_id}) + address_id = partner_address_pool.create(cr, uid, address_value, context=context) + partner_address = partner_address_pool.browse(cr, uid, address_id, context=context) + partner_address_id = self.edi_m2o(cr, uid, partner_address, context=context) + partner = partner_pool.browse(cr, uid, partner_id, context=context) + edi_document['partner_id'] = self.edi_m2o(cr, uid, partner, context=context) + edi_document.update({ + 'partner_invoice_id': partner_address_id, + 'partner_order_id': partner_address_id, + 'partner_shipping_id': partner_address_id, + #'product_uom_qty': edi_document['order_line'][0]['product_qty'], + 'delay': 10, + }) + + # all fields are converted for sale order import so unnecessary fields are deleted + for i in range(len(edi_document['order_line'])): + edi_document['order_line'][i].update({'tax_id':edi_document['order_line'][i]['taxes_id']}) + delete_key = ['date_planned','product_qty','date_approve','validator','location_id','partner_address_id','company_address','company_id','warehouse_id','taxes_id'] + for key in delete_key: + if edi_document.has_key(key): + del edi_document[key] + else: + for document in edi_document['order_line']: + if document.has_key(key): + del document[key] + 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 new file mode 100644 index 00000000000..a9e25bd2562 --- /dev/null +++ b/addons/sale/edi_sale_order_data.xml @@ -0,0 +1,76 @@ + + + + + + context.update({'edi_web_url_view': '%s/edi/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').generate_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 + + + + + + + + + + + + ${object.company_id.name} - Sale Order ${object.name} + ${object.partner_invoice_id.email} + + True + +<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, print and pay invoice: <br/> + <a href="${object._context.get('edi_web_url_view')}">${object._context.get('edi_web_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 /> Confirm date: ${object.date_confirm 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> + +${object.company_id.paypal_account and "<p>It is possible to pay with Paypal: <br/> <a href=\"https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=%s&item_name=OpenERP%%20Invoice%%20%s&invoice=%s&amount=%s&button_subtype=services&no_note=1&bn=OpenERP_Invoice_PayNow_%s\"><img src=\"https://www.paypalobjects.com/en_US/i/btn/btn_paynowCC_LG.gif\" style=\"margin-left: 100px; border: 0px; padding: 1px; text-decoration: none;\"/></a> </p>"%(object.company_id.paypal_account, object.name and object.name.replace('/','%2f') or '', object.name and object.name.replace('/','%2f') or '', object.amount_total) or ''} + +<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, print and pay invoice: + + ${object._context.get('edi_web_url_view') or 'n/a'} + +Order Number: *${object.name}* +Amount: *${object.amount_total}* +Confirm date: ${object.date_confirm or 'n/a'} +Your contact: ${object.user_id.name} ${object.user_id.user_email and '<%s>'%(object.user_id.user_email) or ''} + +${object.company_id.paypal_account and "It is possible to pay with Paypal: https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=%s&item_name=OpenERP%%20Invoice%%20%s&invoice=%s&amount=%s&currency_code=%s&button_subtype=services&no_note=1&bn=OpenERP_Invoice_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) 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 ''} + + mako + Mail Template of Sale Order For EDI Document + sale.order + ${object.user_id.user_email or ''} + + + diff --git a/addons/sale/test/edi_sale_order.yml b/addons/sale/test/edi_sale_order.yml new file mode 100644 index 00000000000..8ad461ea476 --- /dev/null +++ b/addons/sale/test/edi_sale_order.yml @@ -0,0 +1,51 @@ +- + I create a partner which is a my customer ====================================== +- + !record {model: res.partner, id: res_partner_test22}: + name: Junjun wala + supplier: False + customer: True + opt_out: False +- + 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 + 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' +- + I Open 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) + +- + I Tesing of EDI functionality. First I export Sale Order from my company than import that Order into customer company +- + !python {model: ir.edi.document}: | + import json + invoice_pool = self.pool.get('sale.order') + orders = invoice_pool.browse(cr, uid, ref("sale_order_test")) + + tokens = self.export_edi(cr, uid, [orders]) + assert tokens, 'Token is not generated' + document = self.get_document(cr, uid, tokens[0]) + document = json.loads(document) + document[0]["__model"] = "purchase.order" + document = json.dumps(document) + a = self.import_edi(cr, uid, edi_document = document) + assert a, 'Invoice is not imported' + + From 5236ef43f183ae40f53bb432b184be81a151b707 Mon Sep 17 00:00:00 2001 From: "Harry (OpenERP)" Date: Thu, 8 Sep 2011 15:13:29 +0530 Subject: [PATCH 032/265] [IMP] accout.edi_invoice: to split edi_import() in smaller methods for importing the different parts bzr revid: hmo@tinyerp.com-20110908094329-14cutn414nbpvgvr --- addons/account/edi_invoice.py | 147 +++++++++++++++++++--------------- 1 file changed, 84 insertions(+), 63 deletions(-) diff --git a/addons/account/edi_invoice.py b/addons/account/edi_invoice.py index 179f2eb7234..cbcddb2430d 100644 --- a/addons/account/edi_invoice.py +++ b/addons/account/edi_invoice.py @@ -113,50 +113,57 @@ class account_invoice(osv.osv, ir_edi.edi): edi_doc_list.append(edi_doc) return edi_doc_list - def edi_import(self, cr, uid, edi_document, context=None): - """ During import, invoices will import the company that is provided in the invoice as - a new partner (e.g. supplier company for a customer invoice will be come a supplier - record for the new invoice. - Summary of tasks that need to be done: - - import company as a new partner, if type==in then supplier=1, else customer=1 - - partner_id field is modified to point to the new partner - - company_address data used to add address to new partner - - change type: out_invoice'<->'in_invoice','out_refund'<->'in_refund' - - 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' - 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 - product's default, i.e. from the default category, as it will not - 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. - """ - - partner_pool = self.pool.get('res.partner') - partner_address_pool = self.pool.get('res.partner.address') - model_data_pool = self.pool.get('ir.model.data') - product_pool = self.pool.get('product.product') - product_categ_pool = self.pool.get('product.category') - company_pool = self.pool.get('res.company') - country_pool = self.pool.get('res.country') - state_pool = self.pool.get('res.country.state') - account_journal_pool = self.pool.get('account.journal') - invoice_line_pool = self.pool.get('account.invoice.line') - account_pool = self.pool.get('account.account') - tax_id = [] - account_id = [] - partner_id = None - company_id = None + 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 + account_pool = self.pool.get('account.account') + account_ids = account_pool.search(cr, uid, [('type','<>','view'),('type','<>','income'), ('type', '<>', 'closed')]) + tax_account = False + if account_ids: + 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): + 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'): + invoice_account = partner.property_account_receivable + else: + invoice_account = partner.property_account_payable + return invoice_account + + def get_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 + else: + account = product.product_tmpl_id.property_account_expense + if not account: + account = product.categ_id.property_account_expense_categ + return account + + def edi_import_company(self, cr, uid, edi_document, context=None): # import company as a new partner, if type==in then supplier=1, else customer=1 # partner_id field is modified to point to the new partner # company_address data used to add address to new partner + + partner_pool = self.pool.get('res.partner') + partner_address_pool = self.pool.get('res.partner.address') edi_company_address = edi_document['company_address'] edi_partner_id = edi_document['partner_id'] company_name = edi_document['company_id'][1] @@ -198,15 +205,43 @@ class account_invoice(osv.osv, ir_edi.edi): partner_address = partner_address_pool.browse(cr, uid, address_id, context=context) 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 + a new partner (e.g. supplier company for a customer invoice will be come a supplier + record for the new invoice. + Summary of tasks that need to be done: + - import company as a new partner, if type==in then supplier=1, else customer=1 + - partner_id field is modified to point to the new partner + - company_address data used to add address to new partner + - change type: out_invoice'<->'in_invoice','out_refund'<->'in_refund' + - 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' + 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 + product's default, i.e. from the default category, as it will not + 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. + """ + if context is None: + context = {} + + #import company as a new partner + partner_id = self.edi_import_company(cr, uid, edi_document, context=context) + # 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 # Set Account - if invoice_type in ('out_invoice', 'out_refund'): - invoice_account = partner.property_account_receivable - else: - invoice_account = partner.property_account_payable + invoice_account = self.get_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' @@ -222,13 +257,9 @@ class account_invoice(osv.osv, ir_edi.edi): del edi_document['company_id'] # journal_id: should be selected based on type: simply put the 'type' in the context when calling create(), will be selected correctly - 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) + 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 + # 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) @@ -236,16 +267,7 @@ class account_invoice(osv.osv, ir_edi.edi): 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) - product = product_pool.browse(cr, uid, product_id, context=context) - - 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 - else: - account = product.product_tmpl_id.property_account_expense - if not account: - account = product.categ_id.property_account_expense_categ + account = self.get_product_account(cr, uid, product_id, invoice_type, context=context) # TODO: add effect of fiscal position # 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 @@ -253,10 +275,9 @@ class account_invoice(osv.osv, ir_edi.edi): # 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. for edi_tax_line in edi_document.get('tax_line', []): - account_ids = account_pool.search(cr, uid, [('type','<>','view'),('type','<>','income'), ('type', '<>', 'closed')]) - if account_ids: - tax_account = account_pool.browse(cr, uid, account_ids[0]) - edi_tax_line['account_id'] = self.edi_m2o(cr, uid, tax_account, context=context) #TODO should select account of output VAT for Customer Invoice and Input VAT for Supplier Invoice + 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['manual'] = True # TODO :=> payment_term: if set, create a default one based on name... From e21d4b3e42cb66abf93595e406909d3f9fb6bdee Mon Sep 17 00:00:00 2001 From: "Yogesh (OpenERP)" Date: Tue, 13 Sep 2011 14:24:34 +0530 Subject: [PATCH 033/265] [ADD] add basic structure of web_process module. bzr revid: ysa@tinyerp.com-20110913085434-z2a2615i2jpwdhmy --- addons/web_process/__init__.py | 0 addons/web_process/__openerp__.py | 11 +++++++++ .../static/src/img/iconset-a-help.gif | Bin 0 -> 379 bytes addons/web_process/static/src/js/process.js | 22 ++++++++++++++++++ .../static/src/xml/web_process.xml | 11 +++++++++ 5 files changed, 44 insertions(+) create mode 100644 addons/web_process/__init__.py create mode 100644 addons/web_process/__openerp__.py create mode 100644 addons/web_process/static/src/img/iconset-a-help.gif create mode 100644 addons/web_process/static/src/js/process.js create mode 100644 addons/web_process/static/src/xml/web_process.xml diff --git a/addons/web_process/__init__.py b/addons/web_process/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/addons/web_process/__openerp__.py b/addons/web_process/__openerp__.py new file mode 100644 index 00000000000..6b6886eae52 --- /dev/null +++ b/addons/web_process/__openerp__.py @@ -0,0 +1,11 @@ +{ + "name" : "Process", + "version" : "2.0", + "depends" : ["web"], + "js": [ + "static/src/js/process.js" + ], + "css": [ + ], + 'active': True +} diff --git a/addons/web_process/static/src/img/iconset-a-help.gif b/addons/web_process/static/src/img/iconset-a-help.gif new file mode 100644 index 0000000000000000000000000000000000000000..5400acec57bd30ea50c05765808d2d20684a6f90 GIT binary patch literal 379 zcmV->0fhcXNk%w1VGaNe0M$MK@$m5T^Yiuf_4D%b_xJbd=jZF|>)qSi|NsBt-{11_ z@#^X6-rU^r@$u~H>h10A?d$96=;+wj*W%#dt*x!**wa??(FRA>FMa^=JxjX{r&y)^z`N9gww5?(XpL@cjJz?Ck9C?d@Dy zSpWb4A^8LW002G!EC2ui01f~S000J^fY5NrK7qlY#sZD<0W&f-H9Cem6ev80H8wU1IgvRb9FUO! zHWe=qJe{7M4=)u3A_h38CKRVQ1|9_v69)@7H#IY~3kMSrJrNce2`{uS2^kg + + + + + + + +

Process View

+
+ From bc35b1250e0f8483f0301e2e121f82c3ef45f685 Mon Sep 17 00:00:00 2001 From: "Yogesh (OpenERP)" Date: Tue, 13 Sep 2011 16:32:27 +0530 Subject: [PATCH 034/265] [IMP] Improve process task. bzr revid: ysa@tinyerp.com-20110913110227-lnnw3e72hjtrsqaw --- addons/web_process/__openerp__.py | 1 + addons/web_process/static/src/css/process.css | 58 ++++++++++++++++++ addons/web_process/static/src/img/cta-a.gif | Bin 0 -> 108 bytes addons/web_process/static/src/img/sep-a.gif | Bin 0 -> 43 bytes .../static/src/xml/web_process.xml | 35 ++++++++++- 5 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 addons/web_process/static/src/css/process.css create mode 100644 addons/web_process/static/src/img/cta-a.gif create mode 100644 addons/web_process/static/src/img/sep-a.gif diff --git a/addons/web_process/__openerp__.py b/addons/web_process/__openerp__.py index 6b6886eae52..fd1a48a3a0d 100644 --- a/addons/web_process/__openerp__.py +++ b/addons/web_process/__openerp__.py @@ -6,6 +6,7 @@ "static/src/js/process.js" ], "css": [ + "static/src/css/process.css" ], 'active': True } diff --git a/addons/web_process/static/src/css/process.css b/addons/web_process/static/src/css/process.css new file mode 100644 index 00000000000..6522932a39a --- /dev/null +++ b/addons/web_process/static/src/css/process.css @@ -0,0 +1,58 @@ + +a.cta-a { + float: left; + padding: 5px 10px; + border: 1px solid #ccc; + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + background: #eeeded url(/web_process/static/src/img/cta-a.gif) repeat-x; + box-shadow: 0 1px 0 #fff; + -moz-box-shadow: 0 1px 0 #fff; + -webkit-box-shadow: 0 1px 0 #fff; + color: #8c8c8c; + font-size: 0.9em; + text-transform: uppercase; + font-weight: bold; + text-shadow: #fff 0 1px 0; + margin: 2px; +} + +a.cta-a span { + float: left; + padding: 7px 0 5px 5px; + background-position: 0 50%; + background-repeat: no-repeat; + cursor: pointer; +} + +a.cta-a strong { + display: block; + color: #393939; +} + +.process_h1 { + background:url("/web_process/static/src/img/sep-a.gif") repeat-x scroll 0 90% transparent; + font-size:2em; + font-weight:normal; + padding:0 0 5px 5px; + line-height: 1.2; +} + +.process-links { + padding: 5px 10px; + text-align: center; + display: table; + margin: auto; +} + +.process-links a.cta-a { + display: table-cell; +} + +.process-help-text { + float: left; + padding:5px 10px; + min-height:56px; + font-size: 120%; +} \ No newline at end of file diff --git a/addons/web_process/static/src/img/cta-a.gif b/addons/web_process/static/src/img/cta-a.gif new file mode 100644 index 0000000000000000000000000000000000000000..daa561e29f58d52f0806ada27a6ad25c1e30f24a GIT binary patch literal 108 zcmZ?wbhEHbWMt4`*v!E2_3PJ0dKfZtW z?lTa4`t;??mk;mXzkB;u@h1xd28j~(|&5Rgd;v{>OR;HAys JFXPT&4FG9+IZXfn literal 0 HcmV?d00001 diff --git a/addons/web_process/static/src/img/sep-a.gif b/addons/web_process/static/src/img/sep-a.gif new file mode 100644 index 0000000000000000000000000000000000000000..5a064f21e89f03e8e6ffd1b898fa51b2fae272e0 GIT binary patch literal 43 scmZ?wbhEHbWMp7sXkcKtd;9jUpFb6UvM_*v4u}BBFfcK>a4}c|00`s>g#Z8m literal 0 HcmV?d00001 diff --git a/addons/web_process/static/src/xml/web_process.xml b/addons/web_process/static/src/xml/web_process.xml index 76a281b911b..a37709ed3e6 100644 --- a/addons/web_process/static/src/xml/web_process.xml +++ b/addons/web_process/static/src/xml/web_process.xml @@ -6,6 +6,39 @@ -

Process View

+ + + + +
From 4dc536c8ce05b870e332acb01d8f9aab55184256 Mon Sep 17 00:00:00 2001 From: "Harry (OpenERP)" Date: Tue, 13 Sep 2011 18:29:23 +0530 Subject: [PATCH 035/265] [IMP] account: improve edi import of invoice to split in different stuff [IMP] sale: edi import process and correct EDI struct on exort [IMP] purchase: edi import process and correct EDI struct on export bzr revid: hmo@tinyerp.com-20110913125923-2gbhgd1vzyd2qrwy --- addons/account/edi_invoice.py | 101 ++------- addons/account/test/test_edi_invoice.yml | 62 +++++- addons/purchase/edi_purchase_order.py | 231 ++++++++------------ addons/purchase/edi_purchase_order_data.xml | 4 +- addons/purchase/test/edi_purchase_order.yml | 60 ++++- addons/sale/__openerp__.py | 3 +- addons/sale/edi_sale_order.py | 223 ++++++++----------- addons/sale/test/data_test.yml | 1 + addons/sale/test/edi_sale_order.yml | 55 ++++- 9 files changed, 362 insertions(+), 378 deletions(-) diff --git a/addons/account/edi_invoice.py b/addons/account/edi_invoice.py index cbcddb2430d..db09e7ab6aa 100644 --- a/addons/account/edi_invoice.py +++ b/addons/account/edi_invoice.py @@ -66,20 +66,9 @@ class account_invoice(osv.osv, ir_edi.edi): 'base_amount': True, 'tax_amount': True, }, + #'paid': True, } - partner_pool = self.pool.get('res.partner') - partner_address_pool = self.pool.get('res.partner.address') - company_address_dict = { - 'street': True, - 'street2': True, - 'zip': True, - 'city': True, - 'state_id': True, - 'country_id': True, - 'email': True, - 'phone': True, - - } + company_pool = 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. @@ -89,26 +78,10 @@ class account_invoice(osv.osv, ir_edi.edi): edi_doc = edi_doc[0] # Add company info and address - res = partner_pool.address_get(cr, uid, [invoice.company_id.partner_id.id], ['contact', 'invoice']) - contact_addr_id = res['contact'] - invoice_addr_id = res['invoice'] - - address = partner_address_pool.browse(cr, uid, invoice_addr_id, context=context) - edi_company_address_dict = {} - for key, value in company_address_dict.items(): - if not value: - continue - address_rec = getattr(address, key) - if not address_rec: - continue - if key.endswith('_id'): - address_rec = self.edi_m2o(cr, uid, address_rec, context=context) - edi_company_address_dict[key] = address_rec - + edi_company_document = company_pool.edi_export_address(cr, uid, [invoice.company_id], context=context)[invoice.company_id.id] edi_doc.update({ - 'company_address': edi_company_address_dict, - #'company_logo': inv_comp.logo,#TODO - #'paid': inv_comp.paid, #TODO + 'company_address': edi_company_document['company_address'], + #'company_logo': edi_company_document['company_logo'],#TODO }) edi_doc_list.append(edi_doc) return edi_doc_list @@ -158,54 +131,30 @@ class account_invoice(osv.osv, ir_edi.edi): return account def edi_import_company(self, cr, uid, edi_document, context=None): - # import company as a new partner, if type==in then supplier=1, else customer=1 - # partner_id field is modified to point to the new partner - # company_address data used to add address to new partner - - partner_pool = self.pool.get('res.partner') partner_address_pool = self.pool.get('res.partner.address') - edi_company_address = edi_document['company_address'] - edi_partner_id = edi_document['partner_id'] - company_name = edi_document['company_id'][1] + partner_pool = self.pool.get('res.partner') + company_pool = self.pool.get('res.company') + + # 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 invoice_type = edi_document['type'] - state_id = edi_company_address.get('state_id', False) - state_name = state_id and state_id[1] - country_id = edi_company_address.get('country_id', False) - country_name = country_id and country_id[1] - - country_id = country_name and self.edi_import_relation(cr, uid, 'res.country', country_name, context=context) or False - state_id = state_name and self.edi_import_relation(cr, uid, 'res.country.state', state_name, - values={'country_id': country_id, 'code': state_name}, context=context) or False - address_value = { - 'street': edi_company_address.get('street', False), - 'street2': edi_company_address.get('street2', False), - 'zip': edi_company_address.get('zip', False), - 'city': edi_company_address.get('city', False), - 'state_id': state_id, - 'country_id': country_id, - 'email': edi_company_address.get('email', False), - 'phone': edi_company_address.get('phone', False), - - } - - - partner_value = {'name': company_name} + partner_value = {} if invoice_type in ('out_invoice', 'in_refund'): - partner_value.update({'customer': True, 'supplier': False}) + partner_value.update({'customer': True}) if invoice_type in ('in_invoice', 'out_refund'): - partner_value.update({'customer': False, 'supplier': True}) - - partner_id = partner_pool.create(cr, uid, partner_value, context=context) - address_value.update({'partner_id': partner_id}) - address_id = partner_address_pool.create(cr, uid, address_value, context=context) + partner_value.update({'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) - edi_document['partner_id'] = self.edi_m2o(cr, uid, partner, 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) - - return partner.id + del edi_document['company_id'] + 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 @@ -251,10 +200,7 @@ class account_invoice(osv.osv, ir_edi.edi): # internal number: reset to False, auto-generated edi_document['internal_number'] = False - - # company should set by default so delete company data from edi Document - del edi_document['company_address'] - del edi_document['company_id'] + # 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) @@ -281,7 +227,6 @@ class account_invoice(osv.osv, ir_edi.edi): 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() @@ -294,3 +239,5 @@ class account_invoice_tax(osv.osv, ir_edi.edi): _inherit = "account.invoice.tax" account_invoice_tax() + + diff --git a/addons/account/test/test_edi_invoice.yml b/addons/account/test/test_edi_invoice.yml index 0a03c3ca9dc..e01e6aaa712 100644 --- a/addons/account/test/test_edi_invoice.yml +++ b/addons/account/test/test_edi_invoice.yml @@ -56,7 +56,7 @@ wf_service.trg_validate(uid, 'account.invoice',invoices.id,'invoice_open', cr) - - I Tesing of EDI functionality. First I export customer invoice from my company than import that invoice into customer company + 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') @@ -64,9 +64,60 @@ tokens = self.export_edi(cr, uid, [invoice]) assert tokens, 'Token is not generated' - document = self.get_document(cr, uid, tokens[0]) - a = self.import_edi(cr, uid, edi_document = document) - assert a, 'Invoice is not imported' +- + I import of EDI document of custmer invoice +- + !python {model: ir.edi.document}: | + invoice_pool = self.pool.get('account.invoice') + edi_document = { + "internal_number": "SAJ/2011/002", + "company_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", + "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, + "date_invoice": "2011-06-22", + "amount_untaxed": 10.0, + "name": "selling product", + "__model": "account.invoice", + "__last_update": False, + "tax_line": [{ + "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, + "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"], + "quantity": 1.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 - @@ -75,8 +126,7 @@ invoice_old = self.browse(cr, uid, ref("customer_invoice_test")) new_partner_id = self.pool.get('res.partner').name_search(cr, uid, invoice_old.company_id.name) assert new_partner_id, 'Partner is not created of Supplier' - - ids = self.search(cr, uid, [('partner_id','=',new_partner_id[0][0]),('reference','=',invoice_old.internal_number)]) + 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]) assert invoice_new.reference == invoice_old.internal_number, "internal number is not stored in reference" diff --git a/addons/purchase/edi_purchase_order.py b/addons/purchase/edi_purchase_order.py index 605e29621b1..cb19f57c103 100644 --- a/addons/purchase/edi_purchase_order.py +++ b/addons/purchase/edi_purchase_order.py @@ -22,58 +22,48 @@ from osv import fields, osv, orm from base.ir import ir_edi from tools.translate import _ -from datetime import date +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 supplier or customer invoice""" + """Exports a purchase order""" edi_struct = { + 'company_id': True, # -> to be changed into partner + 'name': 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, - 'origin': True, - 'date_order': True, - 'date_approve': True, - 'partner_id': True, - 'partner_address_id': True, - 'dest_address_id': True, - 'warehouse_id': True, - 'location_id': True, - 'pricelist_id': True, - 'validator' : True, - 'amount_tax': True, - 'amount_total': True, - 'amount_untaxed': True, - 'order_line': { - 'name': True, - 'product_qty': True, - 'date_planned': True, - 'taxes_id': True, - 'product_uom': True, - 'product_id': True, - 'move_dest_id': True, - 'price_unit': True, - 'order_id': True, - 'invoiced': True, - 'price_subtotal': True, - }, - 'invoice_ids': True, - 'shipped': True, - 'company_id': True, - } - partner_pool = self.pool.get('res.partner') - partner_address_pool = self.pool.get('res.partner.address') - company_address_dict = { - 'street': True, - 'street2': True, - 'zip': True, - 'city': True, - 'state_id': True, - 'country_id': True, - 'email': True, - 'phone': True, - + 'date_planned': True, + #SO: 'delay' : 'date_approve' - 'date_planned' + #PO: 'date_planned': 'date_approve' + 'delay' + + 'product_id': True, + 'product_uom': True, + 'price_unit': 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. @@ -83,107 +73,80 @@ class purchase_order(osv.osv, ir_edi.edi): edi_doc = edi_doc[0] # Add company info and address - res = partner_pool.address_get(cr, uid, [order.company_id.partner_id.id], ['contact', 'order']) - contact_addr_id = res['contact'] - invoice_addr_id = res['order'] - - address = partner_address_pool.browse(cr, uid, invoice_addr_id, context=context) - edi_company_address_dict = {} - for key, value in company_address_dict.items(): - if not value: - continue - address_rec = getattr(address, key) - if not address_rec: - continue - if key.endswith('_id'): - address_rec = self.edi_m2o(cr, uid, address_rec, context=context) - edi_company_address_dict[key] = address_rec - + 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_address_dict, - #'company_logo': inv_comp.logo,#TODO - #'paid': inv_comp.paid, #TODO + 'company_address': edi_company_document['company_address'], + #'company_logo': edi_company_document['company_logo'],#TODO }) - edi_doc['__model'] = 'sale.order' edi_doc_list.append(edi_doc) - return edi_doc_list - def edi_import(self, cr, uid, edi_document, context=None): - - partner_pool = self.pool.get('res.partner') + def edi_import_company(self, cr, uid, edi_document, context=None): partner_address_pool = self.pool.get('res.partner.address') - model_data_pool = self.pool.get('ir.model.data') - product_pool = self.pool.get('product.product') - product_categ_pool = self.pool.get('product.category') + partner_pool = self.pool.get('res.partner') company_pool = self.pool.get('res.company') - country_pool = self.pool.get('res.country') - state_pool = self.pool.get('res.country.state') - account_journal_pool = self.pool.get('account.journal') - invoice_line_pool = self.pool.get('account.invoice.line') - account_pool = self.pool.get('account.account') - stock = self.pool.get('stock.location') - tax_id = [] - account_id = [] - partner_id = None - company_id = None + + # 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 = {} - print edi_document - # import company as a new partner, if type==in then supplier=1, else customer=1 - # partner_id field is modified to point to the new partner - # company_address data used to add address to new partner - edi_company_address = edi_document['company_address'] - edi_partner_id = edi_document['partner_id'] - company_name = edi_document['shop_id'][1] - state_id = edi_company_address.get('state_id', False) - state_name = state_id and state_id[1] - country_id = edi_company_address.get('country_id', False) - country_name = country_id and country_id[1] - - country_id = country_name and self.edi_import_relation(cr, uid, 'res.country', country_name, context=context) or False - state_id = state_name and self.edi_import_relation(cr, uid, 'res.country.state', state_name, - values={'country_id': country_id, 'code': state_name}, context=context) or False - address_value = { - 'street': edi_company_address.get('street', False), - 'street2': edi_company_address.get('street2', False), - 'zip': edi_company_address.get('zip', False), - 'city': edi_company_address.get('city', False), - 'state_id': state_id, - 'country_id': country_id, - 'email': edi_company_address.get('email', False), - 'phone': edi_company_address.get('phone', False), - - } - partner_value = {'name': company_name} - partner_value.update({'customer': False, 'supplier': True}) - partner_id = partner_pool.create(cr, uid, partner_value, context=context) - address_value.update({'partner_id': partner_id}) - address_id = partner_address_pool.create(cr, uid, address_value, context=context) - partner_address = partner_address_pool.browse(cr, uid, address_id, context=context) - edi_document.update({'partner_address_id':self.edi_m2o(cr, uid, partner_address, context=context)}) - partner = partner_pool.browse(cr, uid, partner_id, context=context) - edi_document['partner_id'] = self.edi_m2o(cr, uid, partner, context=context) - location_id = stock.search(cr, uid,[('name','=','Stock')]) - location = stock.browse(cr, uid, location_id[0]) - edi_document.update({'dest_address_id': edi_document['partner_shipping_id'],'location_id': self.edi_m2o(cr, uid, location, context=context)}) - for line in range(len(edi_document['order_line'])): - product_qty = edi_document['order_line'][line]['product_uom_qty'] - edi_document['order_line'][line].update({'product_qty': product_qty,'taxes_id':edi_document['order_line'][line]['tax_id']}) - - # all fields are converted for purchase order import so unnecessary fields are deleted - delete_key = ['sequence','procurement_id','product_uom_qty','company_address','shop_id','create_date','picking_policy','order_policy','partner_order_id','partner_shipping_id','invoice_quantity','partner_invoice_id','price_subtotal','date_confirm'] - for key in delete_key: - if edi_document.has_key(key): - del edi_document[key] - else: - for document in edi_document['order_line']: - if document.has_key(key): - del document[key] - print "in the edi_purchase import",edi_document + model = edi_document['__model'] + assert model == 'sale.order', _('Could not import purchase order') + edi_document['__model'] = self._name + #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): diff --git a/addons/purchase/edi_purchase_order_data.xml b/addons/purchase/edi_purchase_order_data.xml index 7351afe4a3f..d8a87fec0c9 100644 --- a/addons/purchase/edi_purchase_order_data.xml +++ b/addons/purchase/edi_purchase_order_data.xml @@ -19,9 +19,9 @@ if not object.partner_id.opt_out: self.pool.get('email.template').generate_mail( - + diff --git a/addons/purchase/test/edi_purchase_order.yml b/addons/purchase/test/edi_purchase_order.yml index 1fbc89db70a..ef3bbb4338b 100644 --- a/addons/purchase/test/edi_purchase_order.yml +++ b/addons/purchase/test/edi_purchase_order.yml @@ -5,7 +5,7 @@ name: jones white supplier: False customer: True - opt_out: False + opt_out: True - I create one Purchase Order - @@ -30,18 +30,56 @@ import netsvc wf_service = netsvc.LocalService("workflow") wf_service.trg_validate(uid, 'purchase.order',orders.id,'approved', cr) +- + I Tesing of EDI functionality. First I export Purchase Order from my company than import that Order into customer company - !python {model: ir.edi.document}: | order_pool = self.pool.get('purchase.order') - purchase_id = order_pool.search(cr, uid, ref("purchase_order_test")) - orders = order_pool.browse(cr, uid, purchase_id) - import json + order = order_pool.browse(cr, uid, ref("purchase_order_test")) - tokens = self.export_edi(cr, uid, [orders]) + tokens = self.export_edi(cr, uid, [order]) assert tokens, 'Token is not generated' - document = self.get_document(cr, uid, tokens[0]) - document = json.loads(document) - document[0]["__model"] = "sale.order" - document = json.dumps(document) - a = self.import_edi(cr, uid, edi_document = document) - + +- + I import purchase order from EDI Document of sale order +- + !python {model: ir.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"] + }], + "order_policy": "manual", + "company_address": { + "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", + "phone": "(+32).81.81.37.00", + "street": "Chaussee de Namur 40" + }, + "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": "sale", + "amount_total": 150.0, + "amount_untaxed": 150.0, + "name": "SO008", + "__model": "sale.order", + "__last_update": False, + "company_id": ["724f93ec-ddd0-11e0-88ec-701a04e25543:base.main_company", "OpenERP S.A."], + "__version": [6, 1], + "pricelist_id": ["724f93ec-ddd0-11e0-88ec-701a04e25543:product.list0", "Public Pricelist (EUR)"] + } + 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' diff --git a/addons/sale/__openerp__.py b/addons/sale/__openerp__.py index 0e3ec9ed075..c862a4cbbfa 100644 --- a/addons/sale/__openerp__.py +++ b/addons/sale/__openerp__.py @@ -89,6 +89,7 @@ Dashboard for Sales Manager that includes: ], 'demo_xml': ['sale_demo.xml'], 'test': [ + 'test/edi_sale_order.yml', 'test/data_test.yml', 'test/manual_order_policy.yml', 'test/prepaid_order_policy.yml', @@ -100,7 +101,7 @@ Dashboard for Sales Manager that includes: 'test/invoice_on_ordered_qty.yml', 'test/invoice_on_shipped_qty.yml', 'test/sale_report.yml', - 'test/edi_sale_order.yml', + ], 'installable': True, 'active': False, diff --git a/addons/sale/edi_sale_order.py b/addons/sale/edi_sale_order.py index 7e193fa672c..70a57a8d216 100644 --- a/addons/sale/edi_sale_order.py +++ b/addons/sale/edi_sale_order.py @@ -22,7 +22,7 @@ from osv import fields, osv, orm from base.ir import ir_edi from tools.translate import _ -from datetime import date +from datetime import date, datetime class sale_order(osv.osv, ir_edi.edi): _inherit = 'sale.order' @@ -30,61 +30,44 @@ class sale_order(osv.osv, ir_edi.edi): 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, + '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, - 'origin' : True, - 'picking_policy': True, - 'order_policy': True, - 'client_order_ref': True, - 'date_order': True, - 'partner_id': True, - 'note': True, - 'amount_untaxed': True, - 'payment_term': True, - 'amount_tax': True, - 'amount_total': True, - 'amount_untaxed': True, - 'pricelist_id': True, - 'incoterm': True, - 'partner_order_id': True, - 'partner_invoice_id': True, - 'partner_shipping_id': True, - 'shipped': True, - 'picked_rate': True, - 'invoice_quantity': True, - 'invoiced': True, - 'invoiced_rate': True, - - 'order_line': { - 'product_uos_qty': True, - 'product_uom': True, - 'sequence': True, - 'price_unit': True, - 'product_uom_qty': True, - 'discount': True, - 'product_uos': True, - 'invoiced': True, - 'delay': True, - 'name': True, - 'notes': True, - 'product_id': True, - 'th_weight': True, - 'product_packaging': True, - 'tax_id': True, - }, - } - partner_pool = self.pool.get('res.partner') - partner_address_pool = self.pool.get('res.partner.address') - company_address_dict = { - 'street': True, - 'street2': True, - 'zip': True, - 'city': True, - 'state_id': True, - 'country_id': True, - 'email': True, - 'phone': True, - + 'delay': True, + #SO: 'delay' : 'date_approve' - 'date_planned' + #PO: 'date_planned': 'date_approve' + 'delay' + + 'product_id': True, + 'product_uom': True, + 'price_unit': True, + 'product_uom_qty': True, + #SO: 'product_uom_qty' + #PO: 'product_qty' + + 'discount': True, + #SO: yes + #PO: No + '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. @@ -94,101 +77,67 @@ class sale_order(osv.osv, ir_edi.edi): edi_doc = edi_doc[0] # Add company info and address - res = partner_pool.address_get(cr, uid, [order.shop_id.company_id.partner_id.id], ['contact', 'order']) - contact_addr_id = res['contact'] - invoice_addr_id = res['order'] - - address = partner_address_pool.browse(cr, uid, invoice_addr_id, context=context) - edi_company_address_dict = {} - for key, value in company_address_dict.items(): - if not value: - continue - address_rec = getattr(address, key) - if not address_rec: - continue - if key.endswith('_id'): - address_rec = self.edi_m2o(cr, uid, address_rec, context=context) - - edi_company_address_dict[key] = address_rec - + 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_address_dict, + 'company_address': edi_company_document['company_address'], + #'company_logo': edi_company_document['company_logo'],#TODO }) edi_doc_list.append(edi_doc) return edi_doc_list - def edi_import(self, cr, uid, edi_document, context=None): - partner_pool = self.pool.get('res.partner') + def edi_import_company(self, cr, uid, edi_document, context=None): partner_address_pool = self.pool.get('res.partner.address') - model_data_pool = self.pool.get('ir.model.data') - product_pool = self.pool.get('product.product') - product_categ_pool = self.pool.get('product.category') + partner_pool = self.pool.get('res.partner') company_pool = self.pool.get('res.company') - country_pool = self.pool.get('res.country') - state_pool = self.pool.get('res.country.state') - - tax_id = [] - account_id = [] - partner_id = None - company_id = None + + # 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, if type==in then supplier=1, else customer=1 - # partner_id field is modified to point to the new partner - # company_address data used to add address to new partner - edi_company_address = edi_document['company_address'] - edi_partner_id = edi_document['partner_id'] - company_name = edi_document['company_id'][1] - state_id = edi_company_address.get('state_id', False) - state_name = state_id and state_id[1] - country_id = edi_company_address.get('country_id', False) - country_name = country_id and country_id[1] + model = edi_document['__model'] + assert model == 'purchase.order', _('Could not import sale order') + edi_document['__model'] = self._name + #import company as a new partner + partner_id = self.edi_import_company(cr, uid, edi_document, context=context) - country_id = country_name and self.edi_import_relation(cr, uid, 'res.country', country_name, context=context) or False - state_id = state_name and self.edi_import_relation(cr, uid, 'res.country.state', state_name, - values={'country_id': country_id, 'code': state_name}, context=context) or False - address_value = { - 'street': edi_company_address.get('street', False), - 'street2': edi_company_address.get('street2', False), - 'zip': edi_company_address.get('zip', False), - 'city': edi_company_address.get('city', False), - 'state_id': state_id, - 'country_id': country_id, - 'email': edi_company_address.get('email', False), - 'phone': edi_company_address.get('phone', False), - - } - - partner_value = {'name': company_name} - partner_value.update({'customer': True, 'supplier': False}) - - partner_id = partner_pool.create(cr, uid, partner_value, context=context) - address_value.update({'partner_id': partner_id}) - address_id = partner_address_pool.create(cr, uid, address_value, context=context) - partner_address = partner_address_pool.browse(cr, uid, [address_id], context=context) - partner_address_id = self.edi_o2m(cr, uid, [partner_address], context=context) - partner = partner_pool.browse(cr, uid, partner_id, context=context) - edi_document['partner_id'] = self.edi_m2o(cr, uid, partner, context=context) - edi_document.update({ - 'partner_invoice_id': partner_address_id, - 'partner_order_id': partner_address_id, - 'partner_shipping_id': partner_address_id, - #'product_uom_qty': edi_document['order_line'][0]['product_qty'], - 'delay': 10, - }) - # all fields are converted for sale order import so unnecessary fields are deleted - del edi_document['order_line'][0]['date_planned'] - del edi_document['order_line'][0]['product_qty'] - del edi_document['date_approve'] - del edi_document['validator'] - - del edi_document['location_id'] - del edi_document['partner_address_id'] - del edi_document['company_address'] - del edi_document['company_id'] - del edi_document['warehouse_id'] + 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_order = datetime.strptime(date_order, "%Y-%m-%d") + date_planned = datetime.strptime(order_line['date_planned'], "%Y-%m-%d") + order_line['delay'] = (date_planned - date_order).days return super(sale_order,self).edi_import(cr, uid, edi_document, context=context) sale_order() diff --git a/addons/sale/test/data_test.yml b/addons/sale/test/data_test.yml index 6e5ec1a9738..2b75e27c90a 100644 --- a/addons/sale/test/data_test.yml +++ b/addons/sale/test/data_test.yml @@ -177,6 +177,7 @@ category_id: - res_partner_category_customers0 name: Cleartrail + opt_out: True - I create contact address for Cleartrail. - diff --git a/addons/sale/test/edi_sale_order.yml b/addons/sale/test/edi_sale_order.yml index b7bd018156e..9eb6fc42ce0 100644 --- a/addons/sale/test/edi_sale_order.yml +++ b/addons/sale/test/edi_sale_order.yml @@ -5,7 +5,7 @@ name: Junjun wala supplier: False customer: True - opt_out: False + opt_out: True - I create one Sale Order - @@ -35,17 +35,52 @@ I Tesing of EDI functionality. First I export Sale Order from my company than import that Order into customer company - !python {model: ir.edi.document}: | - import json - invoice_pool = self.pool.get('sale.order') - orders = invoice_pool.browse(cr, uid, ref("sale_order_test")) + 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' - document = self.get_document(cr, uid, tokens[0]) - document = json.loads(document) - document[0]["__model"] = "purchase.order" - document = json.dumps(document) - #a = self.import_edi(cr, uid, edi_document = document) - #assert a, 'Invoice is not imported' +- + I import Sale order from EDI Document of purchase order +- + !python {model: ir.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-08-31", + "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"] + }], + "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": "purchase", + "amount_total": 150.0, + "company_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", + }, + "amount_untaxed": 150.0, + "name": "PO00011", + "__model": "purchase.order", + "__last_update": False, + "company_id": ["5af1272e-dd26-11e0-b65e-701a04e25543:base.main_company", "OpenERP S.A."], + "__version": [6, 1], + "pricelist_id": ["5af1272e-dd26-11e0-b65e-701a04e25543:product.list0", "Public Pricelist (EUR)"] + } + 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' From fa802828877780cb0f1cbab1a45b1009b5d643b2 Mon Sep 17 00:00:00 2001 From: "Harry (OpenERP)" Date: Thu, 15 Sep 2011 11:00:43 +0530 Subject: [PATCH 036/265] [FIX] edi: correct datas of email_template bzr revid: hmo@tinyerp.com-20110915053043-a6f2d7ecwfbzspu1 --- addons/account/edi_invoice_action_data.xml | 23 +++++++------- addons/account/test/test_edi_invoice.yml | 5 ++-- addons/email_template/email_template.py | 1 + addons/purchase/edi_purchase_order_data.xml | 33 ++++++++++----------- addons/sale/edi_sale_order_data.xml | 28 ++++++++--------- 5 files changed, 44 insertions(+), 46 deletions(-) diff --git a/addons/account/edi_invoice_action_data.xml b/addons/account/edi_invoice_action_data.xml index fb89e585195..22d3eb7dbdf 100644 --- a/addons/account/edi_invoice_action_data.xml +++ b/addons/account/edi_invoice_action_data.xml @@ -4,10 +4,10 @@ context.update({'edi_web_invoice_url_view': '%s/edi/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').generate_mail(cr, +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, 'account', 'email_template_edi_invoice')[1], - [object.id], + object.id, context=context) code @@ -26,10 +26,14 @@ if not object.partner_id.opt_out: self.pool.get('email.template').generate_mail( - ${object.company_id.name} Invoice (Ref ${object.number or 'n/a' }) - ${object.address_invoice_id.email or ''} - - + Mail Template of Invoice For EDI Document + ${object.user_id.user_email or ''} + ${object.user_id.user_email or ''} + + ${object.company_id.name} Invoice (Ref ${object.number or 'n/a' }) + ${object.address_invoice_id.email or ''} + + <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.address_invoice_id.name and ' ' or ''},</p> @@ -44,7 +48,7 @@ ${object.company_id.paypal_account and "<p>It is possible to pay with Payp <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=Invoice%20${object.number}">${object.user_id.name}</a></div> <div> </div> </div> </div> <p> </p> - + Hello ${object.address_invoice_id.name and ' ' or ''}, You can click on the following link to preview, print and pay invoice: @@ -67,10 +71,7 @@ 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 ''} - mako - Mail Template of Invoice For EDI Document - account.invoice - ${object.user_id.user_email or ''} +
diff --git a/addons/account/test/test_edi_invoice.yml b/addons/account/test/test_edi_invoice.yml index e01e6aaa712..d29fe96fc89 100644 --- a/addons/account/test/test_edi_invoice.yml +++ b/addons/account/test/test_edi_invoice.yml @@ -123,13 +123,12 @@ - !python {model: account.invoice}: | - invoice_old = self.browse(cr, uid, ref("customer_invoice_test")) - new_partner_id = self.pool.get('res.partner').name_search(cr, uid, invoice_old.company_id.name) + 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]) - assert invoice_new.reference == invoice_old.internal_number, "internal number is not stored in reference" + 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.internal_number == False, "internal number is not reset" assert invoice_new.journal_id.id, "journal id is not selected" diff --git a/addons/email_template/email_template.py b/addons/email_template/email_template.py index 3917b3f2ddb..1a8ba49594d 100644 --- a/addons/email_template/email_template.py +++ b/addons/email_template/email_template.py @@ -382,5 +382,6 @@ class email_template(osv.osv): if context.has_key('default_type'): del context['default_type'] attachment_ids.append(ir_attachment.create(cr, uid, attachment_data, context)) + return message_id # 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 index d8a87fec0c9..e99fe687b5d 100644 --- a/addons/purchase/edi_purchase_order_data.xml +++ b/addons/purchase/edi_purchase_order_data.xml @@ -3,11 +3,11 @@ - context.update({'edi_web_url_view': '%s/edi/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').generate_mail(cr, + context.update({'edi_web_purchase_url_view': '%s/edi/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], + object.id, context=context) code @@ -19,23 +19,25 @@ if not object.partner_id.opt_out: self.pool.get('email.template').generate_mail( - + - ${object.company_id.name} - Purchase Order ${object.name} - ${object.partner_address_id.email} - - True - + 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, print and pay invoice: <br/> - <a href="${object._context.get('edi_web_url_view')}">${object._context.get('edi_web_url_view')} </a> + <a href="${object._context.get('edi_web_purchase_url_view')}">${object._context.get('edi_web_purchase_url_view')} </a> </p> @@ -45,12 +47,12 @@ ${object.company_id.paypal_account and "<p>It is possible to pay with Payp <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, print and pay invoice: - ${object._context.get('edi_web_url_view') or 'n/a'} + ${object._context.get('edi_web_purchase_url_view') or 'n/a'} Order Number: *${object.name}* Amount: *${object.amount_total}* @@ -67,10 +69,7 @@ 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 ''} - mako - Mail Template of Purchase Order For EDI Document - purchase.order - ${object.validator.user_email or ''} + diff --git a/addons/sale/edi_sale_order_data.xml b/addons/sale/edi_sale_order_data.xml index a9e25bd2562..0e9fa04b12e 100644 --- a/addons/sale/edi_sale_order_data.xml +++ b/addons/sale/edi_sale_order_data.xml @@ -3,11 +3,11 @@ - context.update({'edi_web_url_view': '%s/edi/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').generate_mail(cr, + context.update({'edi_web_sale_url_view': '%s/edi/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_email(cr, uid, self.pool.get('ir.model.data').get_object_reference(cr, uid, 'sale', 'email_template_edi_sale')[1], - [object.id], + object.id, context=context) code @@ -26,16 +26,18 @@ if not object.partner_id.opt_out: self.pool.get('email.template').generate_mail( - ${object.company_id.name} - Sale Order ${object.name} - ${object.partner_invoice_id.email} - - True - + 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, print and pay invoice: <br/> - <a href="${object._context.get('edi_web_url_view')}">${object._context.get('edi_web_url_view')} </a> + <a href="${object._context.get('edi_web_sale_url_view')}">${object._context.get('edi_web_sale_url_view')} </a> </p> @@ -45,12 +47,12 @@ ${object.company_id.paypal_account and "<p>It is possible to pay with Payp <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, print and pay invoice: - ${object._context.get('edi_web_url_view') or 'n/a'} + ${object._context.get('edi_web_sale_url_view') or 'n/a'} Order Number: *${object.name}* Amount: *${object.amount_total}* @@ -67,10 +69,6 @@ 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 ''} - mako - Mail Template of Sale Order For EDI Document - sale.order - ${object.user_id.user_email or ''} From cbc18d6479d37c13666056709fe1c2c82204a939 Mon Sep 17 00:00:00 2001 From: "Hardik Ansodariy (OpenERP)" Date: Thu, 15 Sep 2011 19:02:13 +0530 Subject: [PATCH 037/265] [IMP] improved yml for edi sale,purchase and account invoice bzr revid: han@tinyerp.com-20110915133213-i67qac35o1q1rtyv --- addons/account/test/test_edi_invoice.yml | 7 +++- addons/purchase/test/edi_purchase_order.yml | 39 ++++++++++++++++-- addons/sale/test/edi_sale_order.yml | 44 ++++++++++----------- 3 files changed, 61 insertions(+), 29 deletions(-) diff --git a/addons/account/test/test_edi_invoice.yml b/addons/account/test/test_edi_invoice.yml index 29c7c626f6d..843892a4573 100644 --- a/addons/account/test/test_edi_invoice.yml +++ b/addons/account/test/test_edi_invoice.yml @@ -150,11 +150,14 @@ 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', "Imported in voice is not supplier invoice" + assert invoice_new.amount_total == 1010.0, "Amount total is not same" + assert invoice_new.amount_tax == 1000.0, "Amount tax is not same" + assert invoice_new.amount_untaxes == 10.0, "Amount untaxed is not same" product = ['Medium PC','Basic PC'] for inv_line in invoice_new.invoice_line: assert inv_line.account_id.id, "account_id is not taken from product's default" - assert inv_line.product_id.name in product, "product is not in Invoice line" + assert inv_line.product_id.name in ['Medium PC','Basic PC'], "product is not in Invoice line" for inv_tax in invoice_new.tax_line: assert inv_tax.manual, "for tax line manual is not set to True" assert inv_tax.account_id, "for tax_line default accounts is not picked based on the tax config of the DB where it is imported." diff --git a/addons/purchase/test/edi_purchase_order.yml b/addons/purchase/test/edi_purchase_order.yml index ef3bbb4338b..a6dc45ee997 100644 --- a/addons/purchase/test/edi_purchase_order.yml +++ b/addons/purchase/test/edi_purchase_order.yml @@ -21,8 +21,15 @@ price_unit: 150.0 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: 200.0 + name: 'medium pc' + date_planned: '2011-08-31' - - I Open the sale order + I Open the Purchase order - !python {model: purchase.order}: | @@ -55,6 +62,16 @@ "__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": 200.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": { @@ -72,8 +89,8 @@ "partner_id": ["724f93ec-ddd0-11e0-88ec-701a04e25543:sale.res_partner_test22", "Junjun wala"], "__attachments": [], "__module": "sale", - "amount_total": 150.0, - "amount_untaxed": 150.0, + "amount_total": 350.0, + "amount_untaxed": 350.0, "name": "SO008", "__model": "sale.order", "__last_update": False, @@ -83,3 +100,19 @@ } 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: sale.order}: | + + ids = self.search(cr, uid, [('partner_id','=','OpenERP S.A.')]) + 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" + for sale_line in order_new.order_line: + assert sale_line.name in ['basic pc','medium pc'], "name of product is not in order" + assert sale_line.product_id.name in ['Basic PC','Medium PC'], "name of product is not in order" + assert sale_line.date_order == '2011-09-13' , "date of order is not same" diff --git a/addons/sale/test/edi_sale_order.yml b/addons/sale/test/edi_sale_order.yml index 1756f369ff6..af1b32a6f01 100644 --- a/addons/sale/test/edi_sale_order.yml +++ b/addons/sale/test/edi_sale_order.yml @@ -21,6 +21,12 @@ product_uom: 1 price_unit: 150.0 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' - I Open the sale order - @@ -63,7 +69,7 @@ "partner_id": ["5af1272e-dd26-11e0-b65e-701a04e25543:purchase.res_partner_test20", "jones white"], "__attachments": [], "__module": "purchase", - "amount_total": 150.0, + "amount_total": 350.0, "company_address": { "phone": "(+32).81.81.37.00", "street": "Chaussee de Namur 40", @@ -73,7 +79,7 @@ "country_id": ["5af1272e-dd26-11e0-b65e-701a04e25543:base.be", "Belgium"], "__id": "5af1272e-dd26-11e0-b65e-701a04e25543:base.main_address", }, - "amount_untaxed": 150.0, + "amount_untaxed": 350.0, "name": "PO00011", "__model": "purchase.order", "__last_update": False, @@ -85,27 +91,17 @@ assert new_sale_order_id, 'Sale order is not imported' - - I Checking the out invoice become in invoice or not after import ======== + I Checking the sale order become purchase order or not after import - - !python {model: account.invoice}: | + !python {model: purchase.order}: | - 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]) - 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.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' - product = ['Medium PC','Basic PC'] - for inv_line in invoice_new.invoice_line: - assert inv_line.account_id.id, "account_id is not taken from product's default" - assert inv_line.product_id.name in product, "product is not in Invoice line" - #print '-----------------=================',inv_line.product_id.quantity - assert inv_line.product_id.price_subtotal == 375, 'subtotal is not matched' - #assert inv_line.producr_id.quantity - for inv_tax in invoice_new.tax_line: - assert inv_tax.manual, "for tax line manual is not set to True" - assert inv_tax.account_id, "for tax_line default accounts is not picked based on the tax config of the DB where it is imported." + ids = self.search(cr, uid, [('partner_id','=','OpenERP S.A.')]) + 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" + for purchase_line in order_new.order_line: + assert purchase_line.name in ['basic pc','medium pc'], "name of product is not in order" + assert purchase_line.product_id.name in ['Basic PC','Medium PC'], "name of product is not in order" + assert purchase_line.date_planned == '2011-09-13' , "date of planned order is not same" From a2df13b0a197934cde5f2f2a725bcba3135ce565 Mon Sep 17 00:00:00 2001 From: "Harry (OpenERP)" Date: Thu, 15 Sep 2011 19:13:01 +0530 Subject: [PATCH 038/265] [IMP] edi: modified web_url bzr revid: hmo@tinyerp.com-20110915134301-jbjssv0p43v6lczm --- addons/account/edi_invoice_action_data.xml | 2 +- addons/purchase/edi_purchase_order_data.xml | 2 +- addons/sale/edi_sale_order_data.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/account/edi_invoice_action_data.xml b/addons/account/edi_invoice_action_data.xml index 22d3eb7dbdf..517628b434c 100644 --- a/addons/account/edi_invoice_action_data.xml +++ b/addons/account/edi_invoice_action_data.xml @@ -3,7 +3,7 @@ - context.update({'edi_web_invoice_url_view': '%s/edi/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])}) + context.update({'edi_web_invoice_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, 'account', 'email_template_edi_invoice')[1], diff --git a/addons/purchase/edi_purchase_order_data.xml b/addons/purchase/edi_purchase_order_data.xml index e99fe687b5d..7e6482b6ca1 100644 --- a/addons/purchase/edi_purchase_order_data.xml +++ b/addons/purchase/edi_purchase_order_data.xml @@ -3,7 +3,7 @@ - context.update({'edi_web_purchase_url_view': '%s/edi/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])}) + 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], diff --git a/addons/sale/edi_sale_order_data.xml b/addons/sale/edi_sale_order_data.xml index 0e9fa04b12e..66e38f40360 100644 --- a/addons/sale/edi_sale_order_data.xml +++ b/addons/sale/edi_sale_order_data.xml @@ -3,7 +3,7 @@ - context.update({'edi_web_sale_url_view': '%s/edi/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])}) + 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_email(cr, uid, self.pool.get('ir.model.data').get_object_reference(cr, uid, 'sale', 'email_template_edi_sale')[1], From c17142a45bc329931bb7ba59550fcdb4d7624b0c Mon Sep 17 00:00:00 2001 From: "Harry (OpenERP)" Date: Fri, 16 Sep 2011 12:13:19 +0530 Subject: [PATCH 039/265] [FIX] edi: correct yml and remove stuff to change model into sale and puchase EDI bzr revid: hmo@tinyerp.com-20110916064319-63zc227t9g8cxao2 --- addons/account/test/test_edi_invoice.yml | 3 -- addons/purchase/edi_purchase_order.py | 3 -- addons/purchase/test/edi_purchase_order.yml | 20 +++++------ addons/sale/edi_sale_order.py | 11 +++--- addons/sale/test/edi_sale_order.yml | 40 +++++++++++++++------ 5 files changed, 45 insertions(+), 32 deletions(-) diff --git a/addons/account/test/test_edi_invoice.yml b/addons/account/test/test_edi_invoice.yml index 843892a4573..0285e541156 100644 --- a/addons/account/test/test_edi_invoice.yml +++ b/addons/account/test/test_edi_invoice.yml @@ -151,9 +151,6 @@ 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.amount_total == 1010.0, "Amount total is not same" - assert invoice_new.amount_tax == 1000.0, "Amount tax is not same" - assert invoice_new.amount_untaxes == 10.0, "Amount untaxed is not same" product = ['Medium PC','Basic PC'] for inv_line in invoice_new.invoice_line: assert inv_line.account_id.id, "account_id is not taken from product's default" diff --git a/addons/purchase/edi_purchase_order.py b/addons/purchase/edi_purchase_order.py index cb19f57c103..8e3979eb8bd 100644 --- a/addons/purchase/edi_purchase_order.py +++ b/addons/purchase/edi_purchase_order.py @@ -124,9 +124,6 @@ class purchase_order(osv.osv, ir_edi.edi): if context is None: context = {} - model = edi_document['__model'] - assert model == 'sale.order', _('Could not import purchase order') - edi_document['__model'] = self._name #import company as a new partner partner_id = self.edi_import_company(cr, uid, edi_document, context=context) diff --git a/addons/purchase/test/edi_purchase_order.yml b/addons/purchase/test/edi_purchase_order.yml index a6dc45ee997..07f5179a65a 100644 --- a/addons/purchase/test/edi_purchase_order.yml +++ b/addons/purchase/test/edi_purchase_order.yml @@ -68,7 +68,7 @@ "name": "medium pc", "product_uom": ["724f93ec-ddd0-11e0-88ec-701a04e25543:product.product_uom_unit", "PCE"], "sequence": 11, - "price_unit": 200.0, + "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"] @@ -88,13 +88,13 @@ "date_order": "2011-09-13", "partner_id": ["724f93ec-ddd0-11e0-88ec-701a04e25543:sale.res_partner_test22", "Junjun wala"], "__attachments": [], - "__module": "sale", + "__module": "purchase", "amount_total": 350.0, "amount_untaxed": 350.0, "name": "SO008", - "__model": "sale.order", + "__model": "purchase.order", "__last_update": False, - "company_id": ["724f93ec-ddd0-11e0-88ec-701a04e25543:base.main_company", "OpenERP S.A."], + "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)"] } @@ -104,15 +104,15 @@ - I Checking the sale order become purchase order or not after import - - !python {model: sale.order}: | + !python {model: purchase.order}: | - ids = self.search(cr, uid, [('partner_id','=','OpenERP S.A.')]) + 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 order_new.amount_total == 350, "Amount total is not same" assert order_new.amount_untaxed == 350, "untaxed amount is not same" - for sale_line in order_new.order_line: - assert sale_line.name in ['basic pc','medium pc'], "name of product is not in order" - assert sale_line.product_id.name in ['Basic PC','Medium PC'], "name of product is not in order" - assert sale_line.date_order == '2011-09-13' , "date of order is not same" + for purchase_line in order_new.order_line: + assert purchase_line.name in ['basic pc','medium pc'], "name of product is not in order" + assert purchase_line.product_id.name in ['Basic PC','Medium PC'], "name of product is not in order" + assert purchase_line.date_order == '2011-09-13' , "date of order is not same" diff --git a/addons/sale/edi_sale_order.py b/addons/sale/edi_sale_order.py index 70a57a8d216..1baad0f59b5 100644 --- a/addons/sale/edi_sale_order.py +++ b/addons/sale/edi_sale_order.py @@ -122,9 +122,6 @@ class sale_order(osv.osv, ir_edi.edi): if context is None: context = {} - model = edi_document['__model'] - assert model == 'purchase.order', _('Could not import sale order') - edi_document['__model'] = self._name #import company as a new partner partner_id = self.edi_import_company(cr, uid, edi_document, context=context) @@ -135,9 +132,11 @@ class sale_order(osv.osv, ir_edi.edi): order_lines = edi_document['order_line'] for order_line in order_lines: order_line['product_uom_qty'] = order_line['product_qty'] - date_order = datetime.strptime(date_order, "%Y-%m-%d") - date_planned = datetime.strptime(order_line['date_planned'], "%Y-%m-%d") - order_line['delay'] = (date_planned - date_order).days + 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() diff --git a/addons/sale/test/edi_sale_order.yml b/addons/sale/test/edi_sale_order.yml index af1b32a6f01..cf8da5f1efb 100644 --- a/addons/sale/test/edi_sale_order.yml +++ b/addons/sale/test/edi_sale_order.yml @@ -56,19 +56,29 @@ "order_line": [{ "name": "basic pc", "product_uom": ["5af1272e-dd26-11e0-b65e-701a04e25543:product.product_uom_unit", "PCE"], - "date_planned": "2011-08-31", + "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": "purchase", + "__module": "sale", "amount_total": 350.0, "company_address": { "phone": "(+32).81.81.37.00", @@ -81,9 +91,9 @@ }, "amount_untaxed": 350.0, "name": "PO00011", - "__model": "purchase.order", + "__model": "sale.order", "__last_update": False, - "company_id": ["5af1272e-dd26-11e0-b65e-701a04e25543:base.main_company", "OpenERP S.A."], + "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)"] } @@ -93,15 +103,25 @@ - I Checking the sale order become purchase order or not after import - - !python {model: purchase.order}: | + !python {model: sale.order}: | - ids = self.search(cr, uid, [('partner_id','=','OpenERP S.A.')]) + 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" - for purchase_line in order_new.order_line: - assert purchase_line.name in ['basic pc','medium pc'], "name of product is not in order" - assert purchase_line.product_id.name in ['Basic PC','Medium PC'], "name of product is not in order" - assert purchase_line.date_planned == '2011-09-13' , "date of planned order is not same" + assert len(order_new.order_line) == 2, "sale lines are not same" + for sale_line in order_new.order_line: + if sale_line.name == 'basic pc': + assert sale_line.delay == 18 , "delay is not same" + 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.product_uom_qty == 1 , "product qty is not same" + elif sale_line.name == 'medium pc': + assert sale_line.delay == 3 , "delay is not same" + 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.product_uom_qty == 2 , "product qty is not same" + else: + assert 'wrong product imported in sale lines' From 16fd6962a098ad8f1a5e80fa769267281377e94f Mon Sep 17 00:00:00 2001 From: "Harry (OpenERP)" Date: Fri, 16 Sep 2011 15:06:11 +0530 Subject: [PATCH 040/265] [FIX] edi: typo and add some fields in export dict bzr revid: hmo@tinyerp.com-20110916093611-p5ee9b7for1gqx6a --- addons/purchase/edi_purchase_order.py | 8 +++++--- addons/sale/edi_sale_order.py | 8 +++++--- addons/sale/edi_sale_order_data.xml | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/addons/purchase/edi_purchase_order.py b/addons/purchase/edi_purchase_order.py index 8e3979eb8bd..e2791164c31 100644 --- a/addons/purchase/edi_purchase_order.py +++ b/addons/purchase/edi_purchase_order.py @@ -32,7 +32,8 @@ class purchase_order(osv.osv, ir_edi.edi): 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 @@ -50,12 +51,13 @@ class purchase_order(osv.osv, ir_edi.edi): 'order_line': { 'name': True, 'date_planned': True, - #SO: 'delay' : 'date_approve' - 'date_planned' - #PO: 'date_planned': 'date_approve' + 'delay' + #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' diff --git a/addons/sale/edi_sale_order.py b/addons/sale/edi_sale_order.py index 1baad0f59b5..e444f1371eb 100644 --- a/addons/sale/edi_sale_order.py +++ b/addons/sale/edi_sale_order.py @@ -32,6 +32,8 @@ class sale_order(osv.osv, ir_edi.edi): 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 @@ -50,8 +52,8 @@ class sale_order(osv.osv, ir_edi.edi): #PO: No 'name': True, 'delay': True, - #SO: 'delay' : 'date_approve' - 'date_planned' - #PO: 'date_planned': 'date_approve' + 'delay' + #SO: 'delay' : 'date_order' - 'date_planned' + #PO: 'date_planned': 'date_order' + 'delay' 'product_id': True, 'product_uom': True, @@ -59,7 +61,7 @@ class sale_order(osv.osv, ir_edi.edi): 'product_uom_qty': True, #SO: 'product_uom_qty' #PO: 'product_qty' - + 'price_subtotal': True, 'discount': True, #SO: yes #PO: No diff --git a/addons/sale/edi_sale_order_data.xml b/addons/sale/edi_sale_order_data.xml index 66e38f40360..04683d1a230 100644 --- a/addons/sale/edi_sale_order_data.xml +++ b/addons/sale/edi_sale_order_data.xml @@ -4,7 +4,7 @@ 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_email(cr, +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, From f8d9aeaca5dc410121495a046b55ac99ad051fc1 Mon Sep 17 00:00:00 2001 From: "Harry (OpenERP)" Date: Fri, 16 Sep 2011 15:40:31 +0530 Subject: [PATCH 041/265] [IMP] edi: Imporve Email Template of sale,purchase bzr revid: hmo@tinyerp.com-20110916101031-3lspjfm35e958qbr --- addons/purchase/edi_purchase_order_data.xml | 10 ++++------ addons/sale/edi_sale_order_data.xml | 10 ++++------ 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/addons/purchase/edi_purchase_order_data.xml b/addons/purchase/edi_purchase_order_data.xml index 7e6482b6ca1..02ecb24b9ba 100644 --- a/addons/purchase/edi_purchase_order_data.xml +++ b/addons/purchase/edi_purchase_order_data.xml @@ -36,30 +36,28 @@ if not object.partner_id.opt_out: self.pool.get('email.template').send_mail(cr, <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, print and pay invoice: <br/> +<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 /> Confirm date: ${object.date_approve 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 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> -${object.company_id.paypal_account and "<p>It is possible to pay with Paypal: <br/> <a href=\"https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=%s&item_name=OpenERP%%20Invoice%%20%s&invoice=%s&amount=%s&button_subtype=services&no_note=1&bn=OpenERP_Invoice_PayNow_%s\"><img src=\"https://www.paypalobjects.com/en_US/i/btn/btn_paynowCC_LG.gif\" style=\"margin-left: 100px; border: 0px; padding: 1px; text-decoration: none;\"/></a> </p>"%(object.company_id.paypal_account, object.name and object.name.replace('/','%2f') or '', object.name and object.name.replace('/','%2f') or '', object.amount_total) or ''} <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, print and pay invoice: +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}* -Approve date: ${object.date_approve or 'n/a'} +Order date: ${object.date_order or 'n/a'} Your contact: ${object.validator.name} ${object.validator.user_email and '<%s>'%(object.validator.user_email) or ''} -${object.company_id.paypal_account and "It is possible to pay with Paypal: https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=%s&item_name=OpenERP%%20Invoice%%20%s&invoice=%s&amount=%s&currency_code=%s&button_subtype=services&no_note=1&bn=OpenERP_Invoice_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) or ''} If you have any question, do not hesitate to reply directly to this e-mail. diff --git a/addons/sale/edi_sale_order_data.xml b/addons/sale/edi_sale_order_data.xml index 04683d1a230..33b65b4c031 100644 --- a/addons/sale/edi_sale_order_data.xml +++ b/addons/sale/edi_sale_order_data.xml @@ -36,30 +36,28 @@ if not object.partner_id.opt_out: self.pool.get('email.template').send_mail(cr, <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, print and pay invoice: <br/> +<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 /> Confirm date: ${object.date_confirm 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 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> -${object.company_id.paypal_account and "<p>It is possible to pay with Paypal: <br/> <a href=\"https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=%s&item_name=OpenERP%%20Invoice%%20%s&invoice=%s&amount=%s&button_subtype=services&no_note=1&bn=OpenERP_Invoice_PayNow_%s\"><img src=\"https://www.paypalobjects.com/en_US/i/btn/btn_paynowCC_LG.gif\" style=\"margin-left: 100px; border: 0px; padding: 1px; text-decoration: none;\"/></a> </p>"%(object.company_id.paypal_account, object.name and object.name.replace('/','%2f') or '', object.name and object.name.replace('/','%2f') or '', object.amount_total) or ''} <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, print and pay invoice: +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}* -Confirm date: ${object.date_confirm or 'n/a'} +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 ''} -${object.company_id.paypal_account and "It is possible to pay with Paypal: https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=%s&item_name=OpenERP%%20Invoice%%20%s&invoice=%s&amount=%s&currency_code=%s&button_subtype=services&no_note=1&bn=OpenERP_Invoice_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) or ''} If you have any question, do not hesitate to reply directly to this e-mail. From b3398647231a9d7ef414e2185f160c44773ac312 Mon Sep 17 00:00:00 2001 From: "Hardik Ansodariy (OpenERP)" Date: Fri, 16 Sep 2011 17:45:54 +0530 Subject: [PATCH 042/265] [imp] bzr revid: han@tinyerp.com-20110916121554-t3wt2v075jl5141u --- addons/sale/edi_sale_order_data.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sale/edi_sale_order_data.xml b/addons/sale/edi_sale_order_data.xml index 66e38f40360..04683d1a230 100644 --- a/addons/sale/edi_sale_order_data.xml +++ b/addons/sale/edi_sale_order_data.xml @@ -4,7 +4,7 @@ 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_email(cr, +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, From 6c17995fb7145e3b555e7004dc6fd5d7f1b8f4d9 Mon Sep 17 00:00:00 2001 From: "Vaibhav (OpenERP)" Date: Mon, 19 Sep 2011 15:27:30 +0530 Subject: [PATCH 043/265] [FIX] Extend with ViewManager. bzr revid: vda@tinyerp.com-20110919095730-toavlykgeokcg4d0 --- addons/web_process/static/src/js/process.js | 99 ++++++-------- .../static/src/xml/web_process.xml | 128 +++++++++--------- 2 files changed, 106 insertions(+), 121 deletions(-) diff --git a/addons/web_process/static/src/js/process.js b/addons/web_process/static/src/js/process.js index 40f4663c08a..b1665e44a7a 100644 --- a/addons/web_process/static/src/js/process.js +++ b/addons/web_process/static/src/js/process.js @@ -2,77 +2,69 @@ openerp.web_process = function (openerp) { var QWeb = openerp.web.qweb; QWeb.add_template('/web_process/static/src/xml/web_process.xml'); - openerp.web.ViewManagerAction.include({ - on_mode_switch: function (view_type) { + openerp.web.ViewManager.include({ + start: function() { + this._super(); var self = this; + + this.process_check(); + }, + process_check: function() { + var self = this, + grandparent = this.widget_parent && this.widget_parent.widget_parent, + view = this.views[this.views_src[0].view_type], + $process_view = this.$element.find('.oe-process-view'); + this.process_model = this.model; - return $.when( - this._super(view_type), - this.process_check(this.views[view_type])).then(function () { - }); - }, - process_check: function(view) { - var self = this; - var grandparent = this.widget_parent && this.widget_parent.widget_parent; - // display shortcuts if on the first view for the action - var $process_toggle = this.$element.find('.oe-process-toggle'); - if (!(grandparent instanceof openerp.web.WebClient) || + if (!(grandparent instanceof openerp.web.WebClient) || !(view.view_type === this.views_src[0].view_type && view.view_id === this.views_src[0].view_id)) { - $process_toggle.hide(); + $process_view.hide(); return; } - $process_toggle.show(); - $process_toggle - .unbind("click") - .click(function(){ - $.when(self.load_process()).then(self.get_process_id()); - }); - }, - - load_process: function() { -// this.widget_parent.$element.html(QWeb.render("ProcessView",this)); - this.$element.html(QWeb.render("ProcessView",this)); - }, - - get_process_id: function() { - var self = this; - this.process_dataset = new openerp.web.DataSetStatic(this, "process.process", this.session.context); - this.process_dataset - .call( - "search_by_model", - [self.process_model,self.session.context], - function(res) { - self.renderer(res); - } - ); - }, - - renderer: function(res) { + $process_view.click(function() { + $.when(self.load_process()).then(self.get_process_id()); + }); + }, + + load_process: function() { + this.$element.html(QWeb.render("ProcessView",this)); + }, + + get_process_id: function() { + var self = this; + this.process_dataset = new openerp.web.DataSetStatic(this, "process.process", this.session.context); + this.process_dataset + .call( + "search_by_model", + [self.process_model,self.session.context], + function(res) {self.process_renderer(res)} + ); + }, + + process_renderer: function(res) { var self = this; if(!res.length) { this.process_model = false; this.get_process_id(); } else { - if(res.length > 1) { this.selection = res; - $.when(this.load_process()).then(function() { - self.widget_parent.$element.find('#change_process').click(function(){ - - self.p_id = self.widget_parent.$element.find('#select_process').val(); - $.when(self.load_process()).then(self.render_process_view()); - + $.when(this.load_process()) + .then(function(){ + var $parent = self.widget_parent.$element; + $parent.find('#change_process').click(function() { + self.selection = false; + self.p_id = $parent.find('#select_process').val(); + $.when(self.load_process()).then(self.render_process_view()); + }); }); - }); - } - else { + } else { this.p_id = res[0][0]; $.when(this.load_process()).then(this.render_process_view()); } } }, - render_process_view: function() { var self = this; this.p_id = parseInt(this.p_id, 10); @@ -150,7 +142,7 @@ QWeb.add_template('/web_process/static/src/xml/web_process.xml'); .push(process_node) .push(process_node_text) .push(process_node_desc); - process_node.mousedown(function(){ + process_node.mousedown(function() { return false; }) return process_set; @@ -189,7 +181,6 @@ QWeb.add_template('/web_process/static/src/xml/web_process.xml'); } ); } - }); }; diff --git a/addons/web_process/static/src/xml/web_process.xml b/addons/web_process/static/src/xml/web_process.xml index 6634f6d8446..11037671e01 100644 --- a/addons/web_process/static/src/xml/web_process.xml +++ b/addons/web_process/static/src/xml/web_process.xml @@ -1,73 +1,67 @@ From 95b859a4f9d7af4069c53bde065bd4a860c729c2 Mon Sep 17 00:00:00 2001 From: "Hardik Ansodariy (OpenERP)" Date: Tue, 20 Sep 2011 14:28:46 +0530 Subject: [PATCH 044/265] [imp] set currency id bzr revid: han@tinyerp.com-20110920085846-dxdr6fbjtw7ltedy --- addons/purchase/edi_purchase_order.py | 3 ++- addons/sale/edi_sale_order.py | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/addons/purchase/edi_purchase_order.py b/addons/purchase/edi_purchase_order.py index 31017daceb1..9119485bffc 100644 --- a/addons/purchase/edi_purchase_order.py +++ b/addons/purchase/edi_purchase_order.py @@ -73,12 +73,13 @@ class purchase_order(osv.osv, ir_edi.edi): 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': edi_company_document['currency_id'], + '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) diff --git a/addons/sale/edi_sale_order.py b/addons/sale/edi_sale_order.py index eddeb618926..69165de9b85 100644 --- a/addons/sale/edi_sale_order.py +++ b/addons/sale/edi_sale_order.py @@ -77,12 +77,12 @@ class sale_order(osv.osv, ir_edi.edi): 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': edi_company_document['currency_id'], + '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) From 83ad47b00373c87a459c29ca3d542e90b3030e90 Mon Sep 17 00:00:00 2001 From: "Vaibhav (OpenERP)" Date: Tue, 20 Sep 2011 22:38:19 +0530 Subject: [PATCH 045/265] [ADD] node images. bzr revid: vda@tinyerp.com-20110920170819-kn0a3uwa32m610v7 --- addons/web_process/static/src/img/ToolOval.jpg | Bin 0 -> 650 bytes .../web_process/static/src/img/ToolShowGrid.jpg | Bin 0 -> 635 bytes .../web_process/static/src/img/ToolShowGrid.png | Bin 0 -> 810 bytes addons/web_process/static/src/img/button-a-a.png | Bin 0 -> 6595 bytes addons/web_process/static/src/img/grid_10.jpg | Bin 0 -> 4530 bytes .../web_process/static/src/img/node-current.png | Bin 0 -> 2472 bytes addons/web_process/static/src/img/node-gray.png | Bin 0 -> 2445 bytes .../static/src/img/node-subflow-gray.png | Bin 0 -> 5105 bytes .../web_process/static/src/img/node-subflow.png | Bin 0 -> 5153 bytes addons/web_process/static/src/img/node.png | Bin 0 -> 2503 bytes addons/web_process/static/src/img/port.gif | Bin 0 -> 166 bytes addons/web_process/static/src/img/window_bg.png | Bin 0 -> 128 bytes .../static/src/img/window_toolbar.png | Bin 0 -> 200 bytes 13 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 addons/web_process/static/src/img/ToolOval.jpg create mode 100644 addons/web_process/static/src/img/ToolShowGrid.jpg create mode 100644 addons/web_process/static/src/img/ToolShowGrid.png create mode 100644 addons/web_process/static/src/img/button-a-a.png create mode 100644 addons/web_process/static/src/img/grid_10.jpg create mode 100644 addons/web_process/static/src/img/node-current.png create mode 100644 addons/web_process/static/src/img/node-gray.png create mode 100644 addons/web_process/static/src/img/node-subflow-gray.png create mode 100644 addons/web_process/static/src/img/node-subflow.png create mode 100644 addons/web_process/static/src/img/node.png create mode 100644 addons/web_process/static/src/img/port.gif create mode 100644 addons/web_process/static/src/img/window_bg.png create mode 100644 addons/web_process/static/src/img/window_toolbar.png diff --git a/addons/web_process/static/src/img/ToolOval.jpg b/addons/web_process/static/src/img/ToolOval.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c30f15a07d27df0d0e0b9baf91a444f74f00482c GIT binary patch literal 650 zcmex=PKLX?fy#VwC z5@2KJUZf(oWdIz%Q+VDQP)%Q^J;!30MZp(R4sLSK9@_^NqH?lZ^D)bA0g*Qb}n zO5Q#e_FW?W>~7tETP~T0X%{Ur5B|2>gs=S2i=8gsMpr$zzYA3KShdKt;LvfAsr+}D zW!7+Q_}s1MThX~!=}Ft%#mk@FP7xAJRJbvBqy28F*_q2)_8pPnk(!dc#Csp}p|Uzj z_fWYzUrkF(H+{Pne$8sHt0T*UHK$fFEwEU%f`NN>?2Ku%vNm~Ir5s>LnE(GK0H}(` AdH?_b literal 0 HcmV?d00001 diff --git a/addons/web_process/static/src/img/ToolShowGrid.jpg b/addons/web_process/static/src/img/ToolShowGrid.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8285acc8aaca324c30f67748dec386d635ff9ba5 GIT binary patch literal 635 zcmex=PKLX?fy#VwC z5@2Cv;{eL&3NSD-0|65YJ5-X15$FdtK?WgVMI}d(M0PR5g`&!;M$UmjAcGhgm{HAP zVrF3gSs^KiF2xA6Uy=F$Ee0ND5R+Mu!JgsEl`mUwe}3WQ#A03eP{!1Mf7s2LofCIx zbTlPTdE+mCZ@Fajg@qbV{>JX!wlczn-{YJ6gqFHJ`^;;%&Mwmb;ou6@yJg zP918fD|dBuIraPH(kjV}`{vmu@4UU@oIYkf?A;k;;ntEVvsBA2p_nbDW%Zu=`(5%dxgOlE%-&H~m(-KB;N?%t@2yN2aUnDC=MP d&`ogfU*SEQy7%9fxa?~pwmCh*flc`TO#pL)yWao+ literal 0 HcmV?d00001 diff --git a/addons/web_process/static/src/img/ToolShowGrid.png b/addons/web_process/static/src/img/ToolShowGrid.png new file mode 100644 index 0000000000000000000000000000000000000000..ea530671b97bb7e150e4a8cf5097f2bd0d2a073f GIT binary patch literal 810 zcmbV}?N3s16vuB_p>EoGVK!M0qSJgRUexBAFU)2buFMQ`EjP`WT9#UCYt?2-rI96q z8f2}qk)};+u$oy$2s%eNpQX$Mf#ULTFZW*H-av$Y{tKP$JnZv5=fydPpO>2*5gro` zK~MzyNLD_`+txfZ1VmlWxCVmON%M|!4hMt5V%X=K{>9w{kV5X zGYd$)P&%TW4Fm$zUtilR8Af;l0f2+*$p!yvz(aYRxZCd!I0-jNc}FG}fTZ{~?zCPPw4y*QsBEa=N#vh3F4B)+ zl*Nt{{0 zuAgRf-e8+E*kr01z~7I|nH-b}p_X9chZ!|GsPATU$wC0>#)FqK#l*6mT>OLUjEK&( zw#)UVmvZ&oJLPoWmx(^b1R(!y`Kmp|;BD)!=I5S-4*vOG2I~FntW3^s;kl9*$t7HF zDGN$qv9=CuNTH|G66th$A}yVs5*HWE;qjj|iUq}W;=;VT=K^u#6Lx5_GBuUK&@dDB zG8jr`5`!_48qwM!Y;Uy`wzL;;3}SJ6LFuUmb`2I65?K}{xzpP*xJl8~@#sUOqQ9df zS-yjFNdI+mOrlrM&T60Phqco=`WUo`ekQ&4CXGhRu1%!TS*&tNWOQNLwc5?cnbkXM zi>otktwNIR^_iJUe{5#w*;xN_XXh5JaG)q^W9z+U{zH>Mz~{3Kf+jwjo6BRzcT2nQ z?s6`dOO(Ho#_uav4JRk2F`p}TF_~{$GBTKHjXk00qEVFJEE9=DSDL3qrL58LBK$;H x`|IBRp1wEL6&Ej5oxfD+gdMhoq-SC4Au{Jc{fSR!u7hJj?8CWP{fA0;{{She3Df`p literal 0 HcmV?d00001 diff --git a/addons/web_process/static/src/img/button-a-a.png b/addons/web_process/static/src/img/button-a-a.png new file mode 100644 index 0000000000000000000000000000000000000000..bd046bbbef7da60895536a7a18323abbbe21e7fb GIT binary patch literal 6595 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 AIsgCw literal 0 HcmV?d00001 diff --git a/addons/web_process/static/src/img/grid_10.jpg b/addons/web_process/static/src/img/grid_10.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5254207b96407a79195cd541dfb145417e8bdb30 GIT binary patch literal 4530 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 literal 0 HcmV?d00001 diff --git a/addons/web_process/static/src/img/node-gray.png b/addons/web_process/static/src/img/node-gray.png new file mode 100644 index 0000000000000000000000000000000000000000..2334abbc2fef44e2c9577a94f19e3baed713a8d0 GIT binary patch literal 2445 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 literal 0 HcmV?d00001 diff --git a/addons/web_process/static/src/img/node-subflow-gray.png b/addons/web_process/static/src/img/node-subflow-gray.png new file mode 100644 index 0000000000000000000000000000000000000000..7703eedd2f0c9252ddc69d4a0437bf24c91915ca GIT binary patch literal 5105 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 literal 0 HcmV?d00001 diff --git a/addons/web_process/static/src/img/node.png b/addons/web_process/static/src/img/node.png new file mode 100644 index 0000000000000000000000000000000000000000..4ed3681fa8d10986952d531dfa9838dc0b8d9d3d GIT binary patch literal 2503 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 a`J7+mD_7u#+WR#?tqh*7elF{r5}E+Ip)ZjD literal 0 HcmV?d00001 diff --git a/addons/web_process/static/src/img/window_toolbar.png b/addons/web_process/static/src/img/window_toolbar.png new file mode 100644 index 0000000000000000000000000000000000000000..77c30b79d828448d0d87b6654424e77b19375de7 GIT binary patch literal 200 zcmeAS@N?(olHy`uVBq!ia0vp^F+eQB!2~4x+s^U*D&i&7I%`2HW3thI00 sEMM&1Ed7LmVYegSF$o|yPFBV4Z=>e6lX{}sKvyt$y85}Sb4q9e0HWbZS^xk5 literal 0 HcmV?d00001 From 8ab9a5ecf946d87a0bf6673de7ead6438c1aa879 Mon Sep 17 00:00:00 2001 From: "Vaibhav (OpenERP)" Date: Tue, 20 Sep 2011 22:43:15 +0530 Subject: [PATCH 046/265] [FIX] typo. bzr revid: vda@tinyerp.com-20110920171315-k1aambijdl9ih04n --- addons/web_process/static/src/js/process.js | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/web_process/static/src/js/process.js b/addons/web_process/static/src/js/process.js index b1665e44a7a..a9cd506bc57 100644 --- a/addons/web_process/static/src/js/process.js +++ b/addons/web_process/static/src/js/process.js @@ -83,6 +83,7 @@ QWeb.add_template('/web_process/static/src/xml/web_process.xml'); }, draw_process_graph: function(res) { + var self = this; var process_graph = new Graph(); var process_renderer = function(r, n) { From d05651bebe85660224b97c05c70c6e215651cde8 Mon Sep 17 00:00:00 2001 From: "Vaibhav (OpenERP)" Date: Tue, 20 Sep 2011 23:00:31 +0530 Subject: [PATCH 047/265] [FIX] Does not allowed drag&drop. bzr revid: vda@tinyerp.com-20110920173031-ialtmcpub2c24k04 --- addons/web_process/static/src/js/process.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/addons/web_process/static/src/js/process.js b/addons/web_process/static/src/js/process.js index a9cd506bc57..b6642a7980b 100644 --- a/addons/web_process/static/src/js/process.js +++ b/addons/web_process/static/src/js/process.js @@ -105,7 +105,11 @@ QWeb.add_template('/web_process/static/src/xml/web_process.xml'); bg = n.node.gray ? bg + "-gray" : bg; img_src = '/web_process/static/src/img/'+ bg + '.png'; - r['image'](img_src, n.node.x, n.node.y,150, 100).attr({"clip-rect": clip_rect}); + r['image'](img_src, n.node.x, n.node.y,150, 100) + .attr({"clip-rect": clip_rect}) + .mousedown(function(){ + return false; + }); //Node process_node = r['rect'](n.node.x, n.node.y, 150, 100); @@ -143,9 +147,9 @@ QWeb.add_template('/web_process/static/src/xml/web_process.xml'); .push(process_node) .push(process_node_text) .push(process_node_desc); - process_node.mousedown(function() { + process_set.mousedown(function() { return false; - }) + }); return process_set; }; From e070274115ad2c87a16353c08e2d3d3725476bd3 Mon Sep 17 00:00:00 2001 From: "Vaibhav (OpenERP)" Date: Wed, 21 Sep 2011 12:16:40 +0530 Subject: [PATCH 048/265] [FIX] subflow id. bzr revid: vda@tinyerp.com-20110921064640-0j7ikcpvuaivicc7 --- addons/web_process/static/src/js/process.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/web_process/static/src/js/process.js b/addons/web_process/static/src/js/process.js index b6642a7980b..67bb8791441 100644 --- a/addons/web_process/static/src/js/process.js +++ b/addons/web_process/static/src/js/process.js @@ -120,7 +120,7 @@ QWeb.add_template('/web_process/static/src/xml/web_process.xml'); if(n.node.subflow) { process_node_text.click(function() { - self.p_id = n.node.id; + self.p_id = n.node.subflow[0]; $.when(self.load_process()).then(self.render_process_view()); }); } From 1aa8f369002c762441d409839581d94817ca2015 Mon Sep 17 00:00:00 2001 From: "Vaibhav (OpenERP)" Date: Wed, 21 Sep 2011 13:07:29 +0530 Subject: [PATCH 049/265] [FIX] do not show border on rect.background image.desc node does not need to add in set. bzr revid: vda@tinyerp.com-20110921073729-zqjijfseuz4ipc1h --- addons/web_process/static/src/js/process.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/addons/web_process/static/src/js/process.js b/addons/web_process/static/src/js/process.js index 67bb8791441..11b44e87d93 100644 --- a/addons/web_process/static/src/js/process.js +++ b/addons/web_process/static/src/js/process.js @@ -112,7 +112,7 @@ QWeb.add_template('/web_process/static/src/xml/web_process.xml'); }); //Node - process_node = r['rect'](n.node.x, n.node.y, 150, 100); + process_node = r['rect'](n.node.x, n.node.y, 150, 100).attr({stroke: "none"}); // Node text process_node_text = r.text(text_position_x, n.node.y+10, (n.node.name)) @@ -128,7 +128,6 @@ QWeb.add_template('/web_process/static/src/xml/web_process.xml'); //Node Description process_node_desc = r.text(n.node.x+75, n.node.y+50, (n.node.notes)); - r['image']('/web/static/src/img/icons/gtk-info.png', n.node.x+20, n.node.y+70, 16, 16) .attr({"cursor": "pointer", "title": "Help"}) .click(function(){ @@ -139,14 +138,13 @@ QWeb.add_template('/web_process/static/src/xml/web_process.xml'); r['image']('/web/static/src/img/icons/gtk-jump-to.png', n.node.x+115, n.node.y+70, 16, 16) .attr({"cursor": "pointer", "title": n.node.menu.name}) .click(function() { - self.jump_to_view(n.node.res_model, n.node.menu.id) + self.jump_to_view(n.node.res_model, n.node.menu.id); }); } process_set = r.set() .push(process_node) - .push(process_node_text) - .push(process_node_desc); + .push(process_node_text); process_set.mousedown(function() { return false; }); From 6ca5e79d89e8e56b15955c4795f1f955a3673315 Mon Sep 17 00:00:00 2001 From: "Vaibhav (OpenERP)" Date: Wed, 21 Sep 2011 13:34:18 +0530 Subject: [PATCH 050/265] [FIX] node text not in set. bzr revid: vda@tinyerp.com-20110921080418-vlfezcpkcrj84tbe --- addons/web_process/static/src/js/process.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/addons/web_process/static/src/js/process.js b/addons/web_process/static/src/js/process.js index 11b44e87d93..362bbd8e108 100644 --- a/addons/web_process/static/src/js/process.js +++ b/addons/web_process/static/src/js/process.js @@ -116,7 +116,7 @@ QWeb.add_template('/web_process/static/src/xml/web_process.xml'); // Node text process_node_text = r.text(text_position_x, n.node.y+10, (n.node.name)) - .attr({"fill": "#fff", "font-weight": "bold"}); + .attr({"fill": "#fff", "font-weight": "bold", "cursor": "pointer"}); if(n.node.subflow) { process_node_text.click(function() { @@ -144,7 +144,6 @@ QWeb.add_template('/web_process/static/src/xml/web_process.xml'); process_set = r.set() .push(process_node) - .push(process_node_text); process_set.mousedown(function() { return false; }); From a7a256454283f4b6a1241abd9df335a23ef16785 Mon Sep 17 00:00:00 2001 From: "Vaibhav (OpenERP)" Date: Wed, 21 Sep 2011 15:18:23 +0530 Subject: [PATCH 051/265] [FIX] Load subflow actions. bzr revid: vda@tinyerp.com-20110921094823-4rrqbdov4s0csk0t --- addons/web_process/static/src/js/process.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/addons/web_process/static/src/js/process.js b/addons/web_process/static/src/js/process.js index 362bbd8e108..67c62efbcd4 100644 --- a/addons/web_process/static/src/js/process.js +++ b/addons/web_process/static/src/js/process.js @@ -176,10 +176,16 @@ QWeb.add_template('/web_process/static/src/xml/web_process.xml'); .call('get', ['action', 'tree_but_open',[['ir.ui.menu', id]], dataset.context], function(res) { + self.$element.empty(); var action = res[0][res[0].length - 1]; - var action_manager = new openerp.web.ActionManager(self); - action_manager.appendTo(self.widget_parent.$element); - action_manager.do_action(action); + self.rpc("/web/action/load", { + action_id: action.id, + context: dataset.context + }, function(result) { + var action_manager = new openerp.web.ActionManager(self); + action_manager.appendTo(self.widget_parent.$element); + action_manager.do_action(result.result); + }); } ); } From 78eb1e13e5a5284854a17cd90d14174b5702be79 Mon Sep 17 00:00:00 2001 From: "Vaibhav (OpenERP)" Date: Wed, 28 Sep 2011 14:17:39 +0530 Subject: [PATCH 052/265] [FIX] Indentation.Show help. bzr revid: vda@tinyerp.com-20110928084739-cd0tnajmulohp0k8 --- addons/web_process/static/src/js/process.js | 387 +++++++++--------- .../static/src/xml/web_process.xml | 134 +++--- 2 files changed, 269 insertions(+), 252 deletions(-) diff --git a/addons/web_process/static/src/js/process.js b/addons/web_process/static/src/js/process.js index 67c62efbcd4..d8d178ae63d 100644 --- a/addons/web_process/static/src/js/process.js +++ b/addons/web_process/static/src/js/process.js @@ -1,195 +1,208 @@ - openerp.web_process = function (openerp) { -var QWeb = openerp.web.qweb; -QWeb.add_template('/web_process/static/src/xml/web_process.xml'); - openerp.web.ViewManager.include({ - start: function() { - this._super(); - var self = this; - - this.process_check(); - }, - process_check: function() { - var self = this, - grandparent = this.widget_parent && this.widget_parent.widget_parent, - view = this.views[this.views_src[0].view_type], - $process_view = this.$element.find('.oe-process-view'); - - this.process_model = this.model; - if (!(grandparent instanceof openerp.web.WebClient) || + var QWeb = openerp.web.qweb; + QWeb.add_template('/web_process/static/src/xml/web_process.xml'); + openerp.web.ViewManager.include({ + start: function() { + this._super(); + var self = this; + this.process_check(); + this.process_help = this.action.help || 'Help: Not Defined'; + }, + process_check: function() { + var self = this, + grandparent = this.widget_parent && this.widget_parent.widget_parent, + view = this.views[this.views_src[0].view_type], + $process_view = this.$element.find('.oe-process-view'); + + this.process_model = this.model; + if (!(grandparent instanceof openerp.web.WebClient) || !(view.view_type === this.views_src[0].view_type && view.view_id === this.views_src[0].view_id)) { - $process_view.hide(); - return; + $process_view.hide(); + return; } - $process_view.click(function() { - $.when(self.load_process()).then(self.get_process_id()); - }); - }, - - load_process: function() { - this.$element.html(QWeb.render("ProcessView",this)); - }, - - get_process_id: function() { - var self = this; - this.process_dataset = new openerp.web.DataSetStatic(this, "process.process", this.session.context); - this.process_dataset - .call( - "search_by_model", - [self.process_model,self.session.context], - function(res) {self.process_renderer(res)} - ); - }, - - process_renderer: function(res) { - var self = this; - if(!res.length) { - this.process_model = false; - this.get_process_id(); - } else { - if(res.length > 1) { - this.selection = res; - $.when(this.load_process()) - .then(function(){ - var $parent = self.widget_parent.$element; - $parent.find('#change_process').click(function() { - self.selection = false; - self.p_id = $parent.find('#select_process').val(); - $.when(self.load_process()).then(self.render_process_view()); - }); - }); - } else { - this.p_id = res[0][0]; - $.when(this.load_process()).then(this.render_process_view()); - } - } - }, - render_process_view: function() { - var self = this; - this.p_id = parseInt(this.p_id, 10); - this.process_dataset - .call( - "graph_get", - [self.p_id, self.model, false, [80,80,150,100]], - function(res) { - res['title'] = res.resource ? res.resource : res.name; - self.process_dataset.call("search_by_model",[self.model,self.session.context],function(r){ - res['related'] = r; - }); - self.draw_process_graph(res); - } - ); - }, - - draw_process_graph: function(res) { - var self = this; - var process_graph = new Graph(); - - var process_renderer = function(r, n) { - var process_node, - process_node_text, - process_node_desc, - process_set; - - var node_button, - node_menu, - img_src; - - var bg = "node"; - var clip_rect = "".concat(n.node.x,",",n.node.y,",150,100"); - var text_position_x = n.node.kind == "subflow" ? n.node.x+88 : n.node.x+75; - - //Image part - bg = n.node.kind == "subflow" ? "node-subflow" : "node"; - bg = n.node.gray ? bg + "-gray" : bg; - img_src = '/web_process/static/src/img/'+ bg + '.png'; - - r['image'](img_src, n.node.x, n.node.y,150, 100) - .attr({"clip-rect": clip_rect}) - .mousedown(function(){ - return false; - }); - - //Node - process_node = r['rect'](n.node.x, n.node.y, 150, 100).attr({stroke: "none"}); - - // Node text - process_node_text = r.text(text_position_x, n.node.y+10, (n.node.name)) - .attr({"fill": "#fff", "font-weight": "bold", "cursor": "pointer"}); - - if(n.node.subflow) { - process_node_text.click(function() { - self.p_id = n.node.subflow[0]; - $.when(self.load_process()).then(self.render_process_view()); - }); - } - - //Node Description - process_node_desc = r.text(n.node.x+75, n.node.y+50, (n.node.notes)); - - r['image']('/web/static/src/img/icons/gtk-info.png', n.node.x+20, n.node.y+70, 16, 16) - .attr({"cursor": "pointer", "title": "Help"}) - .click(function(){ - window.open(n.node.url || "http://doc.openerp.com/v6.0/index.php?model=" + n.node.model); - }); - - if(n.node.menu) { - r['image']('/web/static/src/img/icons/gtk-jump-to.png', n.node.x+115, n.node.y+70, 16, 16) - .attr({"cursor": "pointer", "title": n.node.menu.name}) - .click(function() { - self.jump_to_view(n.node.res_model, n.node.menu.id); - }); - } - - process_set = r.set() - .push(process_node) + $process_view.click(function() { + $.when(self.load_process()).then(self.get_process_id()); + }); + }, + + process_subflow : function() { + var self = this; + new openerp.web.DataSetSearch(this, + "ir.actions.act_window",this.session.context,[]) + .read_slice(['help'], + { domain: + [ + ['res_model','=',this.process_action_model], + ['name','ilike', this.process_action_name] + ] + }, + function(res) { + if (res.length) { + self.process_help = res[0]['help'] || 'Help: Not Defined'; + } + $.when(self.load_process()).then(self.render_process_view()); + + }); + }, + + load_process: function() { + this.$element.html(QWeb.render("ProcessView", this)); + }, + + get_process_id: function() { + var self = this; + this.process_dataset = new openerp.web.DataSetStatic(this, "process.process", this.session.context); + this.process_dataset.call("search_by_model", + [self.process_model,self.session.context], + function(res) {self.process_renderer(res)}); + }, + process_renderer: function(res) { + var self = this; + if(!res.length) { + this.process_model = false; + this.get_process_id(); + } else { + if(res.length > 1) { + this.selection = res; + $.when(this.load_process()).then(function() { + var $parent = self.widget_parent.$element; + $parent.find('#change_process').click(function() { + self.selection = false; + self.p_id = $parent.find('#select_process').val(); + $.when(self.load_process()).then(self.render_process_view()); + }); + }); + } else { + this.p_id = res[0][0]; + $.when(this.load_process()).then(this.render_process_view()); + } + } + }, + + render_process_view: function() { + var self = this; + this.p_id = parseInt(this.p_id, 10); + this.process_dataset.call("graph_get", + [self.p_id, self.model, false, [80,80,150,100]], + function(res) { + res['title'] = res.resource ? res.resource : res.name; + self.process_dataset.call("search_by_model", + [self.model,self.session.context], + function(r) { + res['related'] = r; + }); + self.draw_process_graph(res); + } + ); + }, + + draw_process_graph: function(res) { + var self = this; + var process_graph = new Graph(); + + var process_renderer = function(r, n) { + var process_node, + process_node_text, + process_node_desc, + process_set; + + var node_button, + node_menu, + img_src; + + var bg = "node", + clip_rect = "".concat(n.node.x,",",n.node.y,",150,100"), +// text_position_x = n.node.x + (n.node.y/2) + + //Image part + bg = n.node.kind == "subflow" ? "node-subflow" : "node"; + bg = n.node.gray ? bg + "-gray" : bg; + img_src = '/web_process/static/src/img/'+ bg + '.png'; + + r['image'](img_src, n.node.x, n.node.y,150, 100) + .attr({"clip-rect": clip_rect}) + .mousedown(function(){ + return false; + }); + + //Node + process_node = r['rect'](n.node.x, n.node.y, 150, 100).attr({stroke: "none"}); + // Node text + process_node_text = r.text(n.node.x, n.node.y, (n.node.name)) + .attr({"fill": "#fff", "font-weight": "bold", "cursor": "pointer"}); + process_node_text.translate(n.node.x / 2, 10) + if(n.node.subflow) { + process_node_text.click(function() { + self.p_id = n.node.subflow[0]; + self.process_action_model = n.node.model; + self.process_action_name = n.node.name; + self.process_subflow(); + }); + } + + //Node Description + process_node_desc = r.text(n.node.x+75, n.node.y+50, (n.node.notes)); + + r['image']('/web/static/src/img/icons/gtk-info.png', n.node.x+20, n.node.y+70, 16, 16) + .attr({"cursor": "pointer", "title": "Help"}) + .click(function() { + window.open(n.node.url || "http://doc.openerp.com/v6.0/index.php?model=" + n.node.model); + }); + + if(n.node.menu) { + r['image']('/web/static/src/img/icons/gtk-jump-to.png', n.node.x+115, n.node.y+70, 16, 16) + .attr({"cursor": "pointer", "title": n.node.menu.name}) + .click(function() { + self.jump_to_view(n.node.res_model, n.node.menu.id); + }); + } + + process_set = r.set().push(process_node); process_set.mousedown(function() { - return false; - }); - return process_set; - }; - - _.each(res['nodes'],function(node, node_id) { - node['res_model'] = self.model, - node['res_id'] = false, - node['id'] = node_id; - process_graph.addNode(node['name'], {node: node,render: process_renderer}); - }); - - _.each(res['transitions'], function(transitions) { - - var src = res['nodes'][transitions['source']]; - var dst = res['nodes'][transitions['target']]; - // make active - transitions['active'] = src.active && !dst.gray; - process_graph.addEdge(src['name'], dst['name'], {directed : true, label: transitions['name']}) - }); - var layouter = new Graph.Layout.Ordered(process_graph); - var render_process_graph = new Graph.Renderer.Raphael('process_canvas', process_graph, $('#process_canvas').width(), $('#process_canvas').height()); - }, - - jump_to_view: function(model, id) { - var self = this; - var dataset = new openerp.web.DataSetStatic(this, 'ir.values', this.session.context); - dataset - .call('get', - ['action', 'tree_but_open',[['ir.ui.menu', id]], dataset.context], - function(res) { - self.$element.empty(); - var action = res[0][res[0].length - 1]; - self.rpc("/web/action/load", { - action_id: action.id, - context: dataset.context - }, function(result) { - var action_manager = new openerp.web.ActionManager(self); - action_manager.appendTo(self.widget_parent.$element); - action_manager.do_action(result.result); - }); - } - ); - } - }); + return false; + }); + return process_set; + }; + + _.each(res['nodes'],function(node, node_id) { + node['res_model'] = self.model, + node['res_id'] = false, + node['id'] = node_id; + process_graph.addNode(node['name'], {node: node,render: process_renderer}); + }); + + _.each(res['transitions'], function(transitions) { + var src = res['nodes'][transitions['source']]; + var dst = res['nodes'][transitions['target']]; + // make active + transitions['active'] = src.active && !dst.gray; + process_graph.addEdge(src['name'], dst['name'], {directed : true}); + }); + + var layouter = new Graph.Layout.Ordered(process_graph); + var render_process_graph = new Graph.Renderer.Raphael('process_canvas', process_graph, $('#process_canvas').width(), $('#process_canvas').height()); + }, + + jump_to_view: function(model, id) { + var self = this; + var dataset = new openerp.web.DataSetStatic(this, 'ir.values', this.session.context); + dataset.call('get', + ['action', 'tree_but_open',[['ir.ui.menu', id]], dataset.context], + function(res) { + self.$element.empty(); + var action = res[0][res[0].length - 1]; + self.rpc("/web/action/load", { + action_id: action.id, + context: dataset.context + }, function(result) { + var action_manager = new openerp.web.ActionManager(self); + action_manager.appendTo(self.widget_parent.$element); + action_manager.do_action(result.result); + }); + }); + } + }); }; diff --git a/addons/web_process/static/src/xml/web_process.xml b/addons/web_process/static/src/xml/web_process.xml index 11037671e01..94ab8e870f2 100644 --- a/addons/web_process/static/src/xml/web_process.xml +++ b/addons/web_process/static/src/xml/web_process.xml @@ -1,67 +1,71 @@ From c029638da64a180827a75b47455c047a85a5193d Mon Sep 17 00:00:00 2001 From: "Yogesh (OpenERP)" Date: Wed, 28 Sep 2011 17:53:10 +0530 Subject: [PATCH 053/265] [IMP] process :- string display in node. bzr revid: ysa@tinyerp.com-20110928122310-dnijca5crg53tx0g --- addons/web_process/static/src/js/process.js | 63 +++++++++++++-------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/addons/web_process/static/src/js/process.js b/addons/web_process/static/src/js/process.js index d8d178ae63d..26beeb81d25 100644 --- a/addons/web_process/static/src/js/process.js +++ b/addons/web_process/static/src/js/process.js @@ -13,7 +13,7 @@ openerp.web_process = function (openerp) { grandparent = this.widget_parent && this.widget_parent.widget_parent, view = this.views[this.views_src[0].view_type], $process_view = this.$element.find('.oe-process-view'); - + this.process_model = this.model; if (!(grandparent instanceof openerp.web.WebClient) || !(view.view_type === this.views_src[0].view_type @@ -25,13 +25,13 @@ openerp.web_process = function (openerp) { $.when(self.load_process()).then(self.get_process_id()); }); }, - + process_subflow : function() { var self = this; - new openerp.web.DataSetSearch(this, + new openerp.web.DataSetSearch(this, "ir.actions.act_window",this.session.context,[]) - .read_slice(['help'], - { domain: + .read_slice(['help'], + { domain: [ ['res_model','=',this.process_action_model], ['name','ilike', this.process_action_name] @@ -42,14 +42,14 @@ openerp.web_process = function (openerp) { self.process_help = res[0]['help'] || 'Help: Not Defined'; } $.when(self.load_process()).then(self.render_process_view()); - + }); }, - + load_process: function() { this.$element.html(QWeb.render("ProcessView", this)); }, - + get_process_id: function() { var self = this; this.process_dataset = new openerp.web.DataSetStatic(this, "process.process", this.session.context); @@ -79,7 +79,7 @@ openerp.web_process = function (openerp) { } } }, - + render_process_view: function() { var self = this; this.p_id = parseInt(this.p_id, 10); @@ -96,36 +96,35 @@ openerp.web_process = function (openerp) { } ); }, - draw_process_graph: function(res) { var self = this; var process_graph = new Graph(); - + var process_renderer = function(r, n) { var process_node, process_node_text, process_node_desc, process_set; - + var node_button, node_menu, img_src; - + var bg = "node", clip_rect = "".concat(n.node.x,",",n.node.y,",150,100"), // text_position_x = n.node.x + (n.node.y/2) - + //Image part bg = n.node.kind == "subflow" ? "node-subflow" : "node"; bg = n.node.gray ? bg + "-gray" : bg; img_src = '/web_process/static/src/img/'+ bg + '.png'; - + r['image'](img_src, n.node.x, n.node.y,150, 100) .attr({"clip-rect": clip_rect}) .mousedown(function(){ return false; }); - + //Node process_node = r['rect'](n.node.x, n.node.y, 150, 100).attr({stroke: "none"}); // Node text @@ -140,16 +139,30 @@ openerp.web_process = function (openerp) { self.process_subflow(); }); } - + //Node Description - process_node_desc = r.text(n.node.x+75, n.node.y+50, (n.node.notes)); - + new_notes = n.node.notes; + if(n.node.notes.length > 25) { + var new_notes= temp_str = ''; + var from = to = 0; + while (1){ + from = 25; + temp_str = n.node.notes.substr(to ,25); + if (temp_str.lastIndexOf(" ") < 25 && temp_str.length >= 25) { + from = temp_str.lastIndexOf(" "); + } + new_notes += "\n" + n.node.notes.substr(to , from); + if(new_notes.length > n.node.notes.length) break; + to += from; + } + } + process_node_desc = r.text(n.node.x+85, n.node.y+50, (new_notes)); r['image']('/web/static/src/img/icons/gtk-info.png', n.node.x+20, n.node.y+70, 16, 16) .attr({"cursor": "pointer", "title": "Help"}) .click(function() { window.open(n.node.url || "http://doc.openerp.com/v6.0/index.php?model=" + n.node.model); }); - + if(n.node.menu) { r['image']('/web/static/src/img/icons/gtk-jump-to.png', n.node.x+115, n.node.y+70, 16, 16) .attr({"cursor": "pointer", "title": n.node.menu.name}) @@ -157,21 +170,21 @@ openerp.web_process = function (openerp) { self.jump_to_view(n.node.res_model, n.node.menu.id); }); } - + process_set = r.set().push(process_node); process_set.mousedown(function() { return false; }); return process_set; }; - + _.each(res['nodes'],function(node, node_id) { node['res_model'] = self.model, node['res_id'] = false, node['id'] = node_id; process_graph.addNode(node['name'], {node: node,render: process_renderer}); }); - + _.each(res['transitions'], function(transitions) { var src = res['nodes'][transitions['source']]; var dst = res['nodes'][transitions['target']]; @@ -179,11 +192,11 @@ openerp.web_process = function (openerp) { transitions['active'] = src.active && !dst.gray; process_graph.addEdge(src['name'], dst['name'], {directed : true}); }); - + var layouter = new Graph.Layout.Ordered(process_graph); var render_process_graph = new Graph.Renderer.Raphael('process_canvas', process_graph, $('#process_canvas').width(), $('#process_canvas').height()); }, - + jump_to_view: function(model, id) { var self = this; var dataset = new openerp.web.DataSetStatic(this, 'ir.values', this.session.context); From c13d18d93b7e4f87a16a3fe6e3eb04add94508a7 Mon Sep 17 00:00:00 2001 From: Numerigraphe - Lionel Sausin Date: Wed, 28 Sep 2011 17:34:34 +0200 Subject: [PATCH 054/265] [FIX] Only consider pricelist items based on partner if we have a partner and it's on the product's supplier info lp bug: https://launchpad.net/bugs/860625 fixed bzr revid: ls@numerigraphe.fr-20110928153434-5qd9lbk6i2dm2f5l --- addons/product/pricelist.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/addons/product/pricelist.py b/addons/product/pricelist.py index 81cec0e7d95..94046710880 100644 --- a/addons/product/pricelist.py +++ b/addons/product/pricelist.py @@ -210,6 +210,13 @@ class product_pricelist(osv.osv): else: categ_where = '(categ_id IS NULL)' + if partner: + partner_where = 'base <> -2 OR %s IN (SELECT name FROM product_supplierinfo WHERE product_id = %s) ' + partner_args = (partner, product_id) + else: + partner_where = 'base <> -2 ' + partner_args = () + cr.execute( 'SELECT i.*, pl.currency_id ' 'FROM product_pricelist_item AS i, ' @@ -217,11 +224,12 @@ class product_pricelist(osv.osv): 'WHERE (product_tmpl_id IS NULL OR product_tmpl_id = %s) ' 'AND (product_id IS NULL OR product_id = %s) ' 'AND (' + categ_where + ' OR (categ_id IS NULL)) ' + 'AND (' + partner_where + ') ' 'AND price_version_id = %s ' 'AND (min_quantity IS NULL OR min_quantity <= %s) ' 'AND i.price_version_id = v.id AND v.pricelist_id = pl.id ' 'ORDER BY sequence', - (tmpl_id, product_id, plversion_ids[0], qty)) + (tmpl_id, product_id) + partner_args + (plversion_ids[0], qty)) res1 = cr.dictfetchall() uom_price_already_computed = False for res in res1: @@ -365,6 +373,12 @@ class product_pricelist(osv.osv): categ_where = '(categ_id IN (' + ','.join(categ_ids) + '))' else: categ_where = '(categ_id IS NULL)' + + if partner: + partner_where = 'base <> -2 OR %s IN (SELECT name FROM product_supplierinfo WHERE product_id = %s) ' + sqlargs = sqlargs + (partner, prod_id) + else: + partner_where = 'base <> -2 ' cr.execute( 'SELECT i.*, pl.currency_id ' @@ -373,6 +387,7 @@ class product_pricelist(osv.osv): 'WHERE (product_tmpl_id IS NULL OR product_tmpl_id = %s) ' 'AND (product_id IS NULL OR product_id = %s) ' 'AND (' + categ_where + ' OR (categ_id IS NULL)) ' + 'AND (' + partner_where + ') ' 'AND price_version_id = %s ' 'AND (min_quantity IS NULL OR min_quantity <= %s) ' 'AND i.price_version_id = v.id AND v.pricelist_id = pl.id ' From da60b9cf776016ce822d349661cca771ab774582 Mon Sep 17 00:00:00 2001 From: "Vaibhav (OpenERP)" Date: Thu, 29 Sep 2011 11:45:53 +0530 Subject: [PATCH 055/265] [ADD] Edit Process. bzr revid: vda@tinyerp.com-20110929061553-0gk3v3j2cuva0jpb --- addons/web_process/static/src/js/process.js | 54 ++++++++++++++++--- .../static/src/xml/web_process.xml | 8 ++- 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/addons/web_process/static/src/js/process.js b/addons/web_process/static/src/js/process.js index 26beeb81d25..67b75bee03d 100644 --- a/addons/web_process/static/src/js/process.js +++ b/addons/web_process/static/src/js/process.js @@ -6,7 +6,7 @@ openerp.web_process = function (openerp) { this._super(); var self = this; this.process_check(); - this.process_help = this.action.help || 'Help: Not Defined'; + this.process_help = this.action ? this.action.help : 'Help: Not Defined'; }, process_check: function() { var self = this, @@ -47,7 +47,49 @@ openerp.web_process = function (openerp) { }, load_process: function() { + var self = this; this.$element.html(QWeb.render("ProcessView", this)); + this.$element.find('#edit_process').click(function() { + self.edit_process_view(); + }); + }, + + edit_process_view: function() { + var self = this; + var action_manager = new openerp.web.ActionManager(this); + var dialog = new openerp.web.Dialog(this, { + width: 800, + height: 600, + buttons : { + Cancel : function() { + $(this).dialog('destroy'); + }, + Save : function() { + var form_view = action_manager.inner_viewmanager.views.form.controller; + + form_view.do_save(function() { + self.process_renderer([[self.process_id]]); + }); + $(this).dialog('destroy'); + } + } + }).start().open(); + + action_manager.appendTo(dialog.$element); + action_manager.do_action({ + res_model : 'process.process', + res_id: self.process_id, + views : [[false, 'form']], + type : 'ir.actions.act_window', + auto_search : false, + flags : { + search_view: false, + sidebar : false, + views_switcher : false, + action_buttons : false, + pager: false + } + }); }, get_process_id: function() { @@ -69,12 +111,12 @@ openerp.web_process = function (openerp) { var $parent = self.widget_parent.$element; $parent.find('#change_process').click(function() { self.selection = false; - self.p_id = $parent.find('#select_process').val(); + self.process_id = $parent.find('#select_process').val(); $.when(self.load_process()).then(self.render_process_view()); }); }); } else { - this.p_id = res[0][0]; + this.process_id = res[0][0]; $.when(this.load_process()).then(this.render_process_view()); } } @@ -82,9 +124,9 @@ openerp.web_process = function (openerp) { render_process_view: function() { var self = this; - this.p_id = parseInt(this.p_id, 10); + this.process_id = parseInt(this.process_id, 10); this.process_dataset.call("graph_get", - [self.p_id, self.model, false, [80,80,150,100]], + [self.process_id, self.model, false, [80,80,150,100]], function(res) { res['title'] = res.resource ? res.resource : res.name; self.process_dataset.call("search_by_model", @@ -133,7 +175,7 @@ openerp.web_process = function (openerp) { process_node_text.translate(n.node.x / 2, 10) if(n.node.subflow) { process_node_text.click(function() { - self.p_id = n.node.subflow[0]; + self.process_id = n.node.subflow[0]; self.process_action_model = n.node.model; self.process_action_name = n.node.name; self.process_subflow(); diff --git a/addons/web_process/static/src/xml/web_process.xml b/addons/web_process/static/src/xml/web_process.xml index 94ab8e870f2..29ccc623d87 100644 --- a/addons/web_process/static/src/xml/web_process.xml +++ b/addons/web_process/static/src/xml/web_process.xml @@ -61,11 +61,17 @@ - +
+ + + + + + From f516936e1c4976fc44e7c6b108ffbf2398ca8833 Mon Sep 17 00:00:00 2001 From: "Vaibhav (OpenERP)" Date: Thu, 29 Sep 2011 12:44:48 +0530 Subject: [PATCH 056/265] [FIX] Changed images for node text align. bzr revid: vda@tinyerp.com-20110929071448-119c8glmi4q6ol3z --- .../static/src/img/node-current.png | Bin 2472 -> 3143 bytes .../web_process/static/src/img/node-gray.png | Bin 2445 -> 3128 bytes .../static/src/img/node-subflow-gray.png | Bin 5105 -> 6837 bytes .../static/src/img/node-subflow.png | Bin 5153 -> 6851 bytes addons/web_process/static/src/img/node.png | Bin 2503 -> 3205 bytes addons/web_process/static/src/js/process.js | 4 ++-- 6 files changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/web_process/static/src/img/node-current.png b/addons/web_process/static/src/img/node-current.png index 2126e45dfd24ee944232a34b754b081eb9affdcf..51f86b04c786e91411168f858503553f1469f4e8 100644 GIT binary patch delta 3127 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 H{U`qefqoyj literal 2472 zcmd6p`9BkmAIAxEq};*~J{e;%*GL(k+|-;o#@r!CBW5f^QNq$kIV#60IZ|`aP?pRQ zEBp9}XtJDhHb*&H`0Bs-{_uJ|ACKqz@p%9Cemve;&IsFMA_^irJUqwj?W|l6S$LQb zA;6#Z>0dj9aEzUI91qWN+Mn?Dp{qj<9n#+FZ}-HK)h|9#iX%#C>*&y}X_S&d)rge5iRNe! z*QS2`H1x;FAfR3!p7I9pdU*^nbEd;tec3kn0eVx$`TiJ78n@=vtId|XKrAtm)l_zO zPs}X7R7wh=U>@*n`fPztoXB@!I zqZ;QB?1J3mHZ9TRPum{{Xu7W)+<~+L3)?xQuE1&JUBIp(Q^lH{K$dn75Q3L z3*4|{5&tEonls2P`r4(S0A|>4Z1=4|CX6R{M*MgtILAgflh#^h`|+4@Jad!H!ZG3) zJ%~w8e*M-&YHE{==ze5!$ZTagcWa2nbTln64HH+m!;AOy>zAtQm`72W}YnPE8$hnM*^fNx-OkEuJVhskL+H z0T3tiZfGFQf*wqhwqwzKZ(5i}Cg}KM|k-`1d zM!}2aY>g!@Ap!eVC?FcuTn$#tN;Zh!sUK#27E~vABziMXgvu;YUkk0lrn(fy&NfSG3 zwB-6E18-uCUr|xLqnka+OJ+nJr zV}p0$hwUct0T6LRLF8TO75BDgNW$4r|Jab@gXALk9N%7@}w#f>p#6=h%+{l_(B3Tn#8Z%1za{pEsVw736>m4%`u5dBGZ_H{Ce4m` z+ACr`t-2(KgZv`3&5>{S#~6}@4`EodEx824?DP!vN*8Oq*-=hgrploYHTRI;h*{p z3CTj}`7TKtJFhMwVMjUDK;ggs&xc)G1+K{D``G4Ocr&Mn+SD3yg*1fJ_Lxs8!ZooB`yTO5uxxocUryG7e~i1&h2_HwvK{ZS zlL)!F&&d0o$~P(ZYkhwC3h}2+Vp%;O=R)2~K6eG%*xD8>x7RTb(x?(+^El-#X`9ox zZ|`u5(ORtSsspioUZ_@VnR*4KqAEhnunnM!%>|7U0`0XzWBKNY~eG#w6ELMf{(N zJB|c)lBk$iQy4=zSMkh7o9j|8W_eTzo>J@vs1UxxxRshcVD4Uh@KN{vX zlV17eei|%AK#GR_qDca`jC7bS4beb)8^&0Vljj*acA8_-3Mi-@{ diff --git a/addons/web_process/static/src/img/node-gray.png b/addons/web_process/static/src/img/node-gray.png index 2334abbc2fef44e2c9577a94f19e3baed713a8d0..972013540cf00d5e379f9c9136b11499ab2e93f7 100644 GIT binary patch literal 3128 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 literal 2445 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 diff --git a/addons/web_process/static/src/img/node-subflow-gray.png b/addons/web_process/static/src/img/node-subflow-gray.png index 7703eedd2f0c9252ddc69d4a0437bf24c91915ca..ffafe1bd681f01d622bcb371dea2488a7d724868 100644 GIT binary patch literal 6837 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 diff --git a/addons/web_process/static/src/img/node.png b/addons/web_process/static/src/img/node.png index 4ed3681fa8d10986952d531dfa9838dc0b8d9d3d..853ac85cd566516bf18e7e4532ecf28610b25e0d 100644 GIT binary patch literal 3205 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 A Date: Thu, 29 Sep 2011 16:31:45 +0530 Subject: [PATCH 057/265] [IMP] show Fields.Changed Mechanism. bzr revid: vda@tinyerp.com-20110929110145-z5fgyg84acx3nuyl --- addons/web_process/static/src/css/process.css | 4 + addons/web_process/static/src/js/process.js | 288 +++++++++++------- .../static/src/xml/web_process.xml | 36 ++- 3 files changed, 207 insertions(+), 121 deletions(-) diff --git a/addons/web_process/static/src/css/process.css b/addons/web_process/static/src/css/process.css index 6522932a39a..364c3788b11 100644 --- a/addons/web_process/static/src/css/process.css +++ b/addons/web_process/static/src/css/process.css @@ -55,4 +55,8 @@ a.cta-a strong { padding:5px 10px; min-height:56px; font-size: 120%; +} + +td.process_fields,button.toggle_fields span:last-child { + display: none; } \ No newline at end of file diff --git a/addons/web_process/static/src/js/process.js b/addons/web_process/static/src/js/process.js index 9fd6606fdc6..faff7d7bb8e 100644 --- a/addons/web_process/static/src/js/process.js +++ b/addons/web_process/static/src/js/process.js @@ -7,141 +7,156 @@ openerp.web_process = function (openerp) { var self = this; this.process_check(); this.process_help = this.action ? this.action.help : 'Help: Not Defined'; + this.process_model = this.model; }, process_check: function() { var self = this, grandparent = this.widget_parent && this.widget_parent.widget_parent, view = this.views[this.views_src[0].view_type], $process_view = this.$element.find('.oe-process-view'); - - this.process_model = this.model; + if (!(grandparent instanceof openerp.web.WebClient) || !(view.view_type === this.views_src[0].view_type && view.view_id === this.views_src[0].view_id)) { $process_view.hide(); return; } + $process_view.click(function() { - $.when(self.load_process()).then(self.get_process_id()); + self.initialize_process_view(); }); + }, - - process_subflow : function() { + + initialize_process_view: function() { var self = this; - new openerp.web.DataSetSearch(this, - "ir.actions.act_window",this.session.context,[]) - .read_slice(['help'], - { domain: - [ - ['res_model','=',this.process_action_model], - ['name','ilike', this.process_action_name] - ] - }, - function(res) { - if (res.length) { - self.process_help = res[0]['help'] || 'Help: Not Defined'; + var is_ready = $.Deferred(); + $.when(this.fields_get(), this.help(), this.get_process_object()).pipe(function(fields, help, process) { + self.process_fields = fields; + self.process_help = help; + if(process && process.length) { + if(process.length > 1) { + self.process_selection = process; + } else { + self.process_id = process[0][0]; } - $.when(self.load_process()).then(self.render_process_view()); - + } + return $.Deferred().resolve(); + }).done(function() { + self.render_process_view(); + }).done(function() { + if(self.process_id) { + self.graph_get().done(function(res) { + self.draw_process_graph(res); + }); + } }); + }, - - load_process: function() { + + graph_get: function() { var self = this; + var def = $.Deferred(); + this.process_id = parseInt(this.process_id, 10); + + this.process_dataset + .call("graph_get",[this.process_id, this.model, false, [80,80,150,100]]) + .done(function(res) { + self.process_dataset + .call("search_by_model",[self.model,self.session.context]) + .done( + function(r) { + res['related'] = r; + def.resolve(res); + }); + + }); + return def.promise(); + }, + + fields_get : function() { + var self = this, + def = $.Deferred(), + dataset = new openerp.web.DataSetStatic(this, this.model, this.session.context); + + dataset + .call('fields_get',[]) + .done(function(fields) { + def.resolve(fields); + }).fail(def.reject); + return def.promise(); + }, + + help : function() { + var self = this, + def = $.Deferred(); + if(!this.subflow_model) { + def.resolve(this.action ? this.action.help : 'Help: Not Defined'); + } else { + var dataset = new openerp.web.DataSetSearch(this, "ir.actions.act_window", this.session.context, []); + dataset + .read_slice(['help'], + { + domain: [ + ['res_model', '=', this.subflow_model], + ['name', 'ilike', this.subflow_name] + ] + } + ).done(function(res) { + def.resolve(res && res.records.length ? res.records[0].help : 'Help: Not Defined'); + }); + + } + return def.promise(); + }, + + get_process_object : function() { + var self = this, + def = $.Deferred(); + if(this.process_id) + return def.resolve().promise(); + this.process_dataset = new openerp.web.DataSetStatic(this, "process.process", this.session.context); + this.process_dataset + .call("search_by_model", [self.process_model,self.session.context]) + .done(function(res) { + if (!res.length) { + self.process_model = false; + self.get_process_object().done(def.resolve); + } + else { + def.resolve(res); + } + }) + .fail(def.reject); + return def.promise(); + }, + + render_process_view : function() { this.$element.html(QWeb.render("ProcessView", this)); + var self = this; this.$element.find('#edit_process').click(function() { self.edit_process_view(); }); + + var $parent = this.widget_parent.$element; + $parent.find('#change_process').click(function() { + self.process_selection = false; + self.process_id = $parent.find('#select_process').val(); + self.initialize_process_view(); + }); + + + this.$element.find(".toggle_fields").click(function() { + $(this).children().toggle(); + self.$element.find('.process_fields').toggle(); + + }) }, - edit_process_view: function() { - var self = this; - var action_manager = new openerp.web.ActionManager(this); - var dialog = new openerp.web.Dialog(this, { - width: 800, - height: 600, - buttons : { - Cancel : function() { - $(this).dialog('destroy'); - }, - Save : function() { - var form_view = action_manager.inner_viewmanager.views.form.controller; - - form_view.do_save(function() { - self.process_renderer([[self.process_id]]); - }); - $(this).dialog('destroy'); - } - } - }).start().open(); + draw_process_graph : function(res) { + var self = this, + process_graph = new Graph(); - action_manager.appendTo(dialog.$element); - action_manager.do_action({ - res_model : 'process.process', - res_id: self.process_id, - views : [[false, 'form']], - type : 'ir.actions.act_window', - auto_search : false, - flags : { - search_view: false, - sidebar : false, - views_switcher : false, - action_buttons : false, - pager: false - } - }); - }, - - get_process_id: function() { - var self = this; - this.process_dataset = new openerp.web.DataSetStatic(this, "process.process", this.session.context); - this.process_dataset.call("search_by_model", - [self.process_model,self.session.context], - function(res) {self.process_renderer(res)}); - }, - process_renderer: function(res) { - var self = this; - if(!res.length) { - this.process_model = false; - this.get_process_id(); - } else { - if(res.length > 1) { - this.selection = res; - $.when(this.load_process()).then(function() { - var $parent = self.widget_parent.$element; - $parent.find('#change_process').click(function() { - self.selection = false; - self.process_id = $parent.find('#select_process').val(); - $.when(self.load_process()).then(self.render_process_view()); - }); - }); - } else { - this.process_id = res[0][0]; - $.when(this.load_process()).then(this.render_process_view()); - } - } - }, - - render_process_view: function() { - var self = this; - this.process_id = parseInt(this.process_id, 10); - this.process_dataset.call("graph_get", - [self.process_id, self.model, false, [80,80,150,100]], - function(res) { - res['title'] = res.resource ? res.resource : res.name; - self.process_dataset.call("search_by_model", - [self.model,self.session.context], - function(r) { - res['related'] = r; - }); - self.draw_process_graph(res); - } - ); - }, - draw_process_graph: function(res) { - var self = this; - var process_graph = new Graph(); - var process_renderer = function(r, n) { var process_node, process_node_text, @@ -154,7 +169,6 @@ openerp.web_process = function (openerp) { var bg = "node", clip_rect = "".concat(n.node.x,",",n.node.y,",150,100"); -// text_position_x = n.node.x + (n.node.y/2) //Image part bg = n.node.kind == "subflow" ? "node-subflow" : "node"; @@ -163,7 +177,7 @@ openerp.web_process = function (openerp) { r['image'](img_src, n.node.x, n.node.y,150, 100) .attr({"clip-rect": clip_rect}) - .mousedown(function(){ + .mousedown(function() { return false; }); @@ -176,9 +190,9 @@ openerp.web_process = function (openerp) { if(n.node.subflow) { process_node_text.click(function() { self.process_id = n.node.subflow[0]; - self.process_action_model = n.node.model; - self.process_action_name = n.node.name; - self.process_subflow(); + self.subflow_model = n.node.model; + self.subflow_name = n.node.name; + self.initialize_process_view(); }); } @@ -187,7 +201,7 @@ openerp.web_process = function (openerp) { if(n.node.notes.length > 25) { var new_notes= temp_str = ''; var from = to = 0; - while (1){ + while (1) { from = 25; temp_str = n.node.notes.substr(to ,25); if (temp_str.lastIndexOf(" ") < 25 && temp_str.length >= 25) { @@ -214,12 +228,12 @@ openerp.web_process = function (openerp) { } process_set = r.set().push(process_node); - process_set.mousedown(function() { + process_set.mousedown(function() { return false; }); return process_set; }; - + _.each(res['nodes'],function(node, node_id) { node['res_model'] = self.model, node['res_id'] = false, @@ -238,7 +252,7 @@ openerp.web_process = function (openerp) { var layouter = new Graph.Layout.Ordered(process_graph); var render_process_graph = new Graph.Renderer.Raphael('process_canvas', process_graph, $('#process_canvas').width(), $('#process_canvas').height()); }, - + jump_to_view: function(model, id) { var self = this; var dataset = new openerp.web.DataSetStatic(this, 'ir.values', this.session.context); @@ -256,7 +270,45 @@ openerp.web_process = function (openerp) { action_manager.do_action(result.result); }); }); - } + }, + + edit_process_view: function() { + var self = this; + var action_manager = new openerp.web.ActionManager(this); + var dialog = new openerp.web.Dialog(this, { + width: 800, + height: 600, + buttons : { + Cancel : function() { + $(this).dialog('destroy'); + }, + Save : function() { + var form_view = action_manager.inner_viewmanager.views.form.controller; + + form_view.do_save(function() { + self.initialize_process_view(); + }); + $(this).dialog('destroy'); + } + } + }).start().open(); + + action_manager.appendTo(dialog.$element); + action_manager.do_action({ + res_model : 'process.process', + res_id: self.process_id, + views : [[false, 'form']], + type : 'ir.actions.act_window', + auto_search : false, + flags : { + search_view: false, + sidebar : false, + views_switcher : false, + action_buttons : false, + pager: false + } + }); + }, }); }; diff --git a/addons/web_process/static/src/xml/web_process.xml b/addons/web_process/static/src/xml/web_process.xml index 29ccc623d87..5ac2c587701 100644 --- a/addons/web_process/static/src/xml/web_process.xml +++ b/addons/web_process/static/src/xml/web_process.xml @@ -44,14 +44,14 @@

- +
Select Process