From 7608df909638b725682db88969787ea09433dfea Mon Sep 17 00:00:00 2001 From: "DBR (OpenERP)" Date: Thu, 20 Oct 2011 11:52:48 +0530 Subject: [PATCH 002/117] [Move]purchase_requisition: Move purchase_requisition.yml in to process folder bzr revid: dbr@tinyerp.com-20111020062248-tg7pkrdvh026jvzm --- .../test/{ => process}/purchase_requisition.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename addons/purchase_requisition/test/{ => process}/purchase_requisition.yml (100%) diff --git a/addons/purchase_requisition/test/purchase_requisition.yml b/addons/purchase_requisition/test/process/purchase_requisition.yml similarity index 100% rename from addons/purchase_requisition/test/purchase_requisition.yml rename to addons/purchase_requisition/test/process/purchase_requisition.yml From 29c0a92ac50eff2e7eb9f374aba0206e0f4dd43e Mon Sep 17 00:00:00 2001 From: "DBR (OpenERP)" Date: Fri, 21 Oct 2011 17:59:41 +0530 Subject: [PATCH 003/117] [IMP]purchase_requisition: try to improve the code on the bases of data bzr revid: dbr@tinyerp.com-20111021122941-dlro6heqzpmwitub --- addons/purchase/purchase_demo.xml | 16 +- addons/purchase_requisition/__openerp__.py | 4 +- .../purchase_requisition_view.xml | 4 +- .../test/process/purchase_requisition.yml | 207 +++--------------- 4 files changed, 45 insertions(+), 186 deletions(-) diff --git a/addons/purchase/purchase_demo.xml b/addons/purchase/purchase_demo.xml index 6aa98f8cf6c..958a1557b4e 100644 --- a/addons/purchase/purchase_demo.xml +++ b/addons/purchase/purchase_demo.xml @@ -161,9 +161,19 @@ 10 - + + [HDD3] HDD Seagate 7200.8 80GB + + + 70 + 10 + + + + + [HDD2] HDD Seagate 7200.8 120GB @@ -172,7 +182,7 @@ - + [RAM] DDR 256MB PC400 @@ -182,7 +192,7 @@ - + [RAM512] DDR 512MB PC400 diff --git a/addons/purchase_requisition/__openerp__.py b/addons/purchase_requisition/__openerp__.py index d1ec2b1c260..ebdb598c081 100644 --- a/addons/purchase_requisition/__openerp__.py +++ b/addons/purchase_requisition/__openerp__.py @@ -43,8 +43,8 @@ This new object will regroup and will allow you to easily keep track and order a "security/ir.model.access.csv","purchase_requisition_sequence.xml" ], "active": False, - "test":['test/purchase_requisition_report.yml', - 'test/purchase_requisition_test.yml', + "test":[#'test/purchase_requisition_report.yml', + 'test/process/purchase_requisition.yml', ], "installable": True, "certificate" : "001023264099823179629", diff --git a/addons/purchase_requisition/purchase_requisition_view.xml b/addons/purchase_requisition/purchase_requisition_view.xml index 06ee94c3941..3b0cfeb7f77 100644 --- a/addons/purchase_requisition/purchase_requisition_view.xml +++ b/addons/purchase_requisition/purchase_requisition_view.xml @@ -21,7 +21,7 @@ purchase.order - + @@ -34,7 +34,7 @@ purchase.order - + diff --git a/addons/purchase_requisition/test/process/purchase_requisition.yml b/addons/purchase_requisition/test/process/purchase_requisition.yml index fb5fa774fc3..df6d4089e54 100644 --- a/addons/purchase_requisition/test/process/purchase_requisition.yml +++ b/addons/purchase_requisition/test/process/purchase_requisition.yml @@ -1,189 +1,38 @@ - - - In order to test the purchase requisition module, I will do a sale order -> purchase_requisition -> - purchase flow and I will buy the required products at two different suppliers. + In order to test the purchase requisition module, I have to add a boolean field in product, + If I checked it then it's requisition create. - - I start by creating a new product 'Laptop ACER', which is purchased at Asustek, in MTO, - with the generation of purchase requisitions. + I start by Checking the product, Product must have requisition field checked. + and Product supply method is buy and the procure method is make to order. - - !record {model: product.product, id: product_product_laptopacer0}: - categ_id: product.product_category_3 - cost_method: standard - mes_type: fixed - name: Laptop ACER - procure_method: make_to_order - purchase_requisition: 1 - seller_ids: - - delay: 1 - name: base.res_partner_asus - qty: 5.0 - min_qty: 1.0 - supply_method: buy - type: product - uom_id: product.product_uom_unit - uom_po_id: product.product_uom_unit - volume: 0.0 - warranty: 0.0 - weight: 0.0 - weight_net: 0.0 - list_price: 100.0 + !record {model: product.product, id: product.product_product_hdd3}: + supply_method: 'buy' + purchase_requisition: True - - Then I sell 5 Laptop ACER to the customer Agrolait, sale order TEST/TENDER/0001. + I create the procurement order. - - !record {model: sale.order, id: sale_order_testtender0}: - date_order: !eval time.strftime('%Y-%m-%d') - invoice_quantity: order - name: TEST/TENDER/0001 - order_line: - - name: Laptop ACER - price_unit: 100.0 - product_uom: product.product_uom_unit - product_uom_qty: 5.0 - state: draft - delay: 7.0 - product_id: product_product_laptopacer0 - product_uos_qty: 5.0 - th_weight: 0.0 - type: make_to_order - order_policy: manual - partner_id: base.res_partner_agrolait - partner_invoice_id: base.res_partner_address_8 - partner_order_id: base.res_partner_address_8 - partner_shipping_id: base.res_partner_address_8 - picking_policy: direct - pricelist_id: product.list0 - shop_id: sale.shop + !python {model: make.procurement}: | + import time + product = self.pool.get('product.product').browse(cr, uid,[ref('product.product_product_hdd3')]) + #product_uom = product.product_uom + fields = { + 'qty': 5.0, + 'product_id': product, + #'uom_id': product_uom, + #'warehouse_id': stock.warehouse0, + 'date_planned': time.strftime('%Y-%m-%d') + } + a = self.default_get(cr, uid, fields, context) + req_id = self.make_procurement(cr, uid, [ref('product.product_product_hdd3')], context) - - I confirm the sale order. -- - !workflow {model: sale.order, action: order_confirm, ref: sale_order_testtender0} -- - I launch the scheduler to compute all procurements, and specify all requisitions orders. -- - !python {model: procurement.order.compute.all}: | - proc_obj = self.pool.get('procurement.order') - proc_obj._procure_confirm(cr,uid) -- - On the purchase requisition, I create a new purchase order for the supplier 'DistriPC' by clicking on - the button 'New RfQ'. This opens a window to ask me the supplier and I set DistriPC . -- - !record {model: purchase.requisition.partner, id: purchase_requisition_partner_0}: - partner_address_id: base.res_partner_address_7 - partner_id: base.res_partner_4 -- - I create a new purchase order. -- - !python {model: purchase.requisition.partner}: | - req_obj = self.pool.get('purchase.requisition') - ids =req_obj.search(cr, uid, [('origin','=','Laptop ACER')]) - self.create_order(cr, uid, [ref("purchase_requisition_partner_0")], {"lang": - 'en_US', "active_model": "purchase.requisition", "tz": False, "record_id": - 1, "active_ids": ids, "active_id": ids[0], }) - -- - I check that I have two purchase orders on the purchase requisition. -- - !python {model: purchase.order}: | - from tools.translate import _ - order_ids =self.search(cr, uid, [('origin','=','TEST/TENDER/0001')]) - ids=len(order_ids) - assert(ids == 2), _('Purchase Order not Created') - -- - I set the purchase requisition as 'Not Exclusive'. -- - !python {model: purchase.requisition}: | - ids =self.search(cr, uid, [('origin','=','Laptop ACER')]) - self.write(cr,uid,ids[0],{'exclusive': 'multiple' }) -- - I change the quantities so that the purchase order for DistriPC includes 3 pieces and the - purchase order for Asustek includes 2 pieces. + I create the procurement order from the selected purchase order. - !python {model: purchase.order}: | - line_obj=self.pool.get('purchase.order.line') - partner_obj=self.pool.get('res.partner') - requistion_obj=self.pool.get('purchase.requisition') - requistion_ids =requistion_obj.search(cr, uid, [('origin','=','Laptop ACER')]) - partner_id1=partner_obj.search(cr,uid,[('name','=','ASUStek')])[0] - partner_id2=partner_obj.search(cr,uid,[('name','=','Distrib PC')])[0] - purchase_id1= self.search(cr, uid, [('partner_id','=',partner_id1),('requisition_id','in',requistion_ids)]) - purchase_id2= self.search(cr, uid, [('partner_id','=',partner_id2),('requisition_id','in',requistion_ids)]) - order_line1=self.browse(cr, uid, purchase_id1, context)[0].order_line[0].id - order_line2=self.browse(cr, uid, purchase_id2, context)[0].order_line[0].id - line_obj.write(cr, uid, order_line1, {'product_qty':2}) - line_obj.write(cr, uid, order_line2, {'product_qty':3}) + req_id = self.pool.get('procurement.order').action_po_assign(cr, uid, [ref('purchase.order_purchase6')], context) + self.wkf_confirm_order(cr, uid, [req_id], context) - - I confirm and validate both purchase orders. + I create the purchase requisition for the selected product. - - !python {model: purchase.order}: | - order_ids= self.search(cr, uid, []) - import netsvc - wf_service = netsvc.LocalService("workflow") - for id in order_ids: - wf_service.trg_validate(uid, 'purchase.order',id,'purchase_confirm', cr) - wf_service.trg_validate(uid, 'purchase.order',id,'purchase_approve', cr) -- - I check that the delivery order of the customer is in state 'Waiting Goods'. -- - !python {model: stock.picking }: | - from tools.translate import _ - picking_id = self.search(cr, uid, [('origin','=','TEST/TENDER/0001')]) - if picking_id: - pick=self.browse(cr,uid,picking_id[0]) - assert (pick.state =='confirmed'),_('Picking is not in confirm state.') - assert (pick.move_lines[0].state == 'waiting'), _('Stock Move is not Waiting state.') - -- - I receive the order of the supplier Asustek from the Incoming Products menu. -- - !python {model: stock.picking }: | - import time - partner_obj=self.pool.get('res.partner') - order_obj=self.pool.get('purchase.order') - partner_id=partner_obj.search(cr,uid,[('name','=','ASUStek')])[0] - picking_id = self.search(cr, uid, [('address_id.partner_id','=',partner_id),('type','=','in')]) - if picking_id: - pick=self.browse(cr,uid,picking_id[0]) - move =pick.move_lines[0] - partial_datas = { - 'partner_id': pick.address_id.partner_id.id, - 'address_id': pick.address_id.id, - 'delivery_date' : time.strftime('%Y-%m-%d'), - } - partial_datas['move%s'%(move.id)]= { - 'product_id': move.product_id.id, - 'product_qty': move.product_qty, - 'product_uom': move.product_uom.id, - } - self.do_partial(cr, uid, picking_id,partial_datas) -- - I receive the order of the supplier DistriPC from the Incoming Shipments menu. -- - !python {model: stock.picking }: | - import time - partner_id=self.pool.get('res.partner').search(cr,uid,[('name','=','Distrib PC')])[0] - picking_id = self.search(cr, uid, [('address_id.partner_id','=',partner_id),('type','=','in')]) - if picking_id: - pick=self.browse(cr,uid,picking_id[0]) - move =pick.move_lines[0] - partial_datas = { - 'partner_id':pick.address_id.partner_id.id, - 'address_id': pick.address_id.id, - 'delivery_date' : time.strftime('%Y-%m-%d'), - } - partial_datas['move%s'%(move.id)]= { - 'product_id': move.product_id.id, - 'product_qty': move.product_qty, - 'product_uom': move.product_uom.id, - } - self.do_partial(cr, uid, picking_id,partial_datas) -- - I check that the delivery order of the customer is in the state Available. -- - !python {model: stock.picking }: | - from tools.translate import _ - picking_id = self.search(cr, uid, [('origin','=','TEST/TENDER/0001'),('type','=','out')]) - if picking_id: - pick=self.browse(cr,uid,picking_id[0]) - assert(pick.state == 'assigned'), _('Picking is not in available state') - + !python {model: purchase.requisition}: | + self.browse(cr, uid, [context.get('requisition_id')], context) + From 86caf711dd971f063d090f4810f2b26e8756068a Mon Sep 17 00:00:00 2001 From: "DBR (OpenERP)" Date: Mon, 31 Oct 2011 14:18:58 +0530 Subject: [PATCH 004/117] [IMP]puchase_requisition:Improve the test case for create procurement order from product bzr revid: dbr@tinyerp.com-20111031084858-e26x17iufxwbzrtu --- .../test/process/purchase_requisition.yml | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/addons/purchase_requisition/test/process/purchase_requisition.yml b/addons/purchase_requisition/test/process/purchase_requisition.yml index df6d4089e54..b3c1aeb0982 100644 --- a/addons/purchase_requisition/test/process/purchase_requisition.yml +++ b/addons/purchase_requisition/test/process/purchase_requisition.yml @@ -9,21 +9,25 @@ supply_method: 'buy' purchase_requisition: True - - I create the procurement order. + I create the procurement order for the product. - - !python {model: make.procurement}: | + !python {model: product.product}: | import time - product = self.pool.get('product.product').browse(cr, uid,[ref('product.product_product_hdd3')]) - #product_uom = product.product_uom - fields = { - 'qty': 5.0, - 'product_id': product, - #'uom_id': product_uom, - #'warehouse_id': stock.warehouse0, - 'date_planned': time.strftime('%Y-%m-%d') - } - a = self.default_get(cr, uid, fields, context) - req_id = self.make_procurement(cr, uid, [ref('product.product_product_hdd3')], context) + procurement = self.pool.get('make.procurement') + product = self.browse(cr, uid,[ref('product.product_product_hdd3')]) + context = {'active_model': 'product.product','active_ids': [product[0].id],'active_id': product[0].id} + default_data = procurement.default_get(cr, uid, ['uom_id', 'warehouse_id', 'date_planned', 'product_id', 'qty'], context) + vals = {'uom_id': product[0].uom_id.id,'warehouse_id': ref('stock.stock_warehouse_shop0'),'qty': default_data.get('qty'),'date_planned': default_data.get('date_planned')} + ids = procurement.create(cr, uid, vals, context) + req_id = procurement.make_procurement(cr, uid, [ids], context) + proc_order = self.pool.get('procurement.order') + order = proc_order.browse(cr, uid, [req_id.get('res_id')]) + assert order[0].state == "confirmed", "Procurement Order should be in Confirmed state" + assert order[0].product_id == product[0],"Product is not correspond in procurement order" + assert order[0].product_qty == default_data.get('qty'),"Product's quantity is not correspond in procurement order" + assert order[0].product_uom == product[0].uom_id,"Product's UOM is not correspond in procurement order" + + - I create the procurement order from the selected purchase order. - From adc05bc4d6559cdd52482f3e435f0a9d6191ef6c Mon Sep 17 00:00:00 2001 From: "DBR (OpenERP)" Date: Mon, 31 Oct 2011 15:27:40 +0530 Subject: [PATCH 005/117] [IMP]puchase_requisition: Improve code for create requisition bzr revid: dbr@tinyerp.com-20111031095740-t42sdppozvhwhfqs --- .../test/process/purchase_requisition.yml | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/addons/purchase_requisition/test/process/purchase_requisition.yml b/addons/purchase_requisition/test/process/purchase_requisition.yml index b3c1aeb0982..42c66f308d4 100644 --- a/addons/purchase_requisition/test/process/purchase_requisition.yml +++ b/addons/purchase_requisition/test/process/purchase_requisition.yml @@ -9,34 +9,34 @@ supply_method: 'buy' purchase_requisition: True - - I create the procurement order for the product. + I create the procurement order for the product and after run the procurement create purchase requisition. - !python {model: product.product}: | import time - procurement = self.pool.get('make.procurement') - product = self.browse(cr, uid,[ref('product.product_product_hdd3')]) - context = {'active_model': 'product.product','active_ids': [product[0].id],'active_id': product[0].id} - default_data = procurement.default_get(cr, uid, ['uom_id', 'warehouse_id', 'date_planned', 'product_id', 'qty'], context) - vals = {'uom_id': product[0].uom_id.id,'warehouse_id': ref('stock.stock_warehouse_shop0'),'qty': default_data.get('qty'),'date_planned': default_data.get('date_planned')} - ids = procurement.create(cr, uid, vals, context) - req_id = procurement.make_procurement(cr, uid, [ids], context) + import netsvc + mk_proc = self.pool.get('make.procurement') proc_order = self.pool.get('procurement.order') + pur_req = self.pool.get('purchase.requisition') + context = {'active_model': 'product.product','active_ids': [ref('product.product_product_hdd3')],'active_id': ref('product.product_product_hdd3')} + default_data = mk_proc.default_get(cr, uid, ['uom_id', 'warehouse_id', 'date_planned', 'product_id', 'qty'], context) + vals = {'uom_id': ref('product.product_uom_unit'),'warehouse_id': ref('stock.stock_warehouse_shop0'),'qty': default_data.get('qty'),'date_planned': default_data.get('date_planned')} + ids = mk_proc.create(cr, uid, vals, context) + req_id = mk_proc.make_procurement(cr, uid, [ids], context) order = proc_order.browse(cr, uid, [req_id.get('res_id')]) assert order[0].state == "confirmed", "Procurement Order should be in Confirmed state" - assert order[0].product_id == product[0],"Product is not correspond in procurement order" + assert order[0].product_id.id == ref('product.product_product_hdd3'),"Product is not correspond in procurement order" assert order[0].product_qty == default_data.get('qty'),"Product's quantity is not correspond in procurement order" - assert order[0].product_uom == product[0].uom_id,"Product's UOM is not correspond in procurement order" - - -- - I create the procurement order from the selected purchase order. -- - !python {model: purchase.order}: | - req_id = self.pool.get('procurement.order').action_po_assign(cr, uid, [ref('purchase.order_purchase6')], context) - self.wkf_confirm_order(cr, uid, [req_id], context) -- - I create the purchase requisition for the selected product. -- - !python {model: purchase.requisition}: | - self.browse(cr, uid, [context.get('requisition_id')], context) - + assert order[0].product_uom.id == ref('product.product_uom_unit'),"Product's UOM is not correspond in procurement order" + wf_service = netsvc.LocalService("workflow") + for proc in order: + wf_service.trg_validate(uid, 'procurement.order',proc.id,'button_check', cr) + proc_ids = proc_order.search(cr, uid, [('id','=',req_id.get('res_id')),('state','in',['running'])]) + proc_id = proc_order.browse(cr, uid, proc_ids) + assert proc_id[0].state == 'running',"Product's UOM is not correspond in procurement order" + if proc_id[0].requisition_id: + pur_req_rec = pur_req.browse(cr, uid, [proc_id[0].requisition_id.id]) + assert pur_req_rec[0].state == 'draft',"Product's UOM is not correspond in procurement order" + for record in pur_req_rec[0].line_ids: + assert record.product_id.id == ref('product.product_product_hdd3'),"Product's UOM is not correspond in procurement order" + assert record.product_qty == default_data.get('qty'),"Product's UOM is not correspond in procurement order" + assert record.product_uom_id.id == ref('product.product_uom_unit'),"Product's UOM is not correspond in procurement order" From a8ee7baa2d95261435d266798cee2196bde4d617 Mon Sep 17 00:00:00 2001 From: "DBR (OpenERP)" Date: Mon, 31 Oct 2011 17:22:25 +0530 Subject: [PATCH 006/117] [IMP,ADD,MOVE]puchase_requisition: Improve the code in purchase_requisition.yml file Create new ui folder Move purchase_requisition_exclusive.yml to onchange_events.yml Improve code for onchange_events.yml bzr revid: dbr@tinyerp.com-20111031115225-1yy9jsz3iee2gmlw --- addons/purchase_requisition/__openerp__.py | 3 +- .../test/process/purchase_requisition.yml | 21 ++-- .../test/purchase_requisition_exclusive.yml | 113 ------------------ .../test/ui/onchange_events.yml | 23 ++++ 4 files changed, 38 insertions(+), 122 deletions(-) delete mode 100644 addons/purchase_requisition/test/purchase_requisition_exclusive.yml create mode 100644 addons/purchase_requisition/test/ui/onchange_events.yml diff --git a/addons/purchase_requisition/__openerp__.py b/addons/purchase_requisition/__openerp__.py index ebdb598c081..e655a574e42 100644 --- a/addons/purchase_requisition/__openerp__.py +++ b/addons/purchase_requisition/__openerp__.py @@ -43,8 +43,9 @@ This new object will regroup and will allow you to easily keep track and order a "security/ir.model.access.csv","purchase_requisition_sequence.xml" ], "active": False, - "test":[#'test/purchase_requisition_report.yml', + "test":[ 'test/process/purchase_requisition.yml', + 'test/ui/onchange_events.yml', ], "installable": True, "certificate" : "001023264099823179629", diff --git a/addons/purchase_requisition/test/process/purchase_requisition.yml b/addons/purchase_requisition/test/process/purchase_requisition.yml index 42c66f308d4..3be7e2a9ea9 100644 --- a/addons/purchase_requisition/test/process/purchase_requisition.yml +++ b/addons/purchase_requisition/test/process/purchase_requisition.yml @@ -1,6 +1,6 @@ - - In order to test the purchase requisition module, I have to add a boolean field in product, - If I checked it then it's requisition create. + In order to test the purchase requisition module, I have to checked a boolean field 'purchase requisition' in product, + If I checked it then it's requisition will be create. - I start by Checking the product, Product must have requisition field checked. and Product supply method is buy and the procure method is make to order. @@ -9,7 +9,7 @@ supply_method: 'buy' purchase_requisition: True - - I create the procurement order for the product and after run the procurement create purchase requisition. + I create the procurement order for the product and after run that procurement for create purchase requisition. - !python {model: product.product}: | import time @@ -17,6 +17,7 @@ mk_proc = self.pool.get('make.procurement') proc_order = self.pool.get('procurement.order') pur_req = self.pool.get('purchase.requisition') + pur_order = self.pool.get('purchase.order') context = {'active_model': 'product.product','active_ids': [ref('product.product_product_hdd3')],'active_id': ref('product.product_product_hdd3')} default_data = mk_proc.default_get(cr, uid, ['uom_id', 'warehouse_id', 'date_planned', 'product_id', 'qty'], context) vals = {'uom_id': ref('product.product_uom_unit'),'warehouse_id': ref('stock.stock_warehouse_shop0'),'qty': default_data.get('qty'),'date_planned': default_data.get('date_planned')} @@ -32,11 +33,15 @@ wf_service.trg_validate(uid, 'procurement.order',proc.id,'button_check', cr) proc_ids = proc_order.search(cr, uid, [('id','=',req_id.get('res_id')),('state','in',['running'])]) proc_id = proc_order.browse(cr, uid, proc_ids) - assert proc_id[0].state == 'running',"Product's UOM is not correspond in procurement order" + assert proc_id[0].state == 'running',"Generated Procurement should be in Running state" if proc_id[0].requisition_id: + po_id = pur_order.search(cr, uid, [('requisition_id','=',proc_id[0].requisition_id.id)]) + po_req = pur_order.browse(cr, uid, po_id)[0].requisition_id pur_req_rec = pur_req.browse(cr, uid, [proc_id[0].requisition_id.id]) - assert pur_req_rec[0].state == 'draft',"Product's UOM is not correspond in procurement order" + assert po_req == proc_id[0].requisition_id,"Created Requisition is not properly linked in purchase order" + assert pur_req_rec[0].state == 'draft',"Created Requisition should be in draft state" for record in pur_req_rec[0].line_ids: - assert record.product_id.id == ref('product.product_product_hdd3'),"Product's UOM is not correspond in procurement order" - assert record.product_qty == default_data.get('qty'),"Product's UOM is not correspond in procurement order" - assert record.product_uom_id.id == ref('product.product_uom_unit'),"Product's UOM is not correspond in procurement order" + assert record.product_id.id == ref('product.product_product_hdd3'),"Requisition Product is not correspond" + assert record.product_qty == default_data.get('qty'),"Requisition Product's quantity is not correspond" + assert record.product_uom_id.id == ref('product.product_uom_unit'),"Requisition Product's UOM is not correspond" + diff --git a/addons/purchase_requisition/test/purchase_requisition_exclusive.yml b/addons/purchase_requisition/test/purchase_requisition_exclusive.yml deleted file mode 100644 index 1ab9bca9493..00000000000 --- a/addons/purchase_requisition/test/purchase_requisition_exclusive.yml +++ /dev/null @@ -1,113 +0,0 @@ -- - In order to test the purchase requisition module, I will do a sale order -> purchase_requisition -> - purchase flow and I will buy the required products at two different suppliers. -- - I start by creating a new product 'Laptop ACER', which is purchased at Asustek, in MTO, - with the generation of purchase requisitions. -- - !record {model: product.product, id: product_product_laptopacer1}: - categ_id: product.product_category_3 - cost_method: standard - list_price: 1000.0 - mes_type: fixed - name: Laptop ACER1 - procure_method: make_to_order - purchase_requisition: 1 - seller_ids: - - delay: 1 - name: base.res_partner_asus - qty: 5.0 - min_qty: 1.0 - supply_method: buy - type: product - uom_id: product.product_uom_unit - uom_po_id: product.product_uom_unit -- - Then I sell 5 Laptop ACER to the customer Agrolait, sale order TEST/TENDER/0002 -- - !record {model: sale.order, id: sale_order_testtender1}: - date_order: !eval time.strftime('%Y-%m-%d') - invoice_quantity: order - name: TEST/TENDER/0002 - order_line: - - name: Laptop ACER1 - price_unit: 1000.0 - product_uom: product.product_uom_unit - product_uom_qty: 5.0 - state: draft - 'delay': 7.0 - 'product_id': product_product_laptopacer1 - 'type': make_to_order - order_policy: manual - partner_id: base.res_partner_agrolait - partner_invoice_id: base.res_partner_address_8 - partner_order_id: base.res_partner_address_8 - partner_shipping_id: base.res_partner_address_8 - picking_policy: direct - pricelist_id: product.list0 - shop_id: sale.shop -- - I confirm sale order. -- - !workflow {model: sale.order, action: order_confirm, ref: sale_order_testtender1} -- - I launch the scheduler to compute all procurements, and planify all requisitions orders. -- - !python {model: procurement.order.compute.all}: | - proc_obj = self.pool.get('procurement.order') - proc_obj._procure_confirm(cr,uid) -- - I should find a purchase requisition with the origin 'TEST/TENDER/0002', that includes a request for - 5 Laptop ACER, and a purchase order on the default supplier for this product. -- - !python {model: purchase.requisition}: | - requisition_ids =self.search(cr, uid, [('origin','=','Laptop ACER1')]) - ids=len(requisition_ids) - assert len(requisition_ids), "Purchase requisition hasn't Created" -- - On the purchase requisition, I create a new purchase order for the supplier 'DistriPC' by clicking on - the button 'New Request for Quotation'. This opens a window to ask me the supplier and I set DistriPC . -- - I Create purchase.requisition.partner . -- - !record {model: purchase.requisition.partner, id: purchase_requisition_partner_0}: - partner_address_id: base.res_partner_address_7 - partner_id: base.res_partner_4 -- - I create a new purchase order for the supplier 'DistriPC'. -- - !python {model: purchase.requisition.partner}: | - req_obj = self.pool.get('purchase.requisition') - ids =req_obj.search(cr, uid, [('origin','=','Laptop ACER1')]) - self.create_order(cr, uid, [ref("purchase_requisition_partner_0")], {"lang": - 'en_US', "active_model": "purchase.requisition", "tz": False, "record_id": - 1, "active_ids": ids, "active_id": ids[0], }) -- - I set the purchase requisition as 'Exclusive' -- - !python {model: purchase.requisition}: | - ids =self.search(cr, uid, [('origin','=','Laptop ACER1')]) - self.write(cr,uid,ids[0],{'exclusive': 'exclusive' }) -- - I confirm and validate the Request for Quotation of ASUStek. -- - !python {model: purchase.order}: | - partner_id=self.pool.get('res.partner').search(cr,uid,[('name','=','ASUStek')])[0] - req_obj = self.pool.get('purchase.requisition') - ids =req_obj.search(cr, uid, [('origin','=','Laptop ACER1')]) - purchase_id= self.search(cr, uid, [('partner_id','=',partner_id),('requisition_id','in',ids)])[0] - import netsvc - wf_service = netsvc.LocalService("workflow") - if purchase_id: - wf_service.trg_validate(uid, 'purchase.order',purchase_id,'purchase_confirm', cr) - wf_service.trg_validate(uid, 'purchase.order',purchase_id,'purchase_approve', cr) -- - I check that Request for Quotation of DistriPC is cancelled. -- - !python {model: purchase.order}: | - partner_id=self.pool.get('res.partner').search(cr,uid,[('name','=','Distrib PC')])[0] - req_obj = self.pool.get('purchase.requisition') - ids =req_obj.search(cr, uid, [('origin','=','Laptop ACER1')]) - purchase_id= self.search(cr, uid, [('partner_id','=',partner_id),('requisition_id','in',ids)])[0] - state=self.browse(cr,uid,purchase_id).state - assert (state=='cancel') diff --git a/addons/purchase_requisition/test/ui/onchange_events.yml b/addons/purchase_requisition/test/ui/onchange_events.yml new file mode 100644 index 00000000000..683edbc6aeb --- /dev/null +++ b/addons/purchase_requisition/test/ui/onchange_events.yml @@ -0,0 +1,23 @@ +- + In order to test the onchange events of purchase requisition. +- + I call onchange event to change the product of purchase requisition line. +- + !python {model: purchase.requisition.line}: | + self.onchange_product_id(cr, uid, [ref('order_purchase_requisition1')],ref('product.product_product_hdd2'), ref('product.product_uom_unit')) +- + I change state of requisition in "In progress". +- + !python {model: purchase.requisition}: | + self.tender_in_progress(cr, uid, ref('order_purchase_requisition1')) +- + I change state of requisition as "done". +- + !python {model: purchase.requisition}: | + self.tender_done(cr, uid, ref('order_purchase_requisition1')) +- + I reset the state of requisition as "New". +- + !python {model: purchase.requisition}: | + self.tender_reset(cr, uid, ref('order_purchase_requisition1')) + From b13ddc11a75f70a4a7dad313d13de68a5eb76e73 Mon Sep 17 00:00:00 2001 From: "DBR (OpenERP)" Date: Mon, 31 Oct 2011 18:11:05 +0530 Subject: [PATCH 007/117] [ADD,MOVE,IMP]purchase_requisition: [ADD]cancel_purchase_requisition.yml [ADD]duplicate_requisition.yml [MOVE]purchase_requisition_test.yml => test/ui/delete_requisition.yml [IMP]delete_requisition.yml [IMP]set the propare sequence in __openerp__.py bzr revid: dbr@tinyerp.com-20111031124105-x0rp6cg5e98lsjrp --- addons/purchase_requisition/__openerp__.py | 3 + .../process/cancel_purchase_requisition.yml | 8 + .../test/purchase_requisition_test.yml | 166 ------------------ .../test/ui/delete_requisition.yml | 27 +++ .../test/ui/duplicate_requisition.yml | 8 + .../{ => ui}/purchase_requisition_report.yml | 0 6 files changed, 46 insertions(+), 166 deletions(-) create mode 100644 addons/purchase_requisition/test/process/cancel_purchase_requisition.yml delete mode 100755 addons/purchase_requisition/test/purchase_requisition_test.yml create mode 100755 addons/purchase_requisition/test/ui/delete_requisition.yml create mode 100644 addons/purchase_requisition/test/ui/duplicate_requisition.yml rename addons/purchase_requisition/test/{ => ui}/purchase_requisition_report.yml (100%) diff --git a/addons/purchase_requisition/__openerp__.py b/addons/purchase_requisition/__openerp__.py index e655a574e42..bbe2551a14e 100644 --- a/addons/purchase_requisition/__openerp__.py +++ b/addons/purchase_requisition/__openerp__.py @@ -45,7 +45,10 @@ This new object will regroup and will allow you to easily keep track and order a "active": False, "test":[ 'test/process/purchase_requisition.yml', + 'test/process/cancel_purchase_requisition.yml', 'test/ui/onchange_events.yml', + 'test/ui/purchase_requisition_report.yml', + 'test/ui/delete_requisition.yml', ], "installable": True, "certificate" : "001023264099823179629", diff --git a/addons/purchase_requisition/test/process/cancel_purchase_requisition.yml b/addons/purchase_requisition/test/process/cancel_purchase_requisition.yml new file mode 100644 index 00000000000..cb85b32d044 --- /dev/null +++ b/addons/purchase_requisition/test/process/cancel_purchase_requisition.yml @@ -0,0 +1,8 @@ +- + In order to test the cancel purchase requisition order. +- + I try to cancel purchase requisition order. +- + !python {model: purchase.requisition}: | + self.tender_cancel(cr, uid, [ref("order_purchase_requisition1")]) + diff --git a/addons/purchase_requisition/test/purchase_requisition_test.yml b/addons/purchase_requisition/test/purchase_requisition_test.yml deleted file mode 100755 index 403eaca04fc..00000000000 --- a/addons/purchase_requisition/test/purchase_requisition_test.yml +++ /dev/null @@ -1,166 +0,0 @@ -- - In order to test the purchase requisition flow,I start by creating a new product 'MOB1' -- - !record {model: product.product, id: product_product_mob1}: - name: MOB1 - categ_id: product.product_category_3 - cost_method: standard - mes_type: fixed - price_margin: 2.0 - procure_method: make_to_stock - property_stock_inventory: stock.location_inventory - property_stock_procurement: stock.location_procurement - property_stock_production: stock.location_production - standard_price: 2000.0 - supply_method: buy - type: product - uom_id: product.product_uom_unit - uom_po_id: product.product_uom_unit - volume: 0.0 - warranty: 0.0 - weight: 0.0 - weight_net: 0.0 -- - I create purchase requisition for MOB1 for 1 quantity. -- - !record {model: purchase.requisition, id: purchase_requisition_te0}: - company_id: base.main_company - exclusive: multiple - line_ids: - - company_id: base.main_company - product_id: product_product_mob1 - product_qty: 10.0 - product_uom_id: product.product_uom_unit - name: TE00009 -- - Initially purchase requisition is in draft state. -- - !assert {model: purchase.requisition, id: purchase_requisition_te0}: - - state == 'draft' -- - Copy purchase requisition which is in draft state than confirm and Done it. -- - !python {model: purchase.requisition}: | - copy_id = self.copy(cr, uid, ref("purchase_requisition_te0")) - self.tender_cancel(cr, uid, [copy_id], context=None) - self.tender_reset(cr, uid, [copy_id], context=None) - self.tender_in_progress(cr, uid, [copy_id], context=None) - self.tender_done(cr, uid, [copy_id], context=None) -- - I confirm the purchase requisition for MOB1. -- - !python {model: purchase.requisition}: | - self.tender_in_progress(cr, uid, [ref("purchase_requisition_te0")]) -- - I check that the purchase requisition which was initially in the draft state has transmit to In Progress after confirm it. -- - !assert {model: purchase.requisition, id: purchase_requisition_te0}: - - state == 'in_progress' -- - In order to create a purchase order for 'Axelor', i click on the wizard 'Request a Quotation' and create record for wizard. -- - !record {model: purchase.requisition.partner, id: purchase_requisition_partner_0}: - partner_address_id: base.res_partner_address_3000 - partner_id: base.res_partner_desertic_hispafuentes -- - I click on 'Create Quotation' for creating PO. -- - !python {model: purchase.requisition.partner}: | - self.create_order(cr, uid, [ref("purchase_requisition_partner_0")], {"active_model": "purchase.requisition", - "active_ids": [ref("purchase_requisition_te0")],"active_id": ref("purchase_requisition_te0"), }) -- - I confirm the purchase order of Axelor. -- - !python {model: purchase.order}: | - purchase_id= self.search(cr, uid, [('requisition_id','=',ref("purchase_requisition_te0"))]) - import netsvc - wf_service = netsvc.LocalService("workflow") - if purchase_id: - wf_service.trg_validate(uid, 'purchase.order',purchase_id[0],'purchase_confirm', cr) - wf_service.trg_validate(uid, 'purchase.order',purchase_id[0],'purchase_approve', cr) -- - I check that Quotation of Axelor is Approved. -- - !python {model: purchase.order}: | - purchase_id= self.search(cr, uid, [('requisition_id','=',ref("purchase_requisition_te0"))])[0] - state=self.browse(cr,uid,purchase_id).state - assert (state=='approved') -- - I click on Done button -- - !python {model: purchase.requisition}: | - self.tender_done(cr, uid, [ref("purchase_requisition_te0")],) -- - I check that after click on Done button state is in done. -- - !assert {model: purchase.requisition, id: purchase_requisition_te0}: - - state == 'done' -- - In order to test the purchase requisition flow for Requisition Type is exclusive -- - I create purchase requisition for Requisition Type is exclusive -- - !record {model: purchase.requisition, id: purchase_requisition_ex1}: - company_id: base.main_company - exclusive: exclusive - line_ids: - - company_id: base.main_company - product_id: product_product_mob1 - product_qty: 10.0 - product_uom_id: product.product_uom_unit - name: TE000010 -- - I Create a First Purchase Order for the supplier 'Distrib PC'. -- - !record {model: purchase.requisition.partner, id: purchase_requisition_partner_1}: - partner_address_id: base.res_partner_address_7 - partner_id: base.res_partner_4 -- - I create Quotations For supplier 'Distrib PC'. -- - !python {model: purchase.requisition.partner}: | - self.create_order(cr, uid, [ref("purchase_requisition_partner_1")], {"active_model": "purchase.requisition", - "active_ids": [ref("purchase_requisition_ex1")],"active_id": ref("purchase_requisition_ex1"), }) -- - I Create a Second Purchase Order for the supplier ASUStek. -- - !record {model: purchase.requisition.partner, id: purchase_requisition_partner_2}: - partner_address_id: base.res_partner_address_tang - partner_id: base.res_partner_asus -- - I create Quotations For supplier 'ASUStek'. -- - !python {model: purchase.requisition.partner}: | - self.create_order(cr, uid, [ref("purchase_requisition_partner_2")], {"active_model": "purchase.requisition", - "active_ids": [ref("purchase_requisition_ex1")],"active_id": ref("purchase_requisition_ex1"), }) -- - I check that Initially purchase requisition is draft state. -- - !assert {model: purchase.requisition, id: purchase_requisition_ex1}: - - state == 'draft' -- - I confirm the Second purchase order of ASUStek, than check that Quotation is Approved. -- - !python {model: purchase.order}: | - purchase_id= self.search(cr, uid, [('partner_id','=',ref("base.res_partner_asus")),('requisition_id','=',ref("purchase_requisition_ex1"))]) - import netsvc - wf_service = netsvc.LocalService("workflow") - if purchase_id: - wf_service.trg_validate(uid, 'purchase.order',purchase_id[0],'purchase_confirm', cr) - wf_service.trg_validate(uid, 'purchase.order',purchase_id[0],'purchase_approve', cr) - state=self.browse(cr,uid,purchase_id[0]).state - assert (state=='approved') - -- - I check that Quotation of Distrib PC is cancelled. -- - !python {model: purchase.order}: | - partner_id=self.pool.get('res.partner').search(cr,uid,[('name','=','Distrib PC')])[0] - purchase_id= self.search(cr, uid, [('partner_id','=',partner_id),('requisition_id','=',ref("purchase_requisition_ex1"))])[0] - state=self.browse(cr,uid,purchase_id).state - assert (state=='cancel') -- - I check that Purchase Requisition is Done. -- - !assert {model: purchase.requisition, id: purchase_requisition_ex1}: - - state == 'done' diff --git a/addons/purchase_requisition/test/ui/delete_requisition.yml b/addons/purchase_requisition/test/ui/delete_requisition.yml new file mode 100755 index 00000000000..f3ca08674f4 --- /dev/null +++ b/addons/purchase_requisition/test/ui/delete_requisition.yml @@ -0,0 +1,27 @@ +- + In order to test the duplicate order and check duplicate details. +- + I duplicate order. +- + !python {model: purchase.requisition}: | + context.update({'active_id':ref('order_purchase_requisition1')}) + self.copy(cr, uid, ref('order_purchase_requisition1'), context) +- + In order to test to delete process on purchase requisition order. +- + I delete draft purchase requisition order. +- + !python {model: purchase.order}: | + self.unlink(cr, uid, [ref("order_purchase_requisition1")]) +- + Now I try to cancel purchase requisition order. +- + !python {model: purchase.requisition}: | + self.tender_cancel(cr, uid, [ref("order_purchase_requisition1")]) +- + I delete cancelled purchase requisition order. +- + !python {model: purchase.order}: | + self.unlink(cr, uid, [ref("order_purchase_requisition1")]) + + diff --git a/addons/purchase_requisition/test/ui/duplicate_requisition.yml b/addons/purchase_requisition/test/ui/duplicate_requisition.yml new file mode 100644 index 00000000000..742500d865d --- /dev/null +++ b/addons/purchase_requisition/test/ui/duplicate_requisition.yml @@ -0,0 +1,8 @@ +- + In order to test the duplicate order and check duplicate details. +- + I duplicate order. +- + !python {model: purchase.requisition}: | + context.update({'active_id':ref('order_purchase_requisition1')}) + self.copy(cr, uid, ref('order_purchase_requisition1'), context) diff --git a/addons/purchase_requisition/test/purchase_requisition_report.yml b/addons/purchase_requisition/test/ui/purchase_requisition_report.yml similarity index 100% rename from addons/purchase_requisition/test/purchase_requisition_report.yml rename to addons/purchase_requisition/test/ui/purchase_requisition_report.yml From a8b7872502ce9f73ebf4741d3d51152b1ffa19f7 Mon Sep 17 00:00:00 2001 From: "DBR (OpenERP)" Date: Mon, 31 Oct 2011 18:17:28 +0530 Subject: [PATCH 008/117] [IMP]purchase_requisition: remove the extra code bzr revid: dbr@tinyerp.com-20111031124728-pmrrp4bq5h1iwps5 --- .../purchase_requisition/test/ui/delete_requisition.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/addons/purchase_requisition/test/ui/delete_requisition.yml b/addons/purchase_requisition/test/ui/delete_requisition.yml index f3ca08674f4..c077784a73e 100755 --- a/addons/purchase_requisition/test/ui/delete_requisition.yml +++ b/addons/purchase_requisition/test/ui/delete_requisition.yml @@ -1,11 +1,3 @@ -- - In order to test the duplicate order and check duplicate details. -- - I duplicate order. -- - !python {model: purchase.requisition}: | - context.update({'active_id':ref('order_purchase_requisition1')}) - self.copy(cr, uid, ref('order_purchase_requisition1'), context) - In order to test to delete process on purchase requisition order. - From f45e2468bc96a191d82fc1b081e8388c531af1e0 Mon Sep 17 00:00:00 2001 From: "DBR (OpenERP)" Date: Wed, 2 Nov 2011 13:05:52 +0530 Subject: [PATCH 009/117] [ADD,IMP] purchase_requisition: [ADD]Add New file for define the main flow of exclusive requisition "purchase_requisition_exclusive.yml" [IMP]Improve the demo data for exclisive code improvement [IMP]Add one new file in __openerp__.py bzr revid: dbr@tinyerp.com-20111102073552-yruxrxuvb9qji3pg --- addons/purchase_requisition/__openerp__.py | 1 + .../purchase_requisition_demo.xml | 42 ++++++++++++++++++- .../purchase_requisition_exclusive.yml | 38 +++++++++++++++++ 3 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 addons/purchase_requisition/test/process/purchase_requisition_exclusive.yml diff --git a/addons/purchase_requisition/__openerp__.py b/addons/purchase_requisition/__openerp__.py index bbe2551a14e..bf21d7f3232 100644 --- a/addons/purchase_requisition/__openerp__.py +++ b/addons/purchase_requisition/__openerp__.py @@ -45,6 +45,7 @@ This new object will regroup and will allow you to easily keep track and order a "active": False, "test":[ 'test/process/purchase_requisition.yml', + 'test/process/purchase_requisition_exclusive.yml', 'test/process/cancel_purchase_requisition.yml', 'test/ui/onchange_events.yml', 'test/ui/purchase_requisition_report.yml', diff --git a/addons/purchase_requisition/purchase_requisition_demo.xml b/addons/purchase_requisition/purchase_requisition_demo.xml index deb25fe9e14..728d5fbdffd 100644 --- a/addons/purchase_requisition/purchase_requisition_demo.xml +++ b/addons/purchase_requisition/purchase_requisition_demo.xml @@ -10,7 +10,7 @@ - multiple + exclusive @@ -24,6 +24,46 @@ 5 + + + + + + + + + + + + + + + + + + + + + + + + [CPU1] Processor AMD Athlon XP 1800+ + + + 60 + 3 + + + + + + [CPU3] Processor AMD Athlon XP 2200+ + + + 50 + 13 + + diff --git a/addons/purchase_requisition/test/process/purchase_requisition_exclusive.yml b/addons/purchase_requisition/test/process/purchase_requisition_exclusive.yml new file mode 100644 index 00000000000..d3bb3a5e97e --- /dev/null +++ b/addons/purchase_requisition/test/process/purchase_requisition_exclusive.yml @@ -0,0 +1,38 @@ +- + Create two PO on based of one tender, + than confirm any one PO the second PO automatically goes in to cancel state. + order_purchase_requisition1 +- + In order to test the exclusive type requisition, I have to create two differ purchase order in one requisition [Tender] +- + I start by Checking the product, Product must have requisition field checked. +- + !record {model: product.product, id: product.product_product_cpu1}: + purchase_requisition: True +- + Checking requisition field for another product. +- + !record {model: product.product, id: product.product_product_cpu3}: + purchase_requisition: True +- + Now check that purchase order's product must have requisition field checked. +- + !python {model: purchase.order}: | + import netsvc + wf_service = netsvc.LocalService("workflow") + pur_order = self.pool.get('purchase.order') + ids = pur_order.search(cr, uid, [('requisition_id','=',ref('order_purchase_requisition1'))]) + po_id = pur_order.browse(cr, uid, ids) + for po in po_id: + for line in po.order_line: + if line.product_id.purchase_requisition == False: + assert line.product_id.purchase_requisition == True, "Purchase Order's product must have requisition field checked" + po_confirm = po_id[0].id + wf_service.trg_validate(uid, 'purchase.order',po_confirm,'purchase_confirm', cr) + assert po_id[0].state == 'approved',"After confirm a purchase order it should be in confirm state" + assert po_id[1].state == 'cancel',"After confirmed a purchase order form the this requisition the second purchase order should be automatically goes in to cancelled state" + + + + + From e90122bb113a6404df6a9efa11c0b5648146f84f Mon Sep 17 00:00:00 2001 From: "DBR (OpenERP)" Date: Wed, 2 Nov 2011 13:08:20 +0530 Subject: [PATCH 010/117] [IMP]purchase_requisition: Remove extra statements bzr revid: dbr@tinyerp.com-20111102073820-kn5zvxgsxpkjmi7i --- .../test/process/purchase_requisition_exclusive.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/addons/purchase_requisition/test/process/purchase_requisition_exclusive.yml b/addons/purchase_requisition/test/process/purchase_requisition_exclusive.yml index d3bb3a5e97e..d68c12c6366 100644 --- a/addons/purchase_requisition/test/process/purchase_requisition_exclusive.yml +++ b/addons/purchase_requisition/test/process/purchase_requisition_exclusive.yml @@ -1,7 +1,3 @@ -- - Create two PO on based of one tender, - than confirm any one PO the second PO automatically goes in to cancel state. - order_purchase_requisition1 - In order to test the exclusive type requisition, I have to create two differ purchase order in one requisition [Tender] - From 85d601efb3333b5d4c0a2c9e841ed3b7930d09e1 Mon Sep 17 00:00:00 2001 From: "DBR (OpenERP)" Date: Wed, 2 Nov 2011 15:58:09 +0530 Subject: [PATCH 011/117] [ADD,IMP] purchase_requisition: [ADD]purchase_requisition/test/ui/requisiton2request_quotation.yml [IMP]add new file in __openerp__.py [IMP]Improve code of onchange_events.yml bzr revid: dbr@tinyerp.com-20111102102809-c3cjgz7a331sdawr --- addons/purchase_requisition/__openerp__.py | 3 ++- .../purchase_requisition_exclusive.yml | 4 ---- .../test/ui/onchange_events.yml | 7 +++++- .../test/ui/requisiton2request_quotation.yml | 23 +++++++++++++++++++ 4 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 addons/purchase_requisition/test/ui/requisiton2request_quotation.yml diff --git a/addons/purchase_requisition/__openerp__.py b/addons/purchase_requisition/__openerp__.py index bf21d7f3232..426e8a770fc 100644 --- a/addons/purchase_requisition/__openerp__.py +++ b/addons/purchase_requisition/__openerp__.py @@ -45,7 +45,8 @@ This new object will regroup and will allow you to easily keep track and order a "active": False, "test":[ 'test/process/purchase_requisition.yml', - 'test/process/purchase_requisition_exclusive.yml', + 'test/process/purchase_requisition_exclusive.yml', + 'test/ui/requisiton2request_quotation.yml', 'test/process/cancel_purchase_requisition.yml', 'test/ui/onchange_events.yml', 'test/ui/purchase_requisition_report.yml', diff --git a/addons/purchase_requisition/test/process/purchase_requisition_exclusive.yml b/addons/purchase_requisition/test/process/purchase_requisition_exclusive.yml index d68c12c6366..8a9116de0d3 100644 --- a/addons/purchase_requisition/test/process/purchase_requisition_exclusive.yml +++ b/addons/purchase_requisition/test/process/purchase_requisition_exclusive.yml @@ -28,7 +28,3 @@ assert po_id[0].state == 'approved',"After confirm a purchase order it should be in confirm state" assert po_id[1].state == 'cancel',"After confirmed a purchase order form the this requisition the second purchase order should be automatically goes in to cancelled state" - - - - diff --git a/addons/purchase_requisition/test/ui/onchange_events.yml b/addons/purchase_requisition/test/ui/onchange_events.yml index 683edbc6aeb..901c50ca1c9 100644 --- a/addons/purchase_requisition/test/ui/onchange_events.yml +++ b/addons/purchase_requisition/test/ui/onchange_events.yml @@ -20,4 +20,9 @@ - !python {model: purchase.requisition}: | self.tender_reset(cr, uid, ref('order_purchase_requisition1')) - +- + I call onchange event to change the partner of purchase requisition. +- + !python {model: purchase.requisition.partner}: | + self.onchange_partner_id(cr, uid, ref('order_purchase_requisition1'), ref('base.res_partner_desertic_hispafuentes')) + diff --git a/addons/purchase_requisition/test/ui/requisiton2request_quotation.yml b/addons/purchase_requisition/test/ui/requisiton2request_quotation.yml new file mode 100644 index 00000000000..6c0ce5eee0a --- /dev/null +++ b/addons/purchase_requisition/test/ui/requisiton2request_quotation.yml @@ -0,0 +1,23 @@ +- + In order to create a Quotatoion, I click on the wizard 'Request a Quotation' and create record from wizard. +- + !record {model: purchase.requisition.partner, id: purchase_requisition_partner_0}: + partner_address_id: base.res_partner_address_3000 + partner_id: base.res_partner_desertic_hispafuentes +- + I click on 'Create Quotation' for creating PO. +- + !python {model: purchase.requisition.partner}: | + self.create_order(cr, uid, [ref("purchase_requisition_partner_0")], {"active_model": "purchase.requisition", + "active_ids": [ref("order_purchase_requisition1")],"active_id": ref("order_purchase_requisition1"), }) +- + I check that the purchase order is created. +- + !python {model: purchase.order}: | + purchase_ids= self.search(cr, uid, [('requisition_id','=',ref("order_purchase_requisition1"))]) + assert purchase_ids, "Purchase Order is not created from this wizard" + rfq = self.browse(cr, uid, purchase_ids[0]) + assert rfq.state == 'draft',"Purchase Order should be in draft state" + assert rfq.partner_address_id.id == ref('base.res_partner_address_3000'),"Purchase Order Partner address is not correspond" + assert rfq.partner_id.id == ref('base.res_partner_desertic_hispafuentes'),"Purchase Order Partner is not correspond" + From 7b800b5f03c9e1bd86884979b60cb5f7348af6bd Mon Sep 17 00:00:00 2001 From: "DBR (OpenERP)" Date: Wed, 2 Nov 2011 16:15:31 +0530 Subject: [PATCH 012/117] [IMP] purchase_requisition: Improve the code for cancel_purchase_requisition.yml file bzr revid: dbr@tinyerp.com-20111102104531-itiutuktds163710 --- .../process/cancel_purchase_requisition.yml | 61 ++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/addons/purchase_requisition/test/process/cancel_purchase_requisition.yml b/addons/purchase_requisition/test/process/cancel_purchase_requisition.yml index cb85b32d044..eeae4689fbc 100644 --- a/addons/purchase_requisition/test/process/cancel_purchase_requisition.yml +++ b/addons/purchase_requisition/test/process/cancel_purchase_requisition.yml @@ -5,4 +5,63 @@ - !python {model: purchase.requisition}: | self.tender_cancel(cr, uid, [ref("order_purchase_requisition1")]) - +- + I check that purchase requisition order is cancelled. +- + !assert {model: purchase.requisition, id: order_purchase_requisition1}: + - state == 'cancel' +- + I change state of requisition in "In progress". +- + !python {model: purchase.requisition}: | + self.tender_in_progress(cr, uid, ref('order_purchase_requisition1')) +- + I check that purchase requisition order is "In progress". +- + !assert {model: purchase.requisition, id: order_purchase_requisition1}: + - state == 'in_progress' +- + I try to cancel "In progress" purchase requisition order. +- + !python {model: purchase.requisition}: | + self.tender_cancel(cr, uid, [ref("order_purchase_requisition1")]) +- + I check that purchase requisition order is cancelled. +- + !assert {model: purchase.requisition, id: order_purchase_requisition1}: + - state == 'cancel' +- + I reset the state of requisition as "New". +- + !python {model: purchase.requisition}: | + self.tender_reset(cr, uid, ref('order_purchase_requisition1')) +- + I check that purchase requisition order is New. +- + !assert {model: purchase.requisition, id: order_purchase_requisition1}: + - state == 'draft' +- + I change state of requisition as "done". +- + !python {model: purchase.requisition}: | + self.tender_done(cr, uid, ref('order_purchase_requisition1')) +- + I check that purchase requisition order is Done. +- + !assert {model: purchase.requisition, id: order_purchase_requisition1}: + - state == 'done' +- + I try to cancel 'Done' purchase requisition order. +- + !python {model: purchase.requisition}: | + self.tender_cancel(cr, uid, [ref("order_purchase_requisition1")]) +- + I check that purchase requisition order is cancelled. +- + !assert {model: purchase.requisition, id: order_purchase_requisition1}: + - state == 'cancel' +- + I reset the state of requisition as "New". +- + !python {model: purchase.requisition}: | + self.tender_reset(cr, uid, ref('order_purchase_requisition1')) From 1132f8cb5870ca6339e214804ac32949849e92d9 Mon Sep 17 00:00:00 2001 From: "Jagdish Panchal (Open ERP)" Date: Tue, 15 Nov 2011 16:00:28 +0530 Subject: [PATCH 013/117] [IMP] hr: improve test case of process of Job position to open job, to start requirement and close job position bzr revid: jap@tinyerp.com-20111115103028-5zmfzal87kpdicaf --- addons/hr/__openerp__.py | 5 +- addons/hr/test/hr_employee_demo.yml | 55 +++++++ .../test/process/open2recruit2close_job.yml | 39 +++++ addons/hr/test/test_hr.yml | 140 ------------------ 4 files changed, 98 insertions(+), 141 deletions(-) create mode 100644 addons/hr/test/hr_employee_demo.yml create mode 100644 addons/hr/test/process/open2recruit2close_job.yml delete mode 100644 addons/hr/test/test_hr.yml diff --git a/addons/hr/__openerp__.py b/addons/hr/__openerp__.py index 900c689dfbf..b78e9c03916 100644 --- a/addons/hr/__openerp__.py +++ b/addons/hr/__openerp__.py @@ -54,7 +54,10 @@ You can manage: 'hr_demo.xml', 'hr_department_demo.xml', ], - 'test': ['test/test_hr.yml'], + 'test': [ + 'test/hr_employee_demo.yml', + 'test/process/open2recruit2close_job.yml', + ], 'installable': True, 'active': False, 'certificate': '0086710558965', diff --git a/addons/hr/test/hr_employee_demo.yml b/addons/hr/test/hr_employee_demo.yml new file mode 100644 index 00000000000..31cf58c2788 --- /dev/null +++ b/addons/hr/test/hr_employee_demo.yml @@ -0,0 +1,55 @@ +- + !record {model: hr.department, id: hr_department_rd0}: + manager_id: base.user_root + name: 'R & D' +- + !record {model: hr.job, id: hr_job_jea0}: + department_id: 'hr_department_rd0' + description: 'Position of Junior Application Engineer' + expected_employees: 5.0 + name: 'JAE' + no_of_employee: 0.0 + no_of_recruitment: 5.0 + state: open +- + !record {model: hr.job, id: hr_job_jea0}: + employee_ids: + - address_home_id: base.res_partner_address_1 + name: Manuel Lehba + department_id: 'hr_department_rd0' + gender: male + parent_id: hr.employee1 +- + !record {model: hr.employee, id: hr_employee001, view: False}: + address_id: base.main_address + company_id: base.main_company + department_id: hr_department_rd0 + name: smith + parent_id: hr.employee1 + user_id: base.user_demo +- + !record {model: hr.employee, id: hr_employee_edwin0}: + address_home_id: base.res_partner_address_3000 + address_id: base.res_partner_address_rogerpecker0 + department_id: hr.dep_administration + job_id: hr.job_hr_manager + name: Edwin + parent_id: hr.employee2 + resource_type: user + time_efficiency: 1.0 + user_id: base.user_demo +- + !record {model: hr.employee.category, id: hr_employee_category_fresher0}: + name: Fresher +- + !record {model: hr.employee.category, id: hr_employee_category_juniorlevel0}: + name: Junior Level + parent_id: hr_employee_category_fresher0 +- + + + + + + + diff --git a/addons/hr/test/process/open2recruit2close_job.yml b/addons/hr/test/process/open2recruit2close_job.yml new file mode 100644 index 00000000000..aedd2a3d2a1 --- /dev/null +++ b/addons/hr/test/process/open2recruit2close_job.yml @@ -0,0 +1,39 @@ +- + In Order to test process of Job Position, +- + I open Job Postion of "Jr. Application Engineer" Profile. +- + !python {model: hr.job}: | + self.job_open(cr, uid, [ref('hr_job_jea0')]) +- + I check state of Job Position after opened it. +- + !assert {model: hr.job, id: hr_job_jea0}: + - state == 'open' +- + Now, Recruitement is started so I start recruitement of Job Postion of "Jr. Application Engineer" Profile. +- + !python {model: hr.job}: | + self.job_recruitement(cr, uid, [ref('hr_job_jea0')]) +- + I check state and number of Expected in Recruitment in Job Position of "Jr. Application Engineer" Profile. +- + !assert {model: hr.job, id: hr_job_jea0}: + - state == 'recruit' + - no_of_recruitment == 1.0 +- + I hired new employee for the job position so I set Job Position of "Jr. Application Engineer" Profile to new employee. +- + !python {model: hr.employee}: | + self.write(cr, uid, [ref('hr_employee001')], {'job_id':ref('hr_job_jea0')}) +- + Now I don't want to recruit new employee on this position. so I mark it as Old. +- + !python {model: hr.job}: | + self.job_old(cr, uid, [ref('hr_job_jea0')]) +- + I check state of Job position and number of Expected in Recruitment after closed Job position. +- + !assert {model: hr.job, id: hr_job_jea0}: + - state == 'old' + - no_of_recruitment == 0 diff --git a/addons/hr/test/test_hr.yml b/addons/hr/test/test_hr.yml deleted file mode 100644 index 7b4ba82b243..00000000000 --- a/addons/hr/test/test_hr.yml +++ /dev/null @@ -1,140 +0,0 @@ -- - In order to test hr module in OpenERP, I will create new Employee, Department and Job Position. -- - I create "R&D Department" in Department form. -- - !record {model: hr.department, id: hr_department_rd0}: - manager_id: base.user_root - name: 'R & D' -- - Now, I create a new employee “Mark Johnson”, and select department as “R&D Department”. -- - !record {model: hr.employee, id: hr_employee_mark}: - address_home_id: base.res_partner_address_1 - company_id: base.main_company - gender: male - marital: 'single' - name: Mark Johnson -- - I change the company of the employee. -- - !python {model: hr.employee}: | - res = self.onchange_company(cr, uid, [ref('hr_employee_mark')], ref('base.main_company'), None) - values = dict([('company_id', ref('base.main_company'))] + res['value'].items()) - self.write(cr, uid, [ref('hr_employee_mark')], values, None) -- - I assign department for employee “Mark Johnson”. -- - !python {model: hr.employee}: | - res = self.onchange_department_id(cr, uid, [ref('hr_employee_mark')], ref('hr_department_rd0'), None) - assert res['value']['parent_id'] - values = dict([('department_id', ref('hr_department_rd0'))] + res['value'].items()) - self.write(cr, uid, [ref('hr_employee_mark')], values, None) -- - Now I create a user for employee “Mark Johnson”. -- - !record {model: res.users, id: hr_users_markjohnson0}: - context_lang: en_US - groups_id: - - base.group_user - login: markjohnson - name: Mark Johnson - password: markjohnson -- - I assign user to employee “Mark Johnson”. -- - !python {model: hr.employee}: | - res = self.onchange_user(cr, uid, [ref('hr_employee_mark')], ref('hr_users_markjohnson0'), None) - values = dict([('user_id', ref('hr_users_markjohnson0'))] + res['value'].items()) - self.write(cr, uid, [ref('hr_employee_mark')], values, None) -- - In order to check the wizard “Employee Hierarchy” , I will create new employee “Phil Graves” and select “Mark Johnson” as - Manager. -- - !record {model: hr.employee, id: hr_employee_phil}: - address_home_id: base.res_partner_address_3000 - company_id: base.main_company - gender: male - name: Phil Graves - user_id: base.user_demo - parent_id: 'hr_employee_mark' -- - I fill the Working address for Employee. -- - !python {model: hr.employee}: | - res = self.onchange_address_id(cr, uid, ref('hr_employee_phil'), ref('base.res_partner_address_3000'), None) - assert res['value'] - values = dict([('address_id', ref('base.res_partner_address_3000'))] + res['value'].items()) - self.write(cr, uid, [ref('hr_employee_phil')], values, None) -- - I will open up form view of “Mark Johnson” and test the wizard “Employee Hierarchy” so it display the employee - hierarchy starting from “Mark Johnson”. - -- - I will create new Job Position. I will check successful creation of new Job Position by adding the information. -- - !record {model: hr.job, id: hr_job_jea0}: - department_id: 'hr_department_rd0' - description: 'Position of Junior Application Engineer' - expected_employees: 5 - name: 'JAE' -- - I check that Employee form is in "Open" state. -- - !assert {model: hr.job, id: hr_job_jea0}: - - state == 'open' -- - I create Employee for job position. -- - !record {model: hr.job, id: hr_job_jea0}: - employee_ids: - - address_home_id: base.res_partner_address_1 - name: Manuel Lehba - department_id: 'hr_department_rd0' - gender: male - parent_id: 'hr_employee_mark' -- - I check that "Number of Employees" field have some value. -- - !assert {model: hr.job, id: hr_job_jea0}: - - no_of_employee != False -- - As more requirements on the said job position are come, I increase the number of expected employees. -- - !python {model: hr.job}: | - res = self.on_change_expected_employee(cr, uid, [ref('hr_job_jea0')], 6, 3, None) - assert res['value']['expected_employees'] - values = dict([('expected_employees', ref('hr_job_jea0'))] + res['value'].items()) - self.write(cr, uid, [ref('hr_job_jea0')], values, None) -- - I open the job position for recruitment. -- - !python {model: hr.job}: | - self.job_recruitement(cr, uid, [ref('hr_job_jea0')]) -- - I assign the job position to employee and mark the position. -- - !python {model: hr.job}: | - self.job_open(cr, uid, [ref('hr_job_jea0')]) -- - Now the process is over so I don't want to use this position. I mark it as Old. -- - !python {model: hr.job}: | - self.job_old(cr, uid, [ref('hr_job_jea0')]) -- - I create a parent category for the new recruited employees who are Freshers. -- - !record {model: hr.employee.category, id: hr_employee_category_fresher0}: - name: Fresher -- - I create another category for Junior Level freshers. -- - !record {model: hr.employee.category, id: hr_employee_category_juniorlevel0}: - name: Junior Level - parent_id: hr_employee_category_fresher0 -- - I open the tree view of Categories and see the categories in a hierarchical manner. -- - !python {model: hr.employee.category}: | - res = self.name_get(cr, uid, [ref('hr_employee_category_juniorlevel0')], None) - assert res From 376d264fcbae95790c0b6c149bbdbeaa6514f352 Mon Sep 17 00:00:00 2001 From: "Jagdish Panchal (Open ERP)" Date: Thu, 17 Nov 2011 14:01:43 +0530 Subject: [PATCH 014/117] [IMP] hr: improve test case of job process bzr revid: jap@tinyerp.com-20111117083143-rjsfxp8ayx78nryr --- addons/hr/__openerp__.py | 2 +- addons/hr/test/hr_employee_demo.yml | 46 +++---------------- .../{process => }/open2recruit2close_job.yml | 16 +++---- 3 files changed, 15 insertions(+), 49 deletions(-) rename addons/hr/test/{process => }/open2recruit2close_job.yml (70%) diff --git a/addons/hr/__openerp__.py b/addons/hr/__openerp__.py index b78e9c03916..c1a75cbb7f5 100644 --- a/addons/hr/__openerp__.py +++ b/addons/hr/__openerp__.py @@ -56,7 +56,7 @@ You can manage: ], 'test': [ 'test/hr_employee_demo.yml', - 'test/process/open2recruit2close_job.yml', + 'test/open2recruit2close_job.yml', ], 'installable': True, 'active': False, diff --git a/addons/hr/test/hr_employee_demo.yml b/addons/hr/test/hr_employee_demo.yml index 31cf58c2788..846747e9a25 100644 --- a/addons/hr/test/hr_employee_demo.yml +++ b/addons/hr/test/hr_employee_demo.yml @@ -1,10 +1,10 @@ - - !record {model: hr.department, id: hr_department_rd0}: + !record {model: hr.department, id: dep_technical, view: False}: manager_id: base.user_root name: 'R & D' - - !record {model: hr.job, id: hr_job_jea0}: - department_id: 'hr_department_rd0' + !record {model: hr.job, id: job_jr_appli, view: False}: + department_id: 'dep_technical' description: 'Position of Junior Application Engineer' expected_employees: 5.0 name: 'JAE' @@ -12,44 +12,10 @@ no_of_recruitment: 5.0 state: open - - !record {model: hr.job, id: hr_job_jea0}: - employee_ids: - - address_home_id: base.res_partner_address_1 - name: Manuel Lehba - department_id: 'hr_department_rd0' - gender: male - parent_id: hr.employee1 -- - !record {model: hr.employee, id: hr_employee001, view: False}: + !record {model: hr.employee, id: employee1, view: False}: address_id: base.main_address company_id: base.main_company - department_id: hr_department_rd0 + department_id: dep_technical name: smith parent_id: hr.employee1 - user_id: base.user_demo -- - !record {model: hr.employee, id: hr_employee_edwin0}: - address_home_id: base.res_partner_address_3000 - address_id: base.res_partner_address_rogerpecker0 - department_id: hr.dep_administration - job_id: hr.job_hr_manager - name: Edwin - parent_id: hr.employee2 - resource_type: user - time_efficiency: 1.0 - user_id: base.user_demo -- - !record {model: hr.employee.category, id: hr_employee_category_fresher0}: - name: Fresher -- - !record {model: hr.employee.category, id: hr_employee_category_juniorlevel0}: - name: Junior Level - parent_id: hr_employee_category_fresher0 -- - - - - - - - + user_id: base.user_demo \ No newline at end of file diff --git a/addons/hr/test/process/open2recruit2close_job.yml b/addons/hr/test/open2recruit2close_job.yml similarity index 70% rename from addons/hr/test/process/open2recruit2close_job.yml rename to addons/hr/test/open2recruit2close_job.yml index aedd2a3d2a1..597db098a29 100644 --- a/addons/hr/test/process/open2recruit2close_job.yml +++ b/addons/hr/test/open2recruit2close_job.yml @@ -4,36 +4,36 @@ I open Job Postion of "Jr. Application Engineer" Profile. - !python {model: hr.job}: | - self.job_open(cr, uid, [ref('hr_job_jea0')]) + self.job_open(cr, uid, [ref('job_jr_appli')]) - I check state of Job Position after opened it. - - !assert {model: hr.job, id: hr_job_jea0}: + !assert {model: hr.job, id: job_jr_appli}: - state == 'open' - Now, Recruitement is started so I start recruitement of Job Postion of "Jr. Application Engineer" Profile. - !python {model: hr.job}: | - self.job_recruitement(cr, uid, [ref('hr_job_jea0')]) + self.job_recruitement(cr, uid, [ref('job_jr_appli')]) - I check state and number of Expected in Recruitment in Job Position of "Jr. Application Engineer" Profile. - - !assert {model: hr.job, id: hr_job_jea0}: + !assert {model: hr.job, id: job_jr_appli}: - state == 'recruit' - no_of_recruitment == 1.0 - I hired new employee for the job position so I set Job Position of "Jr. Application Engineer" Profile to new employee. - !python {model: hr.employee}: | - self.write(cr, uid, [ref('hr_employee001')], {'job_id':ref('hr_job_jea0')}) + self.write(cr, uid, [ref('employee1')], {'job_id':ref('job_jr_appli')}) - Now I don't want to recruit new employee on this position. so I mark it as Old. - !python {model: hr.job}: | - self.job_old(cr, uid, [ref('hr_job_jea0')]) + self.job_old(cr, uid, [ref('job_jr_appli')]) - I check state of Job position and number of Expected in Recruitment after closed Job position. - - !assert {model: hr.job, id: hr_job_jea0}: + !assert {model: hr.job, id: job_jr_appli}: - state == 'old' - - no_of_recruitment == 0 + - no_of_recruitment == 0 \ No newline at end of file From 2ab51f3af900577a214d60a8b336168c1bc246e9 Mon Sep 17 00:00:00 2001 From: "Jagdish Panchal (Open ERP)" Date: Fri, 18 Nov 2011 18:24:30 +0530 Subject: [PATCH 015/117] [IMP] improve test case of recruitment process bzr revid: jap@tinyerp.com-20111118125430-l02i4orxr2z940s3 --- addons/hr_recruitment/__openerp__.py | 4 +- .../test/recruitment_process.yml | 65 ++ addons/hr_recruitment/test/resume.eml | 839 ++++++++++++++++++ .../test/test_hr_recruitment.yml | 139 --- .../wizard/hr_recruitment_phonecall.py | 2 +- 5 files changed, 908 insertions(+), 141 deletions(-) create mode 100644 addons/hr_recruitment/test/recruitment_process.yml create mode 100644 addons/hr_recruitment/test/resume.eml delete mode 100644 addons/hr_recruitment/test/test_hr_recruitment.yml diff --git a/addons/hr_recruitment/__openerp__.py b/addons/hr_recruitment/__openerp__.py index b728609c53d..bff574de94b 100644 --- a/addons/hr_recruitment/__openerp__.py +++ b/addons/hr_recruitment/__openerp__.py @@ -56,7 +56,9 @@ system to store and search in your CV base. 'demo_xml': [ 'hr_recruitment_demo.xml', ], - 'test':['test/test_hr_recruitment.yml'], + 'test':[ + 'test/recruitment_process.yml', + ], 'installable': True, 'active': False, 'certificate' : '001073437025460275621', diff --git a/addons/hr_recruitment/test/recruitment_process.yml b/addons/hr_recruitment/test/recruitment_process.yml new file mode 100644 index 00000000000..64e8ab687a8 --- /dev/null +++ b/addons/hr_recruitment/test/recruitment_process.yml @@ -0,0 +1,65 @@ +- + In Order to test process of Recruitment, +- + Applicant interested in job position. so He send resume by email. +- + !python {model: mail.thread}: | + import addons + request_file = open(addons.get_module_resource('hr_recruitment','test', 'resume.eml'),'rb') + request_message = request_file.read() + self.message_process(cr, uid, 'hr.applicant', request_message) +- + After getting the mail, I check details of new applicant. +- + !python {model: hr.applicant}: | + applicant_ids = self.search(cr, uid, [('email_from','=', 'Mr. Richard Anderson ')]) + assert applicant_ids, "Applicant is not created after getting the mail" + applicant = self.browse(cr, uid, applicant_ids[0], context=context) + assert applicant.name == "Application for the post of Jr.application Programmer", "Subject does not match" + assert applicant.state == "draft" +- + I assign the Job position to the applicant +- + !python {model: hr.applicant}: | + self.write(cr, uid, [ref('hr_case_programmer')], {'job_id':ref('hr.job_jr_appli')}) +- + I open applicant for the Recruitment +- + + !python {model: hr.applicant}: | + self.case_open(cr, uid, [ref("hr_case_programmer")]) +- + I start communication with applicant, first schedule phonecall. +- + !python {model: hr.recruitment.job2phonecall}: | + self.make_phonecall(cr, uid, [ref('hr_case_programmer')]) +- + I schedule meeting with applicant for interview. +- + !python {model: hr.applicant}: | + self.action_makeMeeting(cr, uid, [ref('hr_case_programmer')]) +- + Applicant fillup the answer of the interview quetion. +- + !python {model: survey.question.wiz}: | + ctx = context.copy() + ctx.update({'active_model': 'hr.applicant', 'active_id': ref("hr_case_programmer"), 'active_ids': [ref("hr_case_programmer")], 'survey_id': ref("survey_job_0")}) + self.fields_view_get(cr, uid, ref("survey.view_survey_question_message"),"form", context=ctx) + vals = self.default_get(cr, uid , [], context=ctx) + self.create(cr, uid, vals, context=ctx) + self.action_new_page(cr, uid, [ref("survey_job_0")], context=ctx) +- + I print Applicant fill up the interview quetion +- + !python {model: hr.applicant}: | + self.action_print_survey(cr, uid, [ref('hr_case_programmer')]) +- + On a successful meeting with the applicant, I hired employee. +- + !python {model: hr.applicant}: | + self.case_close(cr, uid, [ref('hr_case_programmer')]) +- + I check that applicant is "Hired". +- + !assert {model: hr.applicant, id: hr_case_programmer}: + - state == 'done' \ No newline at end of file diff --git a/addons/hr_recruitment/test/resume.eml b/addons/hr_recruitment/test/resume.eml new file mode 100644 index 00000000000..9529873a49c --- /dev/null +++ b/addons/hr_recruitment/test/resume.eml @@ -0,0 +1,839 @@ +Return-Path: +X-Original-To: hr@mycompany.com +Delivered-To: hr@mycompany.com +Received: by mail1.mycompany.com (Postfix, from userid 10002) + id 7047CBFC94; Fri, 18 Nov 2011 10:28:16 +0100 (CET) +X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail1.mycompany.com +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM, + HTML_MESSAGE autolearn=ham version=3.3.1 +Received: from nm12-vm2.bullet.mail.ne1.yahoo.com (nm12-vm2.bullet.mail.ne1.yahoo.com [98.138.91.88]) + by mail1.mycompany.com (Postfix) with SMTP id 0D04ABF53A + for ; Fri, 18 Nov 2011 10:27:50 +0100 (CET) +Received: from [98.138.90.50] by nm12.bullet.mail.ne1.yahoo.com with NNFMP; 18 Nov 2011 09:26:49 -0000 +Received: from [98.138.226.126] by tm3.bullet.mail.ne1.yahoo.com with NNFMP; 18 Nov 2011 09:26:49 -0000 +Received: from [127.0.0.1] by smtp205.mail.ne1.yahoo.com with NNFMP; 18 Nov 2011 09:26:49 -0000 +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.in; s=s1024; t=1321608409; bh=GGVn24b6ZH8Ojn91evBkrwuNFmAsLAPy4OeUvOqjgig=; h=X-Yahoo-Newman-Id:X-Yahoo-Newman-Property:X-YMail-OSG:X-Yahoo-SMTP:Received:Message-ID:Date:From:User-Agent:MIME-Version:To:Subject:Content-Type; b=DFCOdjskDmdbkzvuxTqFWJOUHsT0nITWiQe5782VeyTrhymhIzNhwzdRq4wfTrzLu03rJhHadZTX0uweNCf0Jpr4OpEQevZa3aVPw44NNmhFeT2tjs9m3kNWyPnz5Nk1Yv8tiTRFSdssPfZAhwz8UXLCBFowa8DRnY2ZFIsATRE= +X-Yahoo-Newman-Id: 644435.12111.bm@smtp205.mail.ne1.yahoo.com +X-Yahoo-Newman-Property: ymail-3 +X-YMail-OSG: 09Al2uQVM1n5JcQepgua6wQsww7jiatAHXaSsMjP5Qvk9Ba + c65j0.ETzyjVh0vpjphFK3XqPtX0n17z9cUCfUhUDDXLUmUSFoZ.NjoiJ_mQ + vwd4S7.I4ObFZm5jgA0ML0cfTRAy_0msUfO3NKsh9LgBdUXztbVOwrTGQhzD + nu2v3TskGG9ZtRTiqM_Iad2qmMqveFdqUz5xBnwYYgBuLWRR7EUmU1qyOgss + LL33J2t9EOCUn2Kc9XQbSkPBBR7BYlIatTF.AAxLdsuOW6ovTGO.HM5ap0qo + LLM1_BE.EOvXdW38ZC_hHcrM4xYaYSR7c0WaOQsR8EZeXk_Vhio7HHUrdxZl + 1oZz7YWK9Q04M023JJoM4v6IrThy3BNepluEFFcavkyOnCw-- +X-Yahoo-SMTP: oNtzSBqswBAqJIGYOgyGesyleENrhUEtEgBkQ053 +Received: from [192.168.1.30] (jagdish.n_panchal@180.211.100.2 with plain) + by smtp205.mail.ne1.yahoo.com with SMTP; 18 Nov 2011 01:26:47 -0800 PST +Message-ID: <4EC624C7.6020000@yahoo.in> +Date: Fri, 18 Nov 2011 14:56:31 +0530 +From: Richard Anderson +User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.17) Gecko/20110424 Thunderbird/3.1.10 +MIME-Version: 1.0 +To: hr@mycompany.com +Subject: Application for the post of Jr.application Programmer. +Content-Type: multipart/mixed; + boundary="------------010903010402010104090709" + +This is a multi-part message in MIME format. +--------------010903010402010104090709 +Content-Type: multipart/alternative; + boundary="------------010004020303010906010104" + + +--------------010004020303010906010104 +Content-Type: text/plain; charset=ISO-8859-1; format=flowed +Content-Transfer-Encoding: 7bit + +Hello Sir, + + I am**Richard Anderson completed MCA from Mac Technological +university, i send my resume for the your company job position, i +attached my resume here + +Thank you +Richard Anderson + +--------------010004020303010906010104 +Content-Type: text/html; charset=ISO-8859-1 +Content-Transfer-Encoding: 7bit + + + + + + + + + Hello Sir,
+
+  I am Richard Anderson completed MCA from Mac Technological + university, i send my resume for the your company job position, i + attached my resume here
+
+ Thank you
+ Richard Anderson + + + +--------------010004020303010906010104-- + +--------------010903010402010104090709 +Content-Type: application/msword; + name="resume.doc" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; + filename="resume.doc" + +0M8R4KGxGuEAAAAAAAAAAAAAAAAAAAAAOwADAP7/CQAGAAAAAAAAAAAAAAABAAAASwAAAAAA +AAAAEAAAAgAAAAEAAAD+////AAAAAAAAAAD///////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +///////////////////////////////////9//////////7///9KAAAABQAAAAYAAAAHAAAA +CAAAAAkAAAAKAAAACwAAAAwAAAANAAAADgAAAA8AAAAQAAAAEQAAABIAAAATAAAAFAAAABUA +AAD+////FwAAABgAAAAZAAAAGgAAABsAAAAcAAAAHQAAAB4AAAAfAAAAIAAAACEAAAAiAAAA +IwAAACQAAAAlAAAAJgAAACcAAAAoAAAA/v///yoAAAArAAAALAAAAC0AAAAuAAAALwAAADAA +AAAxAAAAMgAAADMAAAA0AAAANQAAADYAAAA3AAAAOAAAADkAAAA6AAAAOwAAADwAAAA9AAAA +PgAAAD8AAABAAAAAQQAAAEIAAABDAAAARAAAAEUAAABGAAAARwAAAEgAAABJAAAA/v////7/ +//9MAAAATQAAAP7///////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////1IA +bwBvAHQAIABFAG4AdAByAHkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAWAAUA////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAA/v///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////////8AAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP// +/////////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7///8AAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAA////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAA/v///wAAAAAAAAAAAQAAAP7////+////BAAAAAUAAAAGAAAABwAAAP7/ +//8JAAAA/v////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////8BAP7/ +AwoAAP////8GCQIAAAAAAMAAAAAAAABGGAAAAE1pY3Jvc29mdCBXb3JkLURva3VtZW50AAoA +AABNU1dvcmREb2MAEAAAAFdvcmQuRG9jdW1lbnQuOAD0ObJxAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAEAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD+/wAAAQACAAAAAAAAAAAAAAAAAAAAAAABAAAA +4IWf8vlPaBCrkQgAKyez2TAAAADsAAAACgAAAAEAAABYAAAAAgAAAGAAAAAEAAAAeAAAAAcA +AACUAAAACAAAAKQAAAAJAAAAsAAAAAoAAAC8AAAACwAAAMgAAAAMAAAA1AAAAA0AAADgAAAA +AgAAAOn9AAAeAAAAEAAAAENhbmRpZGF0ZXMgTmFtZQAeAAAAFAAAAHNhZ2FyIHAgc3VyeWF3 +YW5zaGkAHgAAAAcAAABOb3JtYWwAAB4AAAAEAAAAc2FpAB4AAAAEAAAAMTY5AEAAAAAAyPid +CgAAAEAAAAAAAAAAAAAAAEAAAAAAnpj/jovLAUAAAAAA1LJ/lhzMAQAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAABIAZwAKAAEAWwAPAAIAAAAAAAAAYAAAEPH/AgBgAAAA +BgBOAG8AcgBtAGEAbAAAABEAAAADJABhJAAxJAEqJAFBJAAALwBCKgBPSgAAUUoAAENKFABt +SAkEc0gJBFBKAABuSAQIXkoAAGFKFABfSAEEdEgBBABcAAEQAQACAFwAAAAJAEgAZQBhAGQA +aQBuAGcAIAAxAAAAJwABAAMkA2EkAw3GBQABOAQAXoQAAF2EoAVghAAAE6RkABSkZAAGJAEA +DwBPSgIAUUoCAENKEgA1CAEAPgACEAEAAgA+AAAACQBIAGUAYQBkAGkAbgBnACAAMgAAAA0A +AgATpGQAFKRkAAYkAQAMAE9KAgBRSgIAQ0oSADoAAxABAAIAOgAAAAkASABlAGEAZABpAG4A +ZwAgADMAAAAFAAMABiQBAA8AT0oCAFFKAgBDShIANQgBAFYABBABAAIAVgAAAAkASABlAGEA +ZABpAG4AZwAgADQAAAAfAAQAEmRoAQEADcYFAAFoAQBehGgBXYQAAGCEmP4GJAEAEgBPSgIA +UUoCAENKEgA1CAFcCAEyAAUQAQBiBTIAAAAJAEgAZQBhAGQAaQBuAGcAIAA1AAAACgAFABOk +ZAAUpGQAAwA1CAEAUAAGEAEAAgBQAAAACQBIAGUAYQBkAGkAbgBnACAANgAAABkABgANxgUA +ATgEAF6EAABdhKAFYIQAAAYkAQASAE9KAgBRSgIAQ0oSAD4qAVwIAWAABxABAAIAYAAAAAkA +SABlAGEAZABpAG4AZwAgADcAAAAwAAcAQCYGCiYGC0YBAAomBgtGAQAxJAANxgUAARwBADck +AF6EHAFdhAAAYITk/gYkAQwAT0oCAFFKAgBDShIASAAIEAEAAgBIAAAACQBIAGUAYQBkAGkA +bgBnACAAOAAAABcACAAxJAA3JABehBwBXYQAAGCE5P4GJAEADABPSgIAUUoCAENKEgAAAEIA +QUDy/6EAQgAAABkAQQBiAHMAYQB0AHoALQBTAHQAYQBuAGQAYQByAGQAcwBjAGgAcgBpAGYA +dABhAHIAdAAAAAAAAAAAAAAAAABCAP4f8v/xAEIAAAAZAEEAYgBzAGEAdAB6AC0AUwB0AGEA +bgBkAGEAcgBkAHMAYwBoAHIAaQBmAHQAYQByAHQAAAAAAEgA/h/y/wEBSAAAABwAVwBXAC0A +QQBiAHMAYQB0AHoALQBTAHQAYQBuAGQAYQByAGQAcwBjAGgAcgBpAGYAdABhAHIAdAAAAAAA +SgD+H/L/EQFKAAAAHQBXAFcALQBBAGIAcwBhAHQAegAtAFMAdABhAG4AZABhAHIAZABzAGMA +aAByAGkAZgB0AGEAcgB0ADEAAAAAAEwA/h/y/yEBTAAAAB4AVwBXAC0AQQBiAHMAYQB0AHoA +LQBTAHQAYQBuAGQAYQByAGQAcwBjAGgAcgBpAGYAdABhAHIAdAAxADEAAAAAAE4A/h/y/zEB +TgAAAB8AVwBXAC0AQQBiAHMAYQB0AHoALQBTAHQAYQBuAGQAYQByAGQAcwBjAGgAcgBpAGYA +dABhAHIAdAAxADEAMQAAAAAAUAD+H/L/QQFQAAAAIABXAFcALQBBAGIAcwBhAHQAegAtAFMA +dABhAG4AZABhAHIAZABzAGMAaAByAGkAZgB0AGEAcgB0ADEAMQAxADEAAAAAAFIA/h/y/1EB +UgAAACEAVwBXAC0AQQBiAHMAYQB0AHoALQBTAHQAYQBuAGQAYQByAGQAcwBjAGgAcgBpAGYA +dABhAHIAdAAxADEAMQAxADEAAAAAAFQA/h/y/2EBVAAAACIAVwBXAC0AQQBiAHMAYQB0AHoA +LQBTAHQAYQBuAGQAYQByAGQAcwBjAGgAcgBpAGYAdABhAHIAdAAxADEAMQAxADEAMQAAAAAA +KgD+H/L/cQEqAAAACQBXAFcAOABOAHUAbQAyAHoAMAAAAAgAT0oBAFFKAQAuAP4f8v+BAS4A +AAAJAFcAVwA4AE4AdQBtADIAegAxAAAADABPSgcAUUoHAF5KBwAqAP4f8v+RASoAAAAJAFcA +VwA4AE4AdQBtADIAegAzAAAACABPSgEAUUoBADYA/h/y/6EBNgAAAAkAVwBXADgATgB1AG0A +MwB6ADAAAAATAE9KAABRSgAANQgBUEoAAF5KAAAAKgD+H/L/sQEqAAAACQBXAFcAOABOAHUA +bQAzAHoAMQAAAAgAT0oHAFFKBwAqAP4f8v/BASoAAAAJAFcAVwA4AE4AdQBtADMAegAyAAAA +CABPSggAUUoIACoA/h/y/9EBKgAAAAkAVwBXADgATgB1AG0ANAB6ADAAAAAIAE9KCABRSggA +LgD+H/L/4QEuAAAACQBXAFcAOABOAHUAbQA0AHoAMQAAAAwAT0oHAFFKBwBeSgcAKgD+H/L/ +8QEqAAAACQBXAFcAOABOAHUAbQA0AHoAMwAAAAgAT0oBAFFKAQA8AP4f8v8BAjwAAAAWAEQA +ZQBmAGEAdQBsAHQAIABQAGEAcgBhAGcAcgBhAHAAaAAgAEYAbwBuAHQAAAAAACoA/h/y/xEC +KgAAAAkAVwBXADgATgB1AG0AMQB6ADAAAAAIAE9KAABRSgAAKgD+H/L/IQIqAAAACQBXAFcA +OABOAHUAbQAzAHoAMwAAAAgAT0oBAFFKAQAqAP4f8v8xAioAAAAJAFcAVwA4AE4AdQBtADUA +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 +NRaQAQIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFMAeQBtAGIAbwBsAAAA +MyaQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEAcgBpAGEAbAAAAEcW +kAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUAGkAbQBlAHMAIABOAGUA +dwAgAFIAbwBtAGEAbgAAADUmkAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AABUAGEAaABvAG0AYQAAAD8WkAECAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AABXAGkAbgBnAGQAaQBuAGcAcwAgADIAAAA3JpABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAVgBlAHIAZABhAG4AYQAAAD80kAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAABDAG8AdQByAGkAZQByACAATgBlAHcAAAA7BpABAgAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVwBpAG4AZwBkAGkAbgBnAHMAAABTJpABgBAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATABpAGIAZQByAGEAdABpAG8AbgAgAFMA +YQBuAHMAAABBAHIAaQBhAGwAAAA/BpABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAARABlAGoAYQBWAHUAIABTAGEAbgBzAAAASSaQAYAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAEEAcgBpAGEAbAAgAFUAbgBpAGMAbwBkAGUAIABNAFMAAABCAAQA +AQiNGAAA0AIAAGgBAAAAAHPC62bU3fWmAAAAAAEAAAAAAMkAAAASBgAAAgA/AAAABACDkD8A +AADJAAAAEgYAAAIAPwAAAD8AAAAAAAAAJwMA8BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABIwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAIAAAAAAAAAAAAAAAAAAPAQAN/f//0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +gAAAAAAAAAAAAAAA//8SAAAAAAAAAA8AQwBhAG4AZABpAGQAYQB0AGUAcwAgAE4AYQBtAGUA +AAAAAAAAEwBzAGEAZwBhAHIAIABwACAAcwB1AHIAeQBhAHcAYQBuAHMAaABpAAMAcwBhAGkA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAJ4EAABEAGQA7gAjAQAAAAAAAAAAAAAAAAAAAACHAKUA6APoAwAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAADwAE8GYAAACyBArwCAAAAAEEAAAACgAAswAL8EIAAACBAAAA +AACCAAAAAACDAAAAAACEAAAAAAAEQQEAAAAGAQAAAAA/AQAAAACBAf///wCDAQAAAAC/ARAA +EAD/AQAACAAAABDwBAAAAAAAAIBiAAfw5AMAAAYGnRZ3tgAAAAB7OGUgEgIAEAAAwAMAAAEA +AAAAAAAAAAAAAABuHvC4AwAAnRZ3tgAAAAB7OGUgEgIAEP+JUE5HDQoaCgAAAA1JSERSAAAA +CQAAAAsIAwAAAJqHVykAAAMAUExURQAAAPf39/////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////88f9h0AAAADdFJOU///ANfKDUEA +AAABYktHRACIBR1IAAAADGNtUFBKQ21wMDcxMgAAAANIAHO8AAAALklEQVQYV22MQQoAAAjC +rP8/Ol10K8IJiuo7tbChbMtiRIMkMeT7m9B4e5RP2B4eJACOUomEagAAAABJRU5ErkJgggAA +ngQAAEQAZADuACMBAAAAAAAAAAAAAAAAAAAAAIcApQDoA+gDAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAPAATwZgAAALIECvAIAAAAAQQAAAAKAACzAAvwQgAAAIEAAAAAAIIA +AAAAAIMAAAAAAIQAAAAAAARBAQAAAAYBAAAAAD8BAAAAAIEB////AIMBAAAAAL8BEAAQAP8B +AAAIAAAAEPAEAAAAAAAAgGIAB/DkAwAABgadFne2AAAAAHs4ZSASAgAQAADAAwAAAQAAAAAA +AAAAAAAAAG4e8LgDAACdFne2AAAAAHs4ZSASAgAQ/4lQTkcNChoKAAAADUlIRFIAAAAJAAAA +CwgDAAAAmodXKQAAAwBQTFRFAAAA9/f3//////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +////////////////////////////////////////zx/2HQAAAAN0Uk5T//8A18oNQQAAAAFi +S0dEAIgFHUgAAAAMY21QUEpDbXAwNzEyAAAAA0gAc7wAAAAuSURBVBhXbYxBCgAACMKs/z86 +XXQrwgmK6ju1sKFsy2JEgyQx5Pub0Hh7lE/YHh4kAI5SiYRqAAAAAElFTkSuQmCCAACeBAAA +RABkAO4AIwEAAAAAAAAAAAAAAAAAAAAAhwClAOgD6AMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAA8ABPBmAAAAsgQK8AgAAAABBAAAAAoAALMAC/BCAAAAgQAAAAAAggAAAAAA +gwAAAAAAhAAAAAAABEEBAAAABgEAAAAAPwEAAAAAgQH///8AgwEAAAAAvwEQABAA/wEAAAgA +AAAQ8AQAAAAAAACAYgAH8OQDAAAGBp0Wd7YAAAAAezhlIBICABAAAMADAAABAAAAAAAAAAAA +AAAAbh7wuAMAAJ0Wd7YAAAAAezhlIBICABD/iVBORw0KGgoAAAANSUhEUgAAAAkAAAALCAMA +AACah1cpAAADAFBMVEUAAAD39/f///////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +///////////////////////////////////PH/YdAAAAA3RSTlP//wDXyg1BAAAAAWJLR0QA +iAUdSAAAAAxjbVBQSkNtcDA3MTIAAAADSABzvAAAAC5JREFUGFdtjEEKAAAIwqz/PzpddCvC +CYrqO7WwoWzLYkSDJDHk+5vQeHuUT9geHiQAjlKJhGoAAAAASUVORK5CYIIAAJ4EAABEAGQA +7gAjAQAAAAAAAAAAAAAAAAAAAACHAKUA6APoAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAADwAE8GYAAACyBArwCAAAAAEEAAAACgAAswAL8EIAAACBAAAAAACCAAAAAACDAAAA +AACEAAAAAAAEQQEAAAAGAQAAAAA/AQAAAACBAf///wCDAQAAAAC/ARAAEAD/AQAACAAAABDw +BAAAAAAAAIBiAAfw5AMAAAYGnRZ3tgAAAAB7OGUgEgIAEAAAwAMAAAEAAAAAAAAAAAAAAABu +HvC4AwAAnRZ3tgAAAAB7OGUgEgIAEP+JUE5HDQoaCgAAAA1JSERSAAAACQAAAAsIAwAAAJqH +VykAAAMAUExURQAAAPf39/////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +/////////////////////////////88f9h0AAAADdFJOU///ANfKDUEAAAABYktHRACIBR1I +AAAADGNtUFBKQ21wMDcxMgAAAANIAHO8AAAALklEQVQYV22MQQoAAAjCrP8/Ol10K8IJiuo7 +tbChbMtiRIMkMeT7m9B4e5RP2B4eJACOUomEagAAAABJRU5ErkJgggAAngQAAEQAZADuACMB +AAAAAAAAAAAAAAAAAAAAAIcApQDoA+gDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAPAATwZgAAALIECvAIAAAAAQQAAAAKAACzAAvwQgAAAIEAAAAAAIIAAAAAAIMAAAAAAIQA +AAAAAARBAQAAAAYBAAAAAD8BAAAAAIEB////AIMBAAAAAL8BEAAQAP8BAAAIAAAAEPAEAAAA +AAAAgGIAB/DkAwAABgadFne2AAAAAHs4ZSASAgAQAADAAwAAAQAAAAAAAAAAAAAAAG4e8LgD +AACdFne2AAAAAHs4ZSASAgAQ/4lQTkcNChoKAAAADUlIRFIAAAAJAAAACwgDAAAAmodXKQAA +AwBQTFRFAAAA9/f3//////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +////////////////////////zx/2HQAAAAN0Uk5T//8A18oNQQAAAAFiS0dEAIgFHUgAAAAM +Y21QUEpDbXAwNzEyAAAAA0gAc7wAAAAuSURBVBhXbYxBCgAACMKs/z86XXQrwgmK6ju1sKFs +y2JEgyQx5Pub0Hh7lE/YHh4kAI5SiYRqAAAAAElFTkSuQmCCAACeBAAARABkAO4AIwEAAAAA +AAAAAAAAAAAAAAAAhwClAOgD6AMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8A +BPBmAAAAsgQK8AgAAAABBAAAAAoAALMAC/BCAAAAgQAAAAAAggAAAAAAgwAAAAAAhAAAAAAA +BEEBAAAABgEAAAAAPwEAAAAAgQH///8AgwEAAAAAvwEQABAA/wEAAAgAAAAQ8AQAAAAAAACA +YgAH8OQDAAAGBp0Wd7YAAAAAezhlIBICABAAAMADAAABAAAAAAAAAAAAAAAAbh7wuAMAAJ0W +d7YAAAAAezhlIBICABD/iVBORw0KGgoAAAANSUhEUgAAAAkAAAALCAMAAACah1cpAAADAFBM +VEUAAAD39/f///////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +///////////////////PH/YdAAAAA3RSTlP//wDXyg1BAAAAAWJLR0QAiAUdSAAAAAxjbVBQ +SkNtcDA3MTIAAAADSABzvAAAAC5JREFUGFdtjEEKAAAIwqz/PzpddCvCCYrqO7WwoWzLYkSD +JDHk+5vQeHuUT9geHiQAjlKJhGoAAAAASUVORK5CYIIAAJ4EAABEAGQA7gAjAQAAAAAAAAAA +AAAAAAAAAACHAKUA6APoAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwAE8GYA +AACyBArwCAAAAAEEAAAACgAAswAL8EIAAACBAAAAAACCAAAAAACDAAAAAACEAAAAAAAEQQEA +AAAGAQAAAAA/AQAAAACBAf///wCDAQAAAAC/ARAAEAD/AQAACAAAABDwBAAAAAAAAIBiAAfw +5AMAAAYGnRZ3tgAAAAB7OGUgEgIAEAAAwAMAAAEAAAAAAAAAAAAAAABuHvC4AwAAnRZ3tgAA +AAB7OGUgEgIAEP+JUE5HDQoaCgAAAA1JSERSAAAACQAAAAsIAwAAAJqHVykAAAMAUExURQAA +APf39/////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +/////////////88f9h0AAAADdFJOU///ANfKDUEAAAABYktHRACIBR1IAAAADGNtUFBKQ21w +MDcxMgAAAANIAHO8AAAALklEQVQYV22MQQoAAAjCrP8/Ol10K8IJiuo7tbChbMtiRIMkMeT7 +m9B4e5RP2B4eJACOUomEagAAAABJRU5ErkJgggAAngQAAEQAZADuACMBAAAAAAAAAAAAAAAA +AAAAAIcApQDoA+gDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAATwZgAAALIE +CvAIAAAAAQQAAAAKAACzAAvwQgAAAIEAAAAAAIIAAAAAAIMAAAAAAIQAAAAAAARBAQAAAAYB +AAAAAD8BAAAAAIEB////AIMBAAAAAL8BEAAQAP8BAAAIAAAAEPAEAAAAAAAAgGIAB/DkAwAA +BgadFne2AAAAAHs4ZSASAgAQAADAAwAAAQAAAAAAAAAAAAAAAG4e8LgDAACdFne2AAAAAHs4 +ZSASAgAQ/4lQTkcNChoKAAAADUlIRFIAAAAJAAAACwgDAAAAmodXKQAAAwBQTFRFAAAA9/f3 +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +////////zx/2HQAAAAN0Uk5T//8A18oNQQAAAAFiS0dEAIgFHUgAAAAMY21QUEpDbXAwNzEy +AAAAA0gAc7wAAAAuSURBVBhXbYxBCgAACMKs/z86XXQrwgmK6ju1sKFsy2JEgyQx5Pub0Hh7 +lE/YHh4kAI5SiYRqAAAAAElFTkSuQmCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAA7KUBAU0gCQQAAAgSvwAAAAAAADAAAAAAAAgAAAAVAAAOAENhb2xhbjgw +AAAAAAAAAAAAAAAAAAAAAAAACQQWAJxBAAAAAAAAAAAAAHIFAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAA0BAAAAAAAA//8PAAsAAAAEAAAA//8PAA8AAAARAAAA//8PAAAAAAAAAAAAAAAAAAAA +AACIAAAAAACIFQAAAAAAAIgVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANgV +AAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADsFQAANAAAACAWAAAkAAAA +RBYAAIwAAAAAAAAAAAAAACYdAAAGAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAOUaAAAmAAAACxsAAAwAAAAXGwAACAAAAAMdAAACAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALCAAAGICAACOIgAAdAAAABEd +AAAVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +aRoAAHwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQFgAAmQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAACIFQAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHxsAAB4A +AADjHAAAGAAAAMAVAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+xwAAAgAAAAAAAAAAAAAAAUdAAAMAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAIA2QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAgACAAIAAgACAAIAAgACAAIAAgACAAQwBVAFIAUgBJAEMAVQBMAFUATQAgAFYA +SQBUAEEARQANAAgADQBSAGkAYwBoAGEAcgBkACAAQQBuAGQAZQByAHMAbwBuACAACwAxADIA +MwA0ACwAIABXAGUAcwB0ACAANgA3ACAAUwB0AHIAZQBlAHQALAAgAAsAQwBhAHIAbABpAHMA +bABlACwAIABNAEEAIAAwADEANwA0ADEALAAgAAsAKAAxADIAMwApAC0ANAA1ADYAIAA3ADgA +OQAwAC4ADQAIAAsAAQAgAEMAYQByAGUAZQByACAATwBiAGoAZQBjAHQAaQB2AGUADQANAEQA +ZQBzAGkAcgBlACAAYQAgAGMAaABhAGwAbABlAG4AZwBpAG4AZwAgAHAAbwBzAGkAdABpAG8A +bgAgAGkAbgAgAHQAaABlACAAYQByAGUAYQAgAG8AZgAgAFMAbwBmAHQAdwBhAHIAZQAgAGQA +ZQB2AGUAbABvAHAAbQBlAG4AdAAsACAAdwBoAGkAYwBoACAAdwBpAGwAbAAgAHUAdABpAGwA +aQB6AGUAIABtAHkAIABpAG4AdABlAHIAZABpAHMAYwBpAHAAbABpAG4AYQByAHkALAAgAHQA +ZQBjAGgAbgBpAGMAYQBsACwAIABhAG4AZAAgAHMAbwBmAHQAdwBhAHIAZQAgAGQAZQB2AGUA +bABvAHAAbQBlAG4AdAAgAGwAaQBmAGUAIABjAHkAYwBsAGUAIABzAGsAaQBsAGwAcwAgAGkA +bgAgAGEAIABwAHIAbwBkAHUAYwB0AGkAdgBlACwAIABlAG4AdABoAHUAcwBpAGEAcwB0AGkA +YwAgAGEAbgBkACAAaQBuACAAYQAgAHQAZQBhAG0ALQBvAHIAaQBlAG4AdABlAGQAIABlAG4A +dgBpAHIAbwBuAG0AZQBuAHQALgANAA0AAQAgAEUAZAB1AGMAYQB0AGkAbwBuAGEAbAAgAFMA +dQBtAG0AYQByAHkADQBQ8CAAQwBvAG0AcABsAGUAdABlAGQAIABNAGEAcwB0AGUAcgBzACAA +aQBuACAAQwBvAG0AcAB1AHQAZQByACAAYQBwAHAAbABpAGMAYQB0AGkAbwBuACAAKABNAC4A +QwAuAEEAKQAgAHcAaQB0AGgAIAA2ADMALgA3ADEAJQAgAA0AAQAgAFQAZQBjAGgAbgBpAGMA +YQBsACAASwBuAG8AdwBsAGUAZABnAGUAIABTAHUAbQBtAGEAcgB5AA0ACAANAAEAIAAgAEQA +ZQB0AGEAaQBsAGUAZAAgAEUAZAB1AGMAYQB0AGkAbwBuAGEAbAAgAEEAYwBhAGQAZQBtAGkA +YwAgAEMAcgBlAGQAZQBuAHQAaQBhAGwAcwANAEUAeABhAG0AaQBuAGEAdABpAG8AbgAHAEIA +bwBhAHIAZAAvAFUAbgBpAHYAZQByAHMAaQB0AHkABwBQAGEAcwBzAGkAbgBnACAAWQBlAGEA +cgAHAFAAZQByAGMAZQBuAHQAYQBnAGUABwAHAAgATQAuAEMALgBBACAABwAHACAAIAAgACAA +IAAgACAAIAAgACAAUwBlAG0AZQBzAHQAZQByACAAVgBJAAcAQwBhAHIAbABpAHMAbABlACAA +VQBuAGkAdgBlAHIAcwBpAHQAeQAHADIAMAAxADEABwA2ADMALgA3ADEABwAHACAAIAAgACAA +IAAgACAAIAAgACAAUwBlAG0AZQBzAHQAZQByACAAVgAHAEMAYQByAGwAaQBzAGwAZQAgAFUA +bgBpAHYAZQByAHMAaQB0AHkABwAyADAAMQAwAAcANgA3AC4AMQA3AAcABwAgACAAIAAgACAA +IAAgACAAIAAgAFMAZQBtAGUAcwB0AGUAcgAgAEkAVgAHAEMAYQByAGwAaQBzAGwAZQAgAFUA +bgBpAHYAZQByAHMAaQB0AHkABwAyADAAMQAwAAcANgAyAC4AOAAwAAcABwAgACAAIAAgACAA +IAAgACAAIAAgAFMAZQBtAGUAcwB0AGUAcgAgAEkASQBJAAcAQwBhAHIAbABpAHMAbABlACAA +VQBuAGkAdgBlAHIAcwBpAHQAeQAHADIAMAAxADAABwA2ADIALgAyADUABwAHACAAIAAgACAA +IAAgACAAIAAgACAAUwBlAG0AZQBzAHQAZQByACAASQBJAAcAQwBhAHIAbABpAHMAbABlACAA +VQBuAGkAdgBlAHIAcwBpAHQAeQAHADIAMAAwADkABwA2ADUALgA3ADUABwAHACAAIAAgACAA +IAAgACAAIAAgACAAUwBlAG0AZQBzAHQAZQByACAASQAHAEMAYQByAGwAaQBzAGwAZQAgAFUA +bgBpAHYAZQByAHMAaQB0AHkABwAyADAAMAA5AAcANgAzAC4AMwAzAAcABwAHAAcABwAHAAcA +BwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcAAQAgAFMAdQBiAGoAZQBjAHQAIAAgAEYA +YQBtAGkAbABpAGEAcgBpAHQAeQA6AA0AUPAgAEQAYQB0AGEAYgBhAHMAZQAgAE0AYQBuAGEA +ZwBlAG0AZQBuAHQAIABDAG8AbgBjAGUAcAB0AHMADQBQ8CAATwBiAGoAZQBjAHQAIABPAHIA +aQBlAG4AdABlAGQAIABQAHIAbwBnAHIAYQBtAG0AaQBuAGcAIABDAG8AbgBjAGUAcAB0AA0A +UPAgAFMAeQBzAHQAZQBtACAAQQBuAGEAbAB5AHMAaQBzACAAYQBuAGQAIABEAGUAcwBpAGcA +bgANAFDwIABzAG8AZgB0AHcAYQByAGUAIABFAG4AZwBpAG4AZQBlAHIAaQBuAGcAIAANAFDw +IABPAHAAZQByAGEAdABpAG4AZwAgAFMAeQBzAHQAZQBtACAAQwBvAG4AYwBlAHAAdAANAFDw +IABVAG4AaQB4ACAAUwBoAGUAbABsACAAUAByAG8AZwByAGEAbQBtAGkAbgBnAA0AAQAgAEEA +cgBlAGEAIABvAGYAIABJAG4AdABlAHIAZQBzAHQAOgANAFDwIABTAG8AZgB0AHcAYQByAGUA +IABkAGUAdgBlAGwAbwBwAG0AZQBuAHQAIAAgAHUAcwBpAG4AZwAgAEoAYQB2AGEALwAuAE4A +ZQB0ACAAdABlAGMAaABuAG8AbABvAGcAaQBlAHMADQBQ8CAATABlAGEAcgBuAGkAbgBnACAA +bgBlAHcAIAB0AGUAYwBoAG4AbwBsAG8AZwBpAGUAcwAuAA0AAQAgAFAAZQByAHMAbwBuAGEA +bAAgAEQAZQB0AGEAaQBsAHMADQBOAGEAbQBlADoAIAAgAAkACQBSAGkAYwBoAGEAcgBkACAA +QQBuAGQAZQByAHMAbwBuAA0AQwB1AHIAcgBlAG4AdAAgAEEAZABkAHIAZQBzAHMACQAxADIA +MwA0ACwAIABXAGUAcwB0ACAANgA3ACAAUwB0AHIAZQBlAHQALAAgAAsAQwBhAHIAbABpAHMA +bABlACwAIABNAEEAIAAwADEANwA0ADEALAAgAAsAKAAxADIAMwApAC0ANAA1ADYAIAA3ADgA +OQAwAC4ADQBEAGEAdABlACAAbwBmACAAQgBpAHIAdABoADoAIAAJADEAcwB0ACAAagB1AG4A +ZQANAEcAZQBuAGQAZQByADoAIAAJAAkATQBhAGwAZQAJAA0ADQABAA0ATABhAG4AZwB1AGEA +ZwBlAHMAIABLAG4AbwB3AG4AIAAHAEMALAAgAEMAKwArACwASgBBAFYAQQAsACAALgBOAEUA +VAAgADMALgA1ACwAIABBAFMAUAAuAE4ARQBUACAAMwAuADUALABWAEIAIAAyADAAMAA4ACwA +cAB5AHQAaABvAG4ABwAHAEQAQgBNAFMALwBSAEQAQgBNAFMAIAAHAE8AUgBBAEMATABFACwA +TQBTACAAQQBjAGMAZQBzAHMALAAgAFMAUQBMACwAIABQAG8AcwB0AGcAcgBlAHMAcwAgAFMA +UQBMAAcABwBXAGUAYgAgAFQAZQBjAGgAbgBvAGwAbwBnAHkABwBIAFQATQBMACwASgBBAFYA +QQAgAFMAYwByAGkAcAB0AAcABwBPAHAAZQByAGEAdABpAG4AZwAgAFMAeQBzAHQAZQBtAAcA +VwBpAG4AZABvAHcAcwAgACgAOQA4AC8AMgAwADAANwAvAFgAUAAgAC8AVgBJAFMAVABBACwA +NwApACwAdQBiAHUAbgB0AHUABwAHAE8AdABoAGUAcgAHAE4AZQB0AHcAbwByAGsAIABQAHIA +bwBnAHIAYQBtAG0AaQBuAGcAIABpAG4AIABKAGEAdgBhACwAIABVAG4AaQB4ACAAUwBoAGUA +bABsACAAUAByAG8AZwByAGEAbQBtAGkAbgBnAAcABwAgAA0ADQANAA0AAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAWCAAAOAgAADoIAAA8CAAAXAgAANgI +AADaCAAA3AgAAN4IAADgCAAAAgkAAAQJAADMCgAAzgoAANAKAADSCgAA+goAAPwKAAD+CgAA +EgsAAGALAABiCwAAbAsAAHwLAAB+CwAAgAsAALgLAAC6CwAAvAsAAL4LAADACwAAwgsAAPn5 +9Ovh2PTMv7bMANisn7aVjoeHf3h4eGu2YfQAVLZhAAAAABlVCAEDauANAAAwSlAAXkoEAE9K +BABRSgQAEj4qATUIAV5KBABPSgQAUUoEAAAZVQgBA2pACQAAMEpQAF5KBABPSgQAUUoEAAxe +SgQAT0oEAFFKBAAADzUIAV5KBABPSgQAUUoEAAxDShIAT0oCAFFKAgAADENKEgBPSgUAUUoF +AAATMEpQAD4qAV5KBABPSgQAUUoEABlVCAEDaqAEAAAwSlAAXkoEAE9KBABRSgQAEkNKEgA+ +KgE1CAFPSgIAUUoCAAAQMEpQAF5KBABPSgQAUUoEAAAZVQgBA2oAAAAAMEpQAF5KBABPSgQA +UUoEABcwSlAAQ0oUAD4qAV5KBABPSgQAUUoEABBDShQAXkoEAE9KBABRSgQAABNDShQANQgB +XkoEAE9KBABRSgQAEENKFABtSAAEc0gABG5IAAQACQNqAAAAAFUIAQxDShYAT0oCAFFKAgAg +wgsAABYMAAAuDAAAUAwAAGoMAACADAAAggwAAIQMAACGDAAAkgwAAKgMAADADAAA0AwAAOgM +AADyDAAA/gwAABQNAAAqDQAAOg0AAFINAABcDQAAaA0AAH4NAACWDQAApg0AAL4NAADIDQAA +1A0AAOoNAAAEDgAAFA4AACwOAAA2DgAAQg4AAFgOAABwDgAAgA4AAJgOAACiDgAArg4AAMQO +AADaDgAA6g4AAAIPAAAMDwAAGA8AABwPAAAeDwAAIA8AACIPAAAmDwAAKA8AACoPAAAsDwAA +MA8AADIPAAA0DwAANg8AADoPAAA8DwAAPg8AAEAPAABCDwAARA8AAEYPAAD27Ozs7ADn39/Y +2M/Y2NjY2M/Y2NjY2M/Y2MnY2M/Y2MnY2M/Y2MnY2M/Y2Mnf2NjYvdjY2N/Y2Njf2NjYALCn +AAAAAAAAAAAAABAwSlAAXkoEAE9KBABRSgQAABlVCAEDaoASAAAwSlAAXkoEAE9KBABRSgQA +FkNKEgA1CAFhShIAXAgBT0oGAFFKBgAAC1wIAU9KBgBRSgYAEENKFABeSgQAT0oEAFFKBAAA +DF5KBABPSgQAUUoEAAAPNQgBXkoEAE9KBABRSgQACQNqAAAAAFUIARNDShIANQgBXkoEAE9K +BABRSgQAEj4qATUIAV5KBABPSgQAUUoEAEBGDwAAbg8AAHIPAAB0DwAAdg8AALAPAACyDwAA +tA8AAPwPAAD+DwAAABAAADYQAAA4EAAAOhAAAGYQAABoEAAAahAAAJwQAACeEAAAoBAAAM4Q +AADQEAAA0hAAAPYQAAD4EAAA+hAAAGARAABiEQAAZBEAAJoRAACcEQAAnhEAAMARAADMEQAA +0hEAAPQRAAASEgAAFBIAAIwSAACqEgAArhIAALISAAC+EgAA0hIAANoSAADeEgAA4BIAAPLm +4dra4dra4dra4dra4dra4drazcS64dra4drarcS6pdqbpZaNpdqF2qXapQAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9IKgFeSgQAT0oEAFFKBAAQQ0oUAF5KBABPSgQAUUoE +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 +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQAAFiQBSWYB +AAAAEmRoAQEAAyQBYSQBRyQAAA0AABYkAUlmAQAAABJkaAEBAAMkAWEkAUckAAAKAAAWJAFJ +ZgEAAAASZGgBAQBHJAAACgAAFiQBSWYBAAAAEmRoAQEARyQAADoAABYkARckAUlmAQAAAAjW +GgABYv/CJIAAAAAEAQEABAEBAAQBAQAEAQEACdYCAAAS1goAAAD/AAAA/wAAcNYKAAAA/wAA +AP8AADTWBgABAQMAADTWBgABAgNsADTWBgABBAMAADTWBgABCANsAAM0AGY0AAAF/gwAAAAN +AAAqDQAAUg0AAFwNAABoDQAAggAAAAAAAAAAAAAAAHcAAAAAAAAAAAAAAABsAAAAAAAAAAAA +AAAAXgAAAAAAAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANAAAWJAFJ +ZgEAAAASZGgBAQADJAFhJAFHJAAADQAAFiQBSWYBAAAAEmRoAQEAAyQBYSQBRyQAAAoAABYk +AUlmAQAAABJkaAEBAEckAAAKAAAWJAFJZgEAAAASZGgBAQBHJAAAfAAAFiQBFyQBSWYBAAAA +CNZcAARi/8IL0hlyH8IkgAAAAAQBAQAEAQEABAEBAAAAAACAAAAABAEBAAQBAQAEAQEAAAAA +AIAAAAAEAQEABAEBAAQBAQAAAAAAgAAAAAQBAQAEAQEABAEBAAQBAQAJ1ggAAAAAAAAAABLW +KAAAAP8AAAD/AAAAAAD/AAAA/wAAAAAA/wAAAP8AAAAAAP8AAAD/AABw1igAAAD/AAAA/wAA +AAAA/wAAAP8AAAAAAP8AAAD/AAAAAAD/AAAA/wAANNYGAAEBAwAANNYGAAECA2wANNYGAAEE +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 +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSAG8AbwB0ACAARQBuAHQAcgB5AAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFgAFAP////////// +AQAAAAYJAgAAAAAAwAAAAAAAAEYAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAACAAgAAAAAAAAEA +QwBvAG0AcABPAGIAagAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAASAAIAAgAAAAUAAAD/////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAGoAAAAAAAAAAQBPAGwAZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAgD/////AwAAAP////8AAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAFAAAAAAAAAAxAFQAYQBiAGwAZQAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgACAAQA +AAD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAACIwAA +AAAAAEQAYQB0AGEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAKAAIA////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAFgAAAP4kAAAAAAAABQBTAHUAbQBtAGEAcgB5AEkAbgBmAG8AcgBtAGEA +dABpAG8AbgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAgAGAAAACAAAAP////8AAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAHAEAAAAAAABXAG8AcgBkAEQA +bwBjAHUAbQBlAG4AdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +GgACAAcAAAD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACkA +AACcQQAAAAAAAE8AYgBqAGUAYwB0AFAAbwBvAGwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAWAAEA////////////////AAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAA/v///wAAAAAAAAAABQBEAG8AYwB1AG0AZQBuAHQAUwB1AG0A +bQBhAHIAeQBJAG4AZgBvAHIAbQBhAHQAaQBvAG4AAAAAAAAAAAAAADgAAgD///////////// +//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAdAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAP///////////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAP7///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////////AAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///// +//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD+////AAAAAAAA +AAA= +--------------010903010402010104090709-- diff --git a/addons/hr_recruitment/test/test_hr_recruitment.yml b/addons/hr_recruitment/test/test_hr_recruitment.yml deleted file mode 100644 index b797353bde2..00000000000 --- a/addons/hr_recruitment/test/test_hr_recruitment.yml +++ /dev/null @@ -1,139 +0,0 @@ -- - In order to test hr_recruitment module for OpenERP, I will create applicants form, Manages job positions and the recruitment process. -- - - I create a department. -- - !record {model: hr.department, id: hr_department_rd0}: - manager_id: base.user_root - name: 'R & D ' - -- - I create new Job Position. -- - !record {model: hr.job, id: hr_job_jea0}: - department_id: 'hr_department_rd0' - description: 'Position of Jr. Application Engineer' - expected_employees: 5 - name: 'JAE ' -- - I create a recruitment stage "Initial Jobs Demand". -- - !record {model: hr.recruitment.stage, id: hr_recrutiment_stage_first0}: - name: 'Initial Jobs Demand' - sequence: 1 -- - I create an applicant. -- - !record {model: hr.applicant, id: hr_applicant_fresher0}: - availability: 0.0 - department_id: hr.dep_it - name: Fresher - partner_address_id: base.res_partner_address_tang - partner_id: base.res_partner_asus - partner_name: Marion Jones - partner_phone: '1111112223' - response: 0.0 - job_id: hr.job_jr_developers - salary_expected: 0.0 - salary_proposed: 0.0 - stage_id: hr_recrutiment_stage_first0 - type_id: hr_recruitment.degree_licenced - -- - I check that applicant is on "draft" state. -- - !assert {model: hr.applicant, id: hr_applicant_fresher0}: - - state == 'draft' - -- - I change the state by click on "In Progress" button. -- - !python {model: hr.applicant}: | - self.case_open(cr, uid, [ref("hr_applicant_fresher0")], {"active_ids": [ref("hr_recruitment.menu_crm_case_categ0_act_job")], - }) -- - I change the stages by clicking on stage next and stage previous buttons. -- - !python {model: hr.applicant}: | - self.stage_next(cr, uid, [ref('hr_applicant_fresher0')], None) - self.stage_previous(cr, uid, [ref('hr_applicant_fresher0')], None) -- - I create a new case category. -- - !record {model: crm.case.categ, id: crm_case_categ_employee0}: - name: 'Employee' - -- - I schedule a phonecall for this applicant by click on "Schedule a Phone Call" button. -- - !record {model: hr.recruitment.job2phonecall, id: hr_recruitment_forinterview0}: - user_id: base.user_root - deadline: !eval time.strftime('%Y-%m-%d 11:51:00') - note: 'For interview.' - category_id: 'crm_case_categ_employee0' - -- - I click on "Schedule phonecall" button of this wizard. -- - !python {model: hr.recruitment.job2phonecall}: | - self.make_phonecall(cr, uid, [ref('hr_recruitment_forinterview0')], {'active_ids': [ref('hr_applicant_fresher0')]}) - -- - I schedule meeting for interview of this applicant by click on "Schedule Meeting" button. -- - !python {model: hr.applicant}: | - self.action_makeMeeting(cr, uid, [ref('hr_recruitment_forinterview0')]) -- - I create an entry for the meeting with the applicant. -- - !record {model: crm.meeting, id: crm_meeting_fresher0}: - alarm_id: base_calendar.alarm1 - count: 0.0 - date: !eval "(datetime.now() + timedelta(1)).strftime('%Y-%m-%d 00:00:00')" - date_deadline: !eval "(datetime.now() + timedelta(1)).strftime('%Y-%m-%d 08:00:00')" - day: 0.0 - duration: 8.0 - name: Fresher - opportunity_id: crm.crm_case_construstazunits0 - partner_address_id: base.res_partner_address_tang - partner_id: base.res_partner_asus - recurrent_uid: 0.0 - rrule_type: none - state: open - user_id: base.user_root -- - I print the survery filled up by the applicant. -- - !python {model: hr.applicant}: | - self.action_print_survey(cr, uid, [ref('hr_applicant_fresher0')], None) -- - I assign the position to the applicant and its relevant department. -- - !python {model: hr.applicant}: | - res = self.onchange_job(cr, uid, [ref('hr_applicant_fresher0')], ref('hr.job_jr_developers'), None) - values = dict([('job_id', ref('hr.job_jr_developers'))] + res['value'].items()) - res1 = self.onchange_department_id(cr, uid, [ref('hr_applicant_fresher0')], ref('hr.dep_it'), None) - values.update(dict([('department_id', ref('hr.dep_it'))] + res1['value'].items())) - self.write(cr, uid, [ref('hr_applicant_fresher0')], values, None) -- - On a successful meeting with the applicant, I hired employee by click on "Hired" button. -- - !python {model: hired.employee}: | - self.case_close(cr, uid, [], context={'active_ids': [ref('hr_applicant_fresher0')]}) -- - I check that applicant state is "Hired". -- - !assert {model: hr.applicant, id: hr_applicant_fresher0}: - - state == 'done' -- - I create partner for the hired applicant for accounting purpose. -- - !record {model: hr.recruitment.partner.create, id: hr_recruitment_partner_create0}: - close: False -- - I click on Create Partner button to create a partner for applicant. -- - !python {model: hr.recruitment.partner.create}: | - self.make_order(cr, uid, [ref('hr_recruitment_partner_create0')], context={'active_ids': [ref('hr_applicant_fresher0')]}) - diff --git a/addons/hr_recruitment/wizard/hr_recruitment_phonecall.py b/addons/hr_recruitment/wizard/hr_recruitment_phonecall.py index cd9cbea52f7..0f7d30b215a 100644 --- a/addons/hr_recruitment/wizard/hr_recruitment_phonecall.py +++ b/addons/hr_recruitment/wizard/hr_recruitment_phonecall.py @@ -88,7 +88,7 @@ class job2phonecall(osv.osv_memory): id2 = data_obj.browse(cr, uid, id2, context=context).res_id if id3: id3 = data_obj.browse(cr, uid, id3, context=context).res_id - + new_phonecall_id = [] for job in job_case_obj.browse(cr, uid, context.get('active_ids', []), context=context): #TODO: Take other info from job new_phonecall_id = phonecall_case_obj.create(cr, uid, { From e27eeae8506e9c6b4baa4c3e6388f798d5472c10 Mon Sep 17 00:00:00 2001 From: "Hemendra Paregi (Open ERP)" Date: Tue, 22 Nov 2011 12:40:20 +0530 Subject: [PATCH 016/117] [IMP]project_gtd: clean yml file bzr revid: hpa@tinyerp.com-20111122071020-0uwauqbta5k6pigu --- addons/project_gtd/__openerp__.py | 3 ++- addons/project_gtd/test/timebox.yml | 42 +++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 addons/project_gtd/test/timebox.yml diff --git a/addons/project_gtd/__openerp__.py b/addons/project_gtd/__openerp__.py index 761b2b44708..42ac8513f37 100644 --- a/addons/project_gtd/__openerp__.py +++ b/addons/project_gtd/__openerp__.py @@ -57,7 +57,8 @@ performing those tasks. ], 'demo_xml': ['project_gtd_demo.xml'], 'test':[ - 'test/gtd_test.yml' + #'test/gtd_test.yml', + 'test/timebox.yml' ], 'installable': True, 'active': False, diff --git a/addons/project_gtd/test/timebox.yml b/addons/project_gtd/test/timebox.yml new file mode 100644 index 00000000000..7379f5857cf --- /dev/null +++ b/addons/project_gtd/test/timebox.yml @@ -0,0 +1,42 @@ +- + In order to set Daily tasks into Weekly Timebox, I create plan for that +- + !record {model: project.timebox.fill.plan, id: plan_id}: + task_ids: [project.project_task_10] + timebox_id: timebox_daily + timebox_to_id: timebox_weekly +- + I run plan to set Daily tasks into Weekly Timebox +- + !python {model: project.timebox.fill.plan}: | + self.process(cr, uid, [ref("plan_id")]) +- + I check Weekly Timebox of task after set Timebox +- + !assert {model: project.task, id: project.project_task_10, string: Task should be set to weekly timebox}: + - timebox_id.id == ref("timebox_weekly") +- + I Empty the Daily Timebox +- + !python {model: project.timebox.empty}: | + self._empty(cr, uid, {"active_model": "project.gtd.timebox", + "active_ids":[ref("timebox_daily")], + "active_id": ref("timebox_daily"), + }) +- + I check task 'Develop time management module' is no more in Daily Timebox +- + !assert {model: project.task, id: project.project_task_10 , string: Task is not in Daily Timebox}: + - timebox_id.id != ref("timebox_daily") +- + I set Previous Timebox on task +- + !python {model: project.task}: | + self.prev_timebox(cr, uid, [ref("project.project_task_10")], + {'active_ids': [ref("project.project_task_1")],}) +- + I set Next Timebox on task +- + !python {model: project.task}: | + self.next_timebox(cr, uid, [ref("project.project_task_10")], + {'active_ids': [ref("project.project_task_1")],}) From a4d069349e7f319703417883b6811d90d8a584fd Mon Sep 17 00:00:00 2001 From: "Jagdish Panchal (Open ERP)" Date: Fri, 25 Nov 2011 10:22:11 +0530 Subject: [PATCH 017/117] [IMP] improve test case process of Job bzr revid: jap@tinyerp.com-20111125045211-ixj5bw3ucgo5246d --- addons/hr/test/open2recruit2close_job.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/addons/hr/test/open2recruit2close_job.yml b/addons/hr/test/open2recruit2close_job.yml index a33aaa7e60f..f199160d9fc 100644 --- a/addons/hr/test/open2recruit2close_job.yml +++ b/addons/hr/test/open2recruit2close_job.yml @@ -1,33 +1,34 @@ - In Order to test process of Job Position, - - I open Job Postion of "Jr. Application Engineer" Profile. + I open Job Postion for "Jr. Application Engineer" - !python {model: hr.job}: | self.job_open(cr, uid, [ref('job_jr_appli')]) - - I check state of Job Position after opened it. + I check state of Job Position after opening it. - !assert {model: hr.job, id: job_jr_appli}: - - state == 'open + - state == 'open' + - no_of_recruitment == 0 - Now, Recruitement is started so I start recruitement of Job Postion of "Jr. Application Engineer" Profile. - !python {model: hr.job}: | self.job_recruitement(cr, uid, [ref('job_jr_appli')]) - - I check state and number of Expected in Recruitment in Job Position of "Jr. Application Engineer" Profile. + I check 'state' and number of 'Expected in Recruitment' after initiating the recruitment - !assert {model: hr.job, id: job_jr_appli}: - state == 'recruit' - no_of_recruitment == 1.0 -- - I hired new employee for the job position so I set Job Position of "Jr. Application Engineer" Profile to new employee. +- + I assign the job position to a newly hired employee - !python {model: hr.employee}: | self.write(cr, uid, [ref('employee1')], {'job_id':ref('job_jr_appli')}) - - Now I don't want to recruit new employee on this position. so I mark it as Old. + Now I don't want to recruit new employee for this position. so I mark it as Old. - !python {model: hr.job}: | self.job_old(cr, uid, [ref('job_jr_appli')]) From 2275d445f95fcd7c11fbe59e94bc2f5c1feaf2f8 Mon Sep 17 00:00:00 2001 From: "Jagdish Panchal (Open ERP)" Date: Mon, 28 Nov 2011 10:43:22 +0530 Subject: [PATCH 018/117] [IMP] improve test case process of Job position bzr revid: jap@tinyerp.com-20111128051322-7bweo3pdz1u0g1fi --- addons/hr/test/open2recruit2close_job.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/addons/hr/test/open2recruit2close_job.yml b/addons/hr/test/open2recruit2close_job.yml index f199160d9fc..7647f525146 100644 --- a/addons/hr/test/open2recruit2close_job.yml +++ b/addons/hr/test/open2recruit2close_job.yml @@ -1,14 +1,14 @@ - - In Order to test process of Job Position, + I test the process of Job position in hr module of OpenERP, - - I open Job Postion for "Jr. Application Engineer" + I open Job Postion for "Jr. Application Engineer". - !python {model: hr.job}: | self.job_open(cr, uid, [ref('job_jr_appli')]) - I check state of Job Position after opening it. - - !assert {model: hr.job, id: job_jr_appli}: + !assert {model: hr.job, id: job_jr_appli, string: Job position is in 'open' state and no_of_recruitment = 0}: - state == 'open' - no_of_recruitment == 0 - @@ -19,7 +19,7 @@ - I check 'state' and number of 'Expected in Recruitment' after initiating the recruitment - - !assert {model: hr.job, id: job_jr_appli}: + !assert {model: hr.job, id: job_jr_appli, string: Job position is in 'recruit' state and no_of_recruitment = 1.0}: - state == 'recruit' - no_of_recruitment == 1.0 - @@ -33,8 +33,8 @@ !python {model: hr.job}: | self.job_old(cr, uid, [ref('job_jr_appli')]) - - I check state of Job position and number of Expected in Recruitment after closed Job position. + I check 'state' and number of 'Expected in Recruitment' after closing the Job position. - - !assert {model: hr.job, id: job_jr_appli}: + !assert {model: hr.job, id: job_jr_appli, string: Job position is in 'old' state and no_of_recruitment = 0}: - state == 'old' - no_of_recruitment == 0 \ No newline at end of file From 4b072366b2d0b1be4bb6fb429a19105e057295ed Mon Sep 17 00:00:00 2001 From: "Hemendra Paregi (Open ERP)" Date: Mon, 28 Nov 2011 10:50:04 +0530 Subject: [PATCH 019/117] [IMP]project_gtd: improvement in yml bzr revid: hpa@tinyerp.com-20111128052004-cv0w7uty6d99cehh --- addons/project_gtd/__openerp__.py | 3 +- addons/project_gtd/test/gtd_test.yml | 78 ------------------- .../test/{timebox.yml => task_timebox.yml} | 0 3 files changed, 1 insertion(+), 80 deletions(-) delete mode 100644 addons/project_gtd/test/gtd_test.yml rename addons/project_gtd/test/{timebox.yml => task_timebox.yml} (100%) diff --git a/addons/project_gtd/__openerp__.py b/addons/project_gtd/__openerp__.py index 42ac8513f37..82e3f4fcb39 100644 --- a/addons/project_gtd/__openerp__.py +++ b/addons/project_gtd/__openerp__.py @@ -57,8 +57,7 @@ performing those tasks. ], 'demo_xml': ['project_gtd_demo.xml'], 'test':[ - #'test/gtd_test.yml', - 'test/timebox.yml' + 'test/task_timebox.yml' ], 'installable': True, 'active': False, diff --git a/addons/project_gtd/test/gtd_test.yml b/addons/project_gtd/test/gtd_test.yml deleted file mode 100644 index 0583bc7e8e0..00000000000 --- a/addons/project_gtd/test/gtd_test.yml +++ /dev/null @@ -1,78 +0,0 @@ -- - Create a task 'Develop time management module' with weekly timebox -- - !record {model: project.task, id: project_task_developtimemanagementmodule0}: - name: Develop time management module - planned_hours: 15.0 - project_id: project.project_project_22 - remaining_hours: 15.0 - state: draft - timebox_id: project_gtd.timebox_weekly - - -- - Open the task -- - !python {model: project.task}: | - self.do_open(cr, uid, [ref("project_task_developtimemanagementmodule0")], {"lang": - "en_US", "project_id": False, "tz": False, "active_model": "ir.ui.menu", - "department_id": False, "section_id": False, "search_default_project_id": - False, "search_default_user_id": 1, "search_default_current": 1, "active_ids": - [ref("project.menu_action_view_task")], "active_id": ref("project.menu_action_view_task"), - }) - -- - Create time box for next week -- - !record {model: project.gtd.timebox, id: project_gtd_timebox_nextweek0}: - name: Next Week - sequence: 0.0 - -- - Create time box for tomorrow -- - !record {model: project.gtd.timebox, id: project_gtd_timebox_tomorrow1}: - name: Tomorrow - sequence: 0.0 - -- - Planify the task from weekly timebox to tomorrow timebox -- - !record {model: project.timebox.fill.plan, id: project_timebox_fill_plan_0}: - task_ids: - - project_task_developtimemanagementmodule0 - timebox_id: project_gtd.timebox_weekly - timebox_to_id: project_gtd_timebox_tomorrow1 - - -- - Set the task to tomorrow timebox -- - !python {model: project.timebox.fill.plan}: | - self.process(cr, uid, [ref("project_timebox_fill_plan_0")], {"lang": "en_US", - "project_id": False, "tz": False, "active_model": "project.gtd.timebox", - "department_id": False, "section_id": False, "record_id": 1, "active_ids": - [ref("project_gtd.timebox_daily")], "active_id": ref("project_gtd.timebox_daily"), - }) - -- - Check if task set to tomorrow timebox -- - !assert {model: project.task, id: project_task_developtimemanagementmodule0, string: Task set to tomorrow timebox}: - - timebox_id.id == ref("project_gtd_timebox_tomorrow1") - -- - Empty Timebox for tomorrow -- - !python {model: project.timebox.empty}: | - self._empty(cr, uid, {"lang": "en_US", - "project_id": False, "tz": False, "active_model": "project.gtd.timebox", - "department_id": False, "section_id": False, "record_id": 1, "active_ids": - [ref("project_gtd_timebox_tomorrow1")], "active_id": ref("project_gtd_timebox_tomorrow1"), - }) - -- - Check task 'Develop time management module' is no more in tomorrow timebox -- - !assert {model: project.task, id: project_task_developtimemanagementmodule0, string: Task is not in tomorrow timebox}: - - timebox_id.id != ref("project_gtd_timebox_tomorrow1") diff --git a/addons/project_gtd/test/timebox.yml b/addons/project_gtd/test/task_timebox.yml similarity index 100% rename from addons/project_gtd/test/timebox.yml rename to addons/project_gtd/test/task_timebox.yml From a0f45aedd5c1cd529325bb525f04434d94d12e78 Mon Sep 17 00:00:00 2001 From: "Harry (OpenERP)" Date: Mon, 28 Nov 2011 11:16:05 +0530 Subject: [PATCH 020/117] [REVIEW] HR: testing cases of Human Resource Management bzr revid: hmo@tinyerp.com-20111128054605-8wb7xpf3fn9ntiea --- addons/hr/__openerp__.py | 2 +- addons/hr/test/hr_demo.yml | 10 ++++++++++ addons/hr/test/hr_employee_demo.yml | 21 --------------------- addons/hr/test/open2recruit2close_job.yml | 6 ++---- 4 files changed, 13 insertions(+), 26 deletions(-) create mode 100644 addons/hr/test/hr_demo.yml delete mode 100644 addons/hr/test/hr_employee_demo.yml diff --git a/addons/hr/__openerp__.py b/addons/hr/__openerp__.py index c1a75cbb7f5..4c99d0d5231 100644 --- a/addons/hr/__openerp__.py +++ b/addons/hr/__openerp__.py @@ -55,8 +55,8 @@ You can manage: 'hr_department_demo.xml', ], 'test': [ - 'test/hr_employee_demo.yml', 'test/open2recruit2close_job.yml', + 'test/hr_demo.yml', ], 'installable': True, 'active': False, diff --git a/addons/hr/test/hr_demo.yml b/addons/hr/test/hr_demo.yml new file mode 100644 index 00000000000..6dee06d5eb3 --- /dev/null +++ b/addons/hr/test/hr_demo.yml @@ -0,0 +1,10 @@ +- + !record {model: hr.job, id: job_jr_appli, view: False}: + no_of_employee: 0.0 + no_of_recruitment: 5.0 +- + !record {model: hr.employee, id: employee1, view: False}: + address_id: base.main_address + company_id: base.main_company + department_id: dep_technical + user_id: base.user_demo diff --git a/addons/hr/test/hr_employee_demo.yml b/addons/hr/test/hr_employee_demo.yml deleted file mode 100644 index 846747e9a25..00000000000 --- a/addons/hr/test/hr_employee_demo.yml +++ /dev/null @@ -1,21 +0,0 @@ -- - !record {model: hr.department, id: dep_technical, view: False}: - manager_id: base.user_root - name: 'R & D' -- - !record {model: hr.job, id: job_jr_appli, view: False}: - department_id: 'dep_technical' - description: 'Position of Junior Application Engineer' - expected_employees: 5.0 - name: 'JAE' - no_of_employee: 0.0 - no_of_recruitment: 5.0 - state: open -- - !record {model: hr.employee, id: employee1, view: False}: - address_id: base.main_address - company_id: base.main_company - department_id: dep_technical - name: smith - parent_id: hr.employee1 - user_id: base.user_demo \ No newline at end of file diff --git a/addons/hr/test/open2recruit2close_job.yml b/addons/hr/test/open2recruit2close_job.yml index 7647f525146..0e618f87a3d 100644 --- a/addons/hr/test/open2recruit2close_job.yml +++ b/addons/hr/test/open2recruit2close_job.yml @@ -1,8 +1,6 @@ - - I test the process of Job position in hr module of OpenERP, + In order to test the process of Human Resource Management, I open Job Postion for "Jr. Application Engineer". - - I open Job Postion for "Jr. Application Engineer". -- !python {model: hr.job}: | self.job_open(cr, uid, [ref('job_jr_appli')]) - @@ -37,4 +35,4 @@ - !assert {model: hr.job, id: job_jr_appli, string: Job position is in 'old' state and no_of_recruitment = 0}: - state == 'old' - - no_of_recruitment == 0 \ No newline at end of file + - no_of_recruitment == 0 From 14dd6ec79008c48eb61c8eb15c30d803ef07d757 Mon Sep 17 00:00:00 2001 From: "Harry (OpenERP)" Date: Mon, 28 Nov 2011 11:39:21 +0530 Subject: [PATCH 021/117] [FIX] hr_recruitment: remove non-exits fields in demo file bzr revid: hmo@tinyerp.com-20111128060921-4v61dzokconpnzl0 --- addons/hr_recruitment/hr_recruitment_demo.xml | 37 ------------------- 1 file changed, 37 deletions(-) diff --git a/addons/hr_recruitment/hr_recruitment_demo.xml b/addons/hr_recruitment/hr_recruitment_demo.xml index 0fc2c94f034..f3790f3a43f 100644 --- a/addons/hr_recruitment/hr_recruitment_demo.xml +++ b/addons/hr_recruitment/hr_recruitment_demo.xml @@ -4,22 +4,17 @@ - - - - - @@ -33,44 +28,32 @@ - - - - - - - - - - - - @@ -78,36 +61,28 @@ - - - - - - - - @@ -121,14 +96,10 @@ - - - - @@ -141,14 +112,10 @@ - - - - @@ -157,18 +124,14 @@ - - - - From c7363ab6a2fe17b2df3486ec251d16f5a628d607 Mon Sep 17 00:00:00 2001 From: "DBR (OpenERP)" Date: Mon, 28 Nov 2011 11:43:07 +0530 Subject: [PATCH 022/117] [IMP]purchase_requisition: Improve the test case's statements bzr revid: dbr@tinyerp.com-20111128061307-8c7452lyvsin0qcn --- .../test/process/cancel_purchase_requisition.yml | 14 ++++++++++---- .../test/process/purchase_requisition.yml | 9 +++------ .../process/purchase_requisition_exclusive.yml | 12 ++++++++---- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/addons/purchase_requisition/test/process/cancel_purchase_requisition.yml b/addons/purchase_requisition/test/process/cancel_purchase_requisition.yml index eeae4689fbc..b065dfcff08 100644 --- a/addons/purchase_requisition/test/process/cancel_purchase_requisition.yml +++ b/addons/purchase_requisition/test/process/cancel_purchase_requisition.yml @@ -1,7 +1,7 @@ - - In order to test the cancel purchase requisition order. + In order to test the cancel flow of purchase requisition order. - - I try to cancel purchase requisition order. + I cancel the "New" purchase requisition order. - !python {model: purchase.requisition}: | self.tender_cancel(cr, uid, [ref("order_purchase_requisition1")]) @@ -10,6 +10,11 @@ - !assert {model: purchase.requisition, id: order_purchase_requisition1}: - state == 'cancel' +- + I reset the state of requisition as "New". +- + !python {model: purchase.requisition}: | + self.tender_reset(cr, uid, ref('order_purchase_requisition1')) - I change state of requisition in "In progress". - @@ -51,7 +56,7 @@ !assert {model: purchase.requisition, id: order_purchase_requisition1}: - state == 'done' - - I try to cancel 'Done' purchase requisition order. + I try to cancel "Done" purchase requisition order. - !python {model: purchase.requisition}: | self.tender_cancel(cr, uid, [ref("order_purchase_requisition1")]) @@ -64,4 +69,5 @@ I reset the state of requisition as "New". - !python {model: purchase.requisition}: | - self.tender_reset(cr, uid, ref('order_purchase_requisition1')) + self.tender_reset(cr, uid, ref('order_purchase_requisition1')) + diff --git a/addons/purchase_requisition/test/process/purchase_requisition.yml b/addons/purchase_requisition/test/process/purchase_requisition.yml index 3be7e2a9ea9..d1c6fe8eb84 100644 --- a/addons/purchase_requisition/test/process/purchase_requisition.yml +++ b/addons/purchase_requisition/test/process/purchase_requisition.yml @@ -1,18 +1,15 @@ - - In order to test the purchase requisition module, I have to checked a boolean field 'purchase requisition' in product, - If I checked it then it's requisition will be create. + In order to test the purchase requisition module, I have to checked product's boolean field 'purchase requisition'. - I start by Checking the product, Product must have requisition field checked. - and Product supply method is buy and the procure method is make to order. - !record {model: product.product, id: product.product_product_hdd3}: - supply_method: 'buy' purchase_requisition: True - - I create the procurement order for the product and after run that procurement for create purchase requisition. + I create the product's procurement order and run that procurement. + After Run the procurement I check created purchase requisition [Tender]. - !python {model: product.product}: | - import time import netsvc mk_proc = self.pool.get('make.procurement') proc_order = self.pool.get('procurement.order') diff --git a/addons/purchase_requisition/test/process/purchase_requisition_exclusive.yml b/addons/purchase_requisition/test/process/purchase_requisition_exclusive.yml index 8a9116de0d3..e5f7f61a5fd 100644 --- a/addons/purchase_requisition/test/process/purchase_requisition_exclusive.yml +++ b/addons/purchase_requisition/test/process/purchase_requisition_exclusive.yml @@ -1,17 +1,21 @@ - - In order to test the exclusive type requisition, I have to create two differ purchase order in one requisition [Tender] + In order to test the exclusive type requisition, I have to create two differ purchase order of one requisition [Tender] - - I start by Checking the product, Product must have requisition field checked. + I select purchase requisition of '[CPU1] Processor AMD Athlon XP 1800+' and '[CPU3] Processor AMD Athlon XP 2200+'. + So, those products must have requisition field checked. +- + I start by Checking requisition field for '[CPU1] Processor AMD Athlon XP 1800+' product. - !record {model: product.product, id: product.product_product_cpu1}: purchase_requisition: True - - Checking requisition field for another product. + Checked requisition field for '[CPU3] Processor AMD Athlon XP 2200+' product. - !record {model: product.product, id: product.product_product_cpu3}: purchase_requisition: True - - Now check that purchase order's product must have requisition field checked. + I search the purchase orders which have exclusive purchase requisition 'TE00001' and confirm any one of them. + Then check the remaining purchase orders goes in to cancel state. - !python {model: purchase.order}: | import netsvc From 3cba14171c02bdf818ce2b02be2049dbd509fe0e Mon Sep 17 00:00:00 2001 From: "Harry (OpenERP)" Date: Mon, 28 Nov 2011 11:52:47 +0530 Subject: [PATCH 023/117] [IMP] hr_recruitment: improve yml test process to check attachment in email after getting bzr revid: hmo@tinyerp.com-20111128062247-ztxmc9zdrdzy57yp --- addons/hr_recruitment/test/recruitment_process.yml | 8 +++++--- addons/hr_recruitment/test/resume.eml | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/addons/hr_recruitment/test/recruitment_process.yml b/addons/hr_recruitment/test/recruitment_process.yml index 64e8ab687a8..33232ab0f2f 100644 --- a/addons/hr_recruitment/test/recruitment_process.yml +++ b/addons/hr_recruitment/test/recruitment_process.yml @@ -15,8 +15,10 @@ applicant_ids = self.search(cr, uid, [('email_from','=', 'Mr. Richard Anderson ')]) assert applicant_ids, "Applicant is not created after getting the mail" applicant = self.browse(cr, uid, applicant_ids[0], context=context) - assert applicant.name == "Application for the post of Jr.application Programmer", "Subject does not match" + resume_ids = self.pool.get('ir.attachment').search(cr, uid, [('datas_fname','=','resume.doc'),('res_model','=',self._name),('res_id','=',applicant.id)]) + assert applicant.name == "Application for the post of Jr.application Programmer.", "Subject does not match" assert applicant.state == "draft" + assert len(resume_ids), "Resume does not attached." - I assign the Job position to the applicant - @@ -54,7 +56,7 @@ !python {model: hr.applicant}: | self.action_print_survey(cr, uid, [ref('hr_case_programmer')]) - - On a successful meeting with the applicant, I hired employee. + On a successful interview with the applicant, I hired employee. - !python {model: hr.applicant}: | self.case_close(cr, uid, [ref('hr_case_programmer')]) @@ -62,4 +64,4 @@ I check that applicant is "Hired". - !assert {model: hr.applicant, id: hr_case_programmer}: - - state == 'done' \ No newline at end of file + - state == 'done' diff --git a/addons/hr_recruitment/test/resume.eml b/addons/hr_recruitment/test/resume.eml index 9529873a49c..00cc5620563 100644 --- a/addons/hr_recruitment/test/resume.eml +++ b/addons/hr_recruitment/test/resume.eml @@ -24,11 +24,11 @@ X-YMail-OSG: 09Al2uQVM1n5JcQepgua6wQsww7jiatAHXaSsMjP5Qvk9Ba LLM1_BE.EOvXdW38ZC_hHcrM4xYaYSR7c0WaOQsR8EZeXk_Vhio7HHUrdxZl 1oZz7YWK9Q04M023JJoM4v6IrThy3BNepluEFFcavkyOnCw-- X-Yahoo-SMTP: oNtzSBqswBAqJIGYOgyGesyleENrhUEtEgBkQ053 -Received: from [192.168.1.30] (jagdish.n_panchal@180.211.100.2 with plain) +Received: from [192.168.1.30] (test@180.211.100.2 with plain) by smtp205.mail.ne1.yahoo.com with SMTP; 18 Nov 2011 01:26:47 -0800 PST Message-ID: <4EC624C7.6020000@yahoo.in> Date: Fri, 18 Nov 2011 14:56:31 +0530 -From: Richard Anderson +From: Mr. Richard Anderson User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.17) Gecko/20110424 Thunderbird/3.1.10 MIME-Version: 1.0 To: hr@mycompany.com From b281d832197aaa73edc6ffd986c5a81ef723d6fa Mon Sep 17 00:00:00 2001 From: "DBR (OpenERP)" Date: Mon, 28 Nov 2011 11:54:22 +0530 Subject: [PATCH 024/117] [IMP,REMOVE]purchase_requisition: Remove onchange_events.yml Improve the requisition2request_quotation.yml and __openerp__.py bzr revid: dbr@tinyerp.com-20111128062422-1l7jopbjkwajc3dc --- addons/purchase_requisition/__openerp__.py | 1 - .../test/ui/onchange_events.yml | 28 ------------------- .../test/ui/requisiton2request_quotation.yml | 6 ++-- 3 files changed, 3 insertions(+), 32 deletions(-) delete mode 100644 addons/purchase_requisition/test/ui/onchange_events.yml diff --git a/addons/purchase_requisition/__openerp__.py b/addons/purchase_requisition/__openerp__.py index 426e8a770fc..67c916aefae 100644 --- a/addons/purchase_requisition/__openerp__.py +++ b/addons/purchase_requisition/__openerp__.py @@ -48,7 +48,6 @@ This new object will regroup and will allow you to easily keep track and order a 'test/process/purchase_requisition_exclusive.yml', 'test/ui/requisiton2request_quotation.yml', 'test/process/cancel_purchase_requisition.yml', - 'test/ui/onchange_events.yml', 'test/ui/purchase_requisition_report.yml', 'test/ui/delete_requisition.yml', ], diff --git a/addons/purchase_requisition/test/ui/onchange_events.yml b/addons/purchase_requisition/test/ui/onchange_events.yml deleted file mode 100644 index 901c50ca1c9..00000000000 --- a/addons/purchase_requisition/test/ui/onchange_events.yml +++ /dev/null @@ -1,28 +0,0 @@ -- - In order to test the onchange events of purchase requisition. -- - I call onchange event to change the product of purchase requisition line. -- - !python {model: purchase.requisition.line}: | - self.onchange_product_id(cr, uid, [ref('order_purchase_requisition1')],ref('product.product_product_hdd2'), ref('product.product_uom_unit')) -- - I change state of requisition in "In progress". -- - !python {model: purchase.requisition}: | - self.tender_in_progress(cr, uid, ref('order_purchase_requisition1')) -- - I change state of requisition as "done". -- - !python {model: purchase.requisition}: | - self.tender_done(cr, uid, ref('order_purchase_requisition1')) -- - I reset the state of requisition as "New". -- - !python {model: purchase.requisition}: | - self.tender_reset(cr, uid, ref('order_purchase_requisition1')) -- - I call onchange event to change the partner of purchase requisition. -- - !python {model: purchase.requisition.partner}: | - self.onchange_partner_id(cr, uid, ref('order_purchase_requisition1'), ref('base.res_partner_desertic_hispafuentes')) - diff --git a/addons/purchase_requisition/test/ui/requisiton2request_quotation.yml b/addons/purchase_requisition/test/ui/requisiton2request_quotation.yml index 6c0ce5eee0a..722ab6df591 100644 --- a/addons/purchase_requisition/test/ui/requisiton2request_quotation.yml +++ b/addons/purchase_requisition/test/ui/requisiton2request_quotation.yml @@ -5,13 +5,13 @@ partner_address_id: base.res_partner_address_3000 partner_id: base.res_partner_desertic_hispafuentes - - I click on 'Create Quotation' for creating PO. + I click on 'Create Quotation' for creating a Quatation. - !python {model: purchase.requisition.partner}: | self.create_order(cr, uid, [ref("purchase_requisition_partner_0")], {"active_model": "purchase.requisition", "active_ids": [ref("order_purchase_requisition1")],"active_id": ref("order_purchase_requisition1"), }) - - I check that the purchase order is created. + I check that the purchase order created. - !python {model: purchase.order}: | purchase_ids= self.search(cr, uid, [('requisition_id','=',ref("order_purchase_requisition1"))]) @@ -20,4 +20,4 @@ assert rfq.state == 'draft',"Purchase Order should be in draft state" assert rfq.partner_address_id.id == ref('base.res_partner_address_3000'),"Purchase Order Partner address is not correspond" assert rfq.partner_id.id == ref('base.res_partner_desertic_hispafuentes'),"Purchase Order Partner is not correspond" - + From 9c582e04e7b00d0f022f853e6228df2c642e4b7f Mon Sep 17 00:00:00 2001 From: "Harry (OpenERP)" Date: Mon, 28 Nov 2011 12:03:18 +0530 Subject: [PATCH 025/117] [REF] hr_recruitment: refector code of case_close_with_rmp of hr_recruitment bzr revid: hmo@tinyerp.com-20111128063318-02c90onrf005yo9t --- addons/hr_recruitment/hr_recruitment.py | 47 +++++++------------ .../test/recruitment_process.yml | 2 +- 2 files changed, 17 insertions(+), 32 deletions(-) diff --git a/addons/hr_recruitment/hr_recruitment.py b/addons/hr_recruitment/hr_recruitment.py index 931600fef9f..60657e9ff85 100644 --- a/addons/hr_recruitment/hr_recruitment.py +++ b/addons/hr_recruitment/hr_recruitment.py @@ -403,14 +403,6 @@ class hr_applicant(crm.crm_case, osv.osv): return res def case_close(self, cr, uid, ids, *args): - """ - @param self: The object pointer - @param cr: the current row, from the database cursor, - @param uid: the current user’s ID for security checks, - @param ids: List of case's Ids - @param *args: Give Tuple Value - """ - employee_obj = self.pool.get('hr.employee') res = super(hr_applicant, self).case_close(cr, uid, ids, *args) for (id, name) in self.name_get(cr, uid, ids): message = _("Applicant '%s' is being hired.") % name @@ -418,29 +410,22 @@ class hr_applicant(crm.crm_case, osv.osv): return res def case_close_with_emp(self, cr, uid, ids, *args): - """ - @param self: The object pointer - @param cr: the current row, from the database cursor, - @param uid: the current user’s ID for security checks, - @param ids: List of case's Ids - @param *args: Give Tuple Value - """ - employee_obj = self.pool.get('hr.employee') - partner_obj = self.pool.get('res.partner') - address_id = False - applicant = self.browse(cr, uid, ids)[0] - if applicant.partner_id: - address_id = partner_obj.address_get(cr, uid, [applicant.partner_id.id], ['contact'])['contact'] - if applicant.job_id: - self.pool.get('hr.job').write(cr, uid, [applicant.job_id.id], {'no_of_recruitment': applicant.job_id.no_of_recruitment - 1}) - emp_id = employee_obj.create(cr,uid,{'name': applicant.partner_name or applicant.name, - 'job_id': applicant.job_id.id, - 'address_home_id': address_id, - 'department_id': applicant.department_id.id - }) - else: - raise osv.except_osv(_('Warning!'),_('You must define Applied Job for Applicant !')) - return self.case_close(cr, uid, ids, *args) + hr_employee = self.pool.get('hr.employee') + for applicant in self.browse(cr, uid, ids): + address_id = False + if applicant.partner_id: + address_id = applicant.partner_id.address_get(['contact'])['contact'] + if applicant.job_id: + applicant.job_id.write({'no_of_recruitment': applicant.job_id.no_of_recruitment - 1}) + emp_id = hr_employee.create(cr,uid,{'name': applicant.partner_name or applicant.name, + 'job_id': applicant.job_id.id, + 'address_home_id': address_id, + 'department_id': applicant.department_id.id + }) + self.case_close(cr, uid, [applicant.id], *args) + else: + raise osv.except_osv(_('Warning!'),_('You must define Applied Job for Applicant !')) + return True def case_reset(self, cr, uid, ids, *args): """Resets case as draft diff --git a/addons/hr_recruitment/test/recruitment_process.yml b/addons/hr_recruitment/test/recruitment_process.yml index 33232ab0f2f..43575137a6e 100644 --- a/addons/hr_recruitment/test/recruitment_process.yml +++ b/addons/hr_recruitment/test/recruitment_process.yml @@ -59,7 +59,7 @@ On a successful interview with the applicant, I hired employee. - !python {model: hr.applicant}: | - self.case_close(cr, uid, [ref('hr_case_programmer')]) + self.case_close_with_emp(cr, uid, [ref('hr_case_programmer')]) - I check that applicant is "Hired". - From 54d2f76703983cf2ed11e260723f606d9a4234fb Mon Sep 17 00:00:00 2001 From: "DBR (OpenERP)" Date: Mon, 28 Nov 2011 12:39:51 +0530 Subject: [PATCH 026/117] [REMOVE]purchase_requisition: remove duplicate_requisition.yml bzr revid: dbr@tinyerp.com-20111128070951-1pogxrrc3921tv24 --- .../test/ui/duplicate_requisition.yml | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 addons/purchase_requisition/test/ui/duplicate_requisition.yml diff --git a/addons/purchase_requisition/test/ui/duplicate_requisition.yml b/addons/purchase_requisition/test/ui/duplicate_requisition.yml deleted file mode 100644 index 742500d865d..00000000000 --- a/addons/purchase_requisition/test/ui/duplicate_requisition.yml +++ /dev/null @@ -1,8 +0,0 @@ -- - In order to test the duplicate order and check duplicate details. -- - I duplicate order. -- - !python {model: purchase.requisition}: | - context.update({'active_id':ref('order_purchase_requisition1')}) - self.copy(cr, uid, ref('order_purchase_requisition1'), context) From be3f9fa4362d095d6d5268f46e433c7bcbf5b2e3 Mon Sep 17 00:00:00 2001 From: "Turkesh Patel (Open ERP)" Date: Mon, 28 Nov 2011 15:07:23 +0530 Subject: [PATCH 027/117] [IMP] clean YML and added draft2open2close_phase.yml bzr revid: tpa@tinyerp.com-20111128093723-8cny1olo2wcnitxt --- addons/project_long_term/__openerp__.py | 7 +- .../project_long_term_demo.xml | 6 +- .../test/draft2open2close_phase.yml | 40 +++ .../test/phase_constraint.yml | 118 --------- .../test/project_schedule_consecutive_day.yml | 127 --------- .../project_schedule_without_wroking_hour.yml | 76 ------ .../test/schedule_project_phases.yml | 221 ++++------------ .../test/schedule_project_tasks.yml | 93 ++----- .../test/test_schedule_phases_case1.yml | 76 ------ .../test/test_schedule_phases_case2.yml | 193 -------------- .../test/test_schedule_tasks_case1.yml | 246 ------------------ 11 files changed, 112 insertions(+), 1091 deletions(-) create mode 100644 addons/project_long_term/test/draft2open2close_phase.yml delete mode 100644 addons/project_long_term/test/phase_constraint.yml delete mode 100644 addons/project_long_term/test/project_schedule_consecutive_day.yml delete mode 100644 addons/project_long_term/test/project_schedule_without_wroking_hour.yml delete mode 100644 addons/project_long_term/test/test_schedule_phases_case1.yml delete mode 100644 addons/project_long_term/test/test_schedule_phases_case2.yml delete mode 100644 addons/project_long_term/test/test_schedule_tasks_case1.yml diff --git a/addons/project_long_term/__openerp__.py b/addons/project_long_term/__openerp__.py index 31522d63ea2..f4dd4637f0f 100644 --- a/addons/project_long_term/__openerp__.py +++ b/addons/project_long_term/__openerp__.py @@ -43,14 +43,9 @@ Features "init_xml": [], "demo_xml": ["project_long_term_demo.xml"], "test": [ - 'test/test_schedule_phases_case1.yml', 'test/schedule_project_phases.yml', 'test/schedule_project_tasks.yml', - 'test/test_schedule_phases_case2.yml', - 'test/project_schedule_consecutive_day.yml', - 'test/project_schedule_without_wroking_hour.yml', - 'test/phase_constraint.yml', - 'test/test_schedule_tasks_case1.yml', + 'test/draft2open2close_phase.yml', ], "update_xml": [ "security/ir.model.access.csv", diff --git a/addons/project_long_term/project_long_term_demo.xml b/addons/project_long_term/project_long_term_demo.xml index fe3f8c8e510..ac15249499e 100644 --- a/addons/project_long_term/project_long_term_demo.xml +++ b/addons/project_long_term/project_long_term_demo.xml @@ -37,9 +37,9 @@ - + - + Development and Integration @@ -60,7 +60,7 @@ Deployement and Training - + 10 diff --git a/addons/project_long_term/test/draft2open2close_phase.yml b/addons/project_long_term/test/draft2open2close_phase.yml new file mode 100644 index 00000000000..610ccb8180a --- /dev/null +++ b/addons/project_long_term/test/draft2open2close_phase.yml @@ -0,0 +1,40 @@ +- + I make "Collect Requirement and Make SRS" in open state. +- + !python {model: project.phase}: | + self.set_open(cr, uid, [ref("project_phase_1")]) +- + I check state of phase after put in open. +- + !assert {model: project.phase, id: project_phase_1, severity: error, string: Phase should be in open state}: + - state == "open" +- + I make Phase in pending state because of resource problem. +- + !python {model: project.phase}: | + self.set_pending(cr, uid, [ref("project_phase_1")]) +- + I check state of phase after put in pending. +- + !assert {model: project.phase, id: project_phase_1, severity: error, string: Phase should be in pending state}: + - state == "pending" +- + I make Phase in cancel state. +- + !python {model: project.phase}: | + self.set_cancel(cr, uid, [ref("project_phase_1")]) +- + I check state of phase after put in cancel. +- + !assert {model: project.phase, id: project_phase_1, severity: error, string: Phase should be in cancel state}: + - state == "cancelled" +- + I make Phase "Design Model" in done state. +- + !python {model: project.phase}: | + self.set_done(cr, uid, [ref("project_phase_2")]) +- + I check state of phase after put in done. +- + !assert {model: project.phase, id: project_phase_2, severity: error, string: Phase should be in done state}: + - state == "done" \ No newline at end of file diff --git a/addons/project_long_term/test/phase_constraint.yml b/addons/project_long_term/test/phase_constraint.yml deleted file mode 100644 index f4fa09e6e38..00000000000 --- a/addons/project_long_term/test/phase_constraint.yml +++ /dev/null @@ -1,118 +0,0 @@ -- - Given that I have a project 'Test Phases'. -- - !record {model: project.project, id: project_project_developyamlproject0}: - name: "Develop Yaml Project Module" - date_start: !eval time.strftime('%Y-%m-%d') - resource_calendar_id: resource.timesheet_group1 - members: - - base.user_admin -- - And I create three human ressources to work on this project, an analyst. -- - !record {model: resource.resource, id: resource_resource_analyst1}: - calendar_id: resource.timesheet_group1 - name: Analyst - resource_type: user - time_efficiency: 1.0 - user_id: base.user_admin -- - I define a developer HR. -- - !record {model: resource.resource, id: resource_resource_develop0}: - calendar_id: resource.timesheet_group1 - name: Developer - resource_type: user - time_efficiency: 1.0 - user_id: base.user_admin -- - I define a tester HR. -- - !record {model: resource.resource, id: resource_resource_tester1}: - calendar_id: resource.timesheet_group1 - name: tester - resource_type: user - time_efficiency: 1.0 - user_id: base.user_admin -- - Then I create three phases for my projects; Analysis, Development, Testing. -- - The first phase is 'Analysis' and has a duration of 6 days. -- - !record {model: project.phase, id: project_phase_analysisflowforyaml0}: - date_start: !eval time.strftime('%Y-%m-%d') - duration: 6.0 - name: "Analysis" - product_uom: product.uom_day - project_id: project_project_developyamlproject0 - state: draft - -- - I update the constrain and the analysis phase to not start before 4 days. -- - !python {model : project.phase }: | - pass - import datetime - from dateutil.relativedelta import * - start = datetime.date.today() + relativedelta(days=4) - self.write(cr,uid, [(ref("project_phase_analysisflowforyaml0"))], {'constraint_date_start': start}) -- - The second phase is 'Development' and depend on the 'Analysis', with a duration of 6 days. -- - !record {model: project.phase, id: project_phase_developyaml0}: - duration: 6.0 - name: Development - product_uom: product.uom_day - project_id: project_project_developyamlproject0 - previous_phase_ids: - - project_phase_analysisflowforyaml0 - -- - I update the Constrain Date Start adn Date End for phase Develop yaml -- - !python {model : project.phase }: | - pass - import datetime - #from dateutil.relativedelta import * - #start = datetime.date.today() - relativedelta(days=5) - #end = datetime.date.today() + relativedelta(days=10) - #self.write(cr,uid, [(ref("project_phase_developyaml0"))], {'constraint_date_start': start, 'constraint_date_end':end}) -- - The third phase is 'Testing' and depend on the 'Develop' phase, with a duration of 6 days. -- - !record {model: project.phase, id: project_phase_testyaml0}: - duration: 6.0 - name: Testing - product_uom: product.uom_day - project_id: project_project_developyamlproject0 - previous_phase_ids: - - project_phase_developyaml0 -- - Then I launch the scheduler to compute starting and ending phases on all phases of this project. -- - !record {model: project.compute.phases, id: project_compute_phases_0}: - project_id: project_project_developyamlproject0 - target_project: one -- - !python {model: project.project}: | - self.schedule_phases(cr, uid, [ref("project_project_developyamlproject0")]) -- - After scheduling, I check the starting date and ending date on the phases are correct. -- - !python {model: project.phase}: | - import datetime - from dateutil.relativedelta import * - minstart = (datetime.date.today() + relativedelta(days=4)).strftime('%Y-%m-%d') - minend = (datetime.date.today() + relativedelta(days=11)).strftime('%Y-%m-%d') - - phase1=self.browse(cr, uid, ref('project_phase_analysisflowforyaml0')) - assert phase1.date_start>=minstart, 'Error, the Analysis phase '+phase1.date_start+' should start after '+str(minstart) - assert phase1.date_end>=minend, 'Error, the Analysis phase should end after '+str(minend) - - phase2=self.browse(cr, uid, ref('project_phase_developyaml0')) - assert phase2.date_start>=phase1.date_end, 'Error, the phase Development should start after the end of the Analysis phase' - - phase3=self.browse(cr, uid, ref('project_phase_testyaml0')) - assert phase3.date_start>=phase2.date_end, 'Error, the phase Testing should start after the end of the Development phase' - assert phase3.date_start=minstart, 'Error, the Collect Requirement and Make SRS phase '+phase1.date_start+' should start after '+str(minstart) + assert phase1.date_end>=minend, 'Error, the Collect Requirement and Make SRS phase should end after '+str(minend) + phase2=self.browse(cr, uid, ref('project_phase_2')) + assert phase2.date_start>=phase1.date_end, 'Error, the phase Design Model should start after the end of the Collect Requirement and Make SRS phase' + + phase3=self.browse(cr, uid, ref('project_phase_3')) + assert phase3.date_start>=phase2.date_end, 'Error, the phase Development and Integration should start after the end of the Design Model phase' + + phase4=self.browse(cr, uid, ref('project_phase_4')) + assert phase4.date_start>=phase3.date_end, 'Error, the phase Review and Testing should start after the end of the Development and Integration phase' + + phase5=self.browse(cr, uid, ref('project_phase_5')) + assert phase5.date_start>=phase4.date_end, 'Error, the phase Deployement and Training start after the end of the Review and Testing phase' + assert phase5.date_start= start),'Start dates are wrong: %s < %s !' % (first_phase.date_start[:10], start) - assert (first_phase.date_end >= end),'End dates are wrong: %s <%s!' % (first_phase.date_end, end) - - second_phase = self.browse(cr, uid, ref('project_phase_secondphase0_case2')) - start = first_phase.date_end - end = (datetime.date.today() + relativedelta(days=4)).strftime('%Y-%m-%d') - assert second_phase.date_start >= start, 'Dates are wrong on second phase: %s < %s!' % (second_phase.date_start, start) - assert second_phase.date_end >= end, 'Dates are wrong on second phase %s < %s!' % (second_phase.date_end, end) - diff --git a/addons/project_long_term/test/test_schedule_phases_case2.yml b/addons/project_long_term/test/test_schedule_phases_case2.yml deleted file mode 100644 index 35173a897a3..00000000000 --- a/addons/project_long_term/test/test_schedule_phases_case2.yml +++ /dev/null @@ -1,193 +0,0 @@ -- - In order to test scheduling of project phases, I create two different - working periods and resources. And schedule the phases. -- - I create first working period 'Working Time A'. -- - !record {model: resource.calendar, id: resource_calendar_workingtimea0}: - attendance_ids: - - dayofweek: '0' - hour_from: 10.0 - hour_to: 16.0 - name: Monday - - dayofweek: '1' - hour_from: 10.0 - hour_to: 16.0 - name: Tuesday - - dayofweek: '2' - hour_from: 10.0 - hour_to: 16.0 - name: Wednesday - - dayofweek: '3' - hour_from: 10.0 - hour_to: 16.0 - name: Thursday - name: Working Time A - -- - Creating a resource.calendar.attendance record -- - !record {model: resource.calendar.attendance, id: resource_calendar_attendance_monday0}: - calendar_id: resource_calendar_workingtimea0 - dayofweek: '0' - hour_from: 10.0 - hour_to: 16.0 - name: Monday -- - Creating a resource.calendar.attendance record -- - !record {model: resource.calendar.attendance, id: resource_calendar_attendance_tuesday0}: - calendar_id: resource_calendar_workingtimea0 - dayofweek: '1' - hour_from: 10.0 - hour_to: 16.0 - name: Tuesday -- - Creating a resource.calendar.attendance record -- - !record {model: resource.calendar.attendance, id: resource_calendar_attendance_wednesday0}: - calendar_id: resource_calendar_workingtimea0 - dayofweek: '2' - hour_from: 10.0 - hour_to: 16.0 - name: Wednesday -- - Creating a resource.calendar.attendance record -- - !record {model: resource.calendar.attendance, id: resource_calendar_attendance_thursday0}: - calendar_id: resource_calendar_workingtimea0 - dayofweek: '3' - hour_from: 10.0 - hour_to: 16.0 - name: Thursday -- - I create second working period 'Working Time B'. -- - !record {model: resource.calendar, id: resource_calendar_workingtimeb0}: - attendance_ids: - - dayofweek: '4' - hour_from: 9.0 - hour_to: 18.0 - name: Friday - name: Working Time B -- - Creating a resource.calendar.attendance record -- - !record {model: resource.calendar.attendance, id: resource_calendar_attendance_friday0}: - calendar_id: resource_calendar_workingtimeb0 - dayofweek: '4' - hour_from: 9.0 - hour_to: 18.0 - name: Friday -- - I create first resource say 'Resource X' without assigning working period. -- - !record {model: resource.resource, id: resource_resource_resourcex0}: - name: Resource X - resource_type: user - time_efficiency: 1.0 - user_id: base.user_admin -- - I create first resource say 'Resource Y' with working period 'Working Time B'. -- - !record {model: resource.resource, id: resource_resource_resourcey0}: - calendar_id: resource_calendar_workingtimeb0 - name: Resource Y - resource_type: user - time_efficiency: 1.0 - user_id: base.user_admin -- - I create a project 'Development and Testing' and assign working period 'Working Time A'. -- - !record {model: project.project, id: project_project_project0}: - balance: 0.0 - credit: 0.0 - currency_id: base.EUR - debit: 0.0 - effective_hours: 0.0 - members: - - base.user_admin - name: Development and Testing - planned_hours: 20.0 - progress_rate: 0.0 - quantity: 0.0 - quantity_max: 0.0 - resource_calendar_id: resource_calendar_workingtimea0 - state: open - tasks: - - delay_hours: 0.0 - effective_hours: 0.0 - name: Task 1 - planned_hours: 10.0 - remaining_hours: 10.0 - state: draft - total_hours: 10.0 - - delay_hours: 0.0 - effective_hours: 0.0 - name: Task 2 - planned_hours: 10.0 - remaining_hours: 10.0 - state: draft - total_hours: 10.0 - total_hours: 10.0 - members: - - project.res_users_analyst - - project.res_users_project_manager - - project.res_users_technical_leader - - project.res_users_developer - - project.res_users_designer - - project.res_users_tester - type_ids: - - project.project_tt_specification - - project.project_tt_development - - project.project_tt_testing - - project.project_tt_merge - -- - I create a phase 'Initial Phase' for project 'Development and Testing'. -- - !record {model: project.phase, id: project_phase_phase0}: - date_start: '2011-01-03 08:00:00' - duration: 0.0 - name: Initial Phase - product_uom: product.uom_day - project_id: project_project_project0 - state: draft -- - I create first task 'Developing module' and assign 10h. -- - !record {model: project.task, id: project_task_task0}: - delay_hours: 0.0 - effective_hours: 0.0 - name: Developing module - planned_hours: 10.0 - project_id: project_project_project0 - remaining_hours: 10.0 - state: draft - total_hours: 10.0 - phase_id: project_phase_phase0 -- - I create first task 'Testing module' and assign 10h. -- - !record {model: project.task, id: project_task_task1}: - delay_hours: 0.0 - effective_hours: 0.0 - name: Testing module - planned_hours: 10.0 - project_id: project_project_project0 - remaining_hours: 10.0 - state: draft - total_hours: 10.0 - phase_id: project_phase_phase0 -- - Now I create a record to compute the phase of project. -- - !record {model: project.compute.phases, id: project_compute_phases0}: - target_project: 'one' - project_id: project_project_project0 -- - I schedule the phases. -- - !python {model: project.compute.phases}: | - self.check_selection(cr, uid, [ref("project_compute_phases0")]) - diff --git a/addons/project_long_term/test/test_schedule_tasks_case1.yml b/addons/project_long_term/test/test_schedule_tasks_case1.yml deleted file mode 100644 index 3bb0ea87c43..00000000000 --- a/addons/project_long_term/test/test_schedule_tasks_case1.yml +++ /dev/null @@ -1,246 +0,0 @@ -- - In order to test scheduling of tasks, I create four tasks with different sequences and schedule them. -- - I create first user. -- - !record {model: res.users, id: res_users_user0}: - company_id: base.main_company - context_lang: en_US - groups_id: - - base.group_partner_manager - - base.group_user - login: user1 - name: User 1 - password: user1 -- - I create second user. -- - !record {model: res.users, id: res_users_user1}: - company_id: base.main_company - context_lang: en_US - groups_id: - - base.group_partner_manager - - base.group_user - login: user2 - name: User 2 - password: user2 -- - I create a Project. -- - !record {model: project.project, id: project_project_projecta0}: - balance: 0.0 - credit: 0.0 - currency_id: base.EUR - debit: 0.0 - effective_hours: 0.0 - name: Project A - members: - - res_users_user0 - - res_users_user1 - phase_ids: - - date_start: '2011-01-06 08:00:00' - duration: 2.0 - name: Phase A - product_uom: product.uom_day - state: draft - task_ids: - - delay_hours: 0.0 - effective_hours: 0.0 - name: Task D - planned_hours: 5.0 - remaining_hours: 5.0 - state: draft - total_hours: 5.0 - - delay_hours: 0.0 - effective_hours: 0.0 - name: Task C - planned_hours: 5.0 - remaining_hours: 5.0 - sequence: 11 - state: draft - total_hours: 5.0 - - delay_hours: 0.0 - effective_hours: 0.0 - name: Task B - planned_hours: 5.0 - remaining_hours: 5.0 - sequence: 13 - state: draft - total_hours: 5.0 - - delay_hours: 0.0 - effective_hours: 0.0 - name: Task A - planned_hours: 5.0 - remaining_hours: 5.0 - sequence: 14 - state: draft - total_hours: 5.0 - planned_hours: 20.0 - progress_rate: 0.0 - quantity: 0.0 - quantity_max: 0.0 - state: open - tasks: - - delay_hours: 0.0 - effective_hours: 0.0 - name: Task D - planned_hours: 5.0 - remaining_hours: 5.0 - state: draft - total_hours: 5.0 - - delay_hours: 0.0 - effective_hours: 0.0 - name: Task C - planned_hours: 5.0 - remaining_hours: 5.0 - sequence: 11 - state: draft - total_hours: 5.0 - - delay_hours: 0.0 - effective_hours: 0.0 - name: Task B - planned_hours: 5.0 - remaining_hours: 5.0 - sequence: 13 - state: draft - total_hours: 5.0 - - delay_hours: 0.0 - effective_hours: 0.0 - name: Task A - planned_hours: 5.0 - remaining_hours: 5.0 - sequence: 14 - state: draft - total_hours: 5.0 - total_hours: 15.0 -- - I create first task with highest sequence. -- - !record {model: project.task, id: project_task_taska0}: - delay_hours: 0.0 - effective_hours: 0.0 - name: Task A - planned_hours: 5.0 - project_id: project_project_projecta0 - remaining_hours: 5.0 - sequence: 14 - state: draft - total_hours: 5.0 -- - I create second task. -- - !record {model: project.task, id: project_task_taskb0}: - delay_hours: 0.0 - effective_hours: 0.0 - name: Task B - planned_hours: 5.0 - project_id: project_project_projecta0 - remaining_hours: 5.0 - sequence: 13 - state: draft - total_hours: 5.0 -- - I create third task. -- - !record {model: project.task, id: project_task_taskc0}: - delay_hours: 0.0 - effective_hours: 0.0 - name: Task C - planned_hours: 5.0 - project_id: project_project_projecta0 - remaining_hours: 5.0 - sequence: 11 - state: draft - total_hours: 5.0 -- - I create fourth task with lowest sequence. -- - !record {model: project.task, id: project_task_taskd0}: - delay_hours: 0.0 - effective_hours: 0.0 - name: Task D - planned_hours: 5.0 - project_id: project_project_projecta0 - remaining_hours: 5.0 - state: draft - total_hours: 5.0 -- - Now I create a resource for first user. -- - !record {model: resource.resource, id: resource_resource_user0}: - name: User 1 - resource_type: user - time_efficiency: 1.0 - user_id: res_users_user0 -- - I create a resource for second user. -- - !record {model: resource.resource, id: resource_resource_user1}: - name: User 2 - resource_type: user - time_efficiency: 1.0 - user_id: res_users_user1 -- - Now I create one phase for the project. -- - !record {model: project.phase, id: project_phase_phasea0}: - date_start: '2011-01-06 08:00:00' - duration: 2.0 - name: Phase A - product_uom: product.uom_day - project_id: project_project_projecta0 - state: draft - task_ids: - - delay_hours: 0.0 - effective_hours: 0.0 - name: Task D - planned_hours: 5.0 - project_id: project_project_projecta0 - remaining_hours: 5.0 - state: draft - total_hours: 5.0 - - delay_hours: 0.0 - effective_hours: 0.0 - name: Task C - planned_hours: 5.0 - project_id: project_project_projecta0 - remaining_hours: 5.0 - sequence: 11 - state: draft - total_hours: 5.0 - - delay_hours: 0.0 - effective_hours: 0.0 - name: Task B - planned_hours: 5.0 - project_id: project_project_projecta0 - remaining_hours: 5.0 - sequence: 13 - state: draft - total_hours: 5.0 - - delay_hours: 0.0 - effective_hours: 0.0 - name: Task A - planned_hours: 5.0 - project_id: project_project_projecta0 - remaining_hours: 5.0 - sequence: 14 - state: draft - total_hours: 5.0 -- - Now I create a record to schedule the tasks of project. -- - !record {model: project.compute.tasks, id: project_compute_tasks0}: - project_id: project_project_projecta0 -- - I schedule the tasks. -- - !python {model: project.compute.tasks}: | - self.compute_date(cr, uid, [ref("project_compute_tasks0")]) -- - I check that whether the tasks now allocated to respected resources or not. -- - !python {model: project.task}: | - task_ids = self.search(cr, uid, [('project_id','=',ref('project_project_projecta0'))]) - for task in self.browse(cr, uid, task_ids): - if (not task.date_start) or (not task.date_end): - raise AssertionError("Tasks are not scheduled.") From 8108d522e3eb6ccf80db6daaa4cf7a98f7414077 Mon Sep 17 00:00:00 2001 From: "Hemendra Paregi (Open ERP)" Date: Mon, 28 Nov 2011 15:49:52 +0530 Subject: [PATCH 028/117] [IMP]project_gtd: improvement in yml of project_gtd bzr revid: hpa@tinyerp.com-20111128101952-99qis8rd0l9kjkp4 --- addons/project_gtd/test/task_timebox.yml | 29 +++++++++++++----------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/addons/project_gtd/test/task_timebox.yml b/addons/project_gtd/test/task_timebox.yml index 7379f5857cf..84de7bda953 100644 --- a/addons/project_gtd/test/task_timebox.yml +++ b/addons/project_gtd/test/task_timebox.yml @@ -1,42 +1,45 @@ - - In order to set Daily tasks into Weekly Timebox, I create plan for that + In order to test the process of Timebox in Project Management module, + I set my task from Daily to Weekly Timebox through Plannify Timebox - !record {model: project.timebox.fill.plan, id: plan_id}: task_ids: [project.project_task_10] timebox_id: timebox_daily timebox_to_id: timebox_weekly - - I run plan to set Daily tasks into Weekly Timebox + I set the task from Daily Timebox to Weekly Timebox - !python {model: project.timebox.fill.plan}: | self.process(cr, uid, [ref("plan_id")]) - - I check Weekly Timebox of task after set Timebox + I check task is set to Weekly Timebox - !assert {model: project.task, id: project.project_task_10, string: Task should be set to weekly timebox}: - timebox_id.id == ref("timebox_weekly") - - I Empty the Daily Timebox + I Empty the Weekly Timebox - !python {model: project.timebox.empty}: | self._empty(cr, uid, {"active_model": "project.gtd.timebox", - "active_ids":[ref("timebox_daily")], - "active_id": ref("timebox_daily"), + "active_ids":[ref("timebox_weekly")], + "active_id": ref("timebox_weekly"), }) - - I check task 'Develop time management module' is no more in Daily Timebox + I check task 'Develop Module in Sale Management' is no more in Weekly Timebox - - !assert {model: project.task, id: project.project_task_10 , string: Task is not in Daily Timebox}: - - timebox_id.id != ref("timebox_daily") + !assert {model: project.task, id: project.project_task_10 , string: Task is not in Weekly Timebox }: + - timebox_id.id != ref("timebox_weekly") - I set Previous Timebox on task - !python {model: project.task}: | - self.prev_timebox(cr, uid, [ref("project.project_task_10")], - {'active_ids': [ref("project.project_task_1")],}) + previous_timebox = self.prev_timebox(cr, uid, [ref("project.project_task_10")], + {'active_ids': [ref("project_gtd.menu_open_gtd_timebox_tree")],}) + assert previous_timebox == True, "I set Previous Timebox on task" - I set Next Timebox on task - !python {model: project.task}: | - self.next_timebox(cr, uid, [ref("project.project_task_10")], - {'active_ids': [ref("project.project_task_1")],}) + nexts_timebox = self.next_timebox(cr, uid, [ref("project.project_task_10")], + {'active_ids': [ref("project_gtd.menu_open_gtd_timebox_tree")],}) + assert nexts_timebox == True, "I set Previous Timebox on task" \ No newline at end of file From fcce28a1d574f3a7e208d68f903a59180956379b Mon Sep 17 00:00:00 2001 From: "Hemendra Paregi (Open ERP)" Date: Mon, 28 Nov 2011 16:00:56 +0530 Subject: [PATCH 029/117] [IMP]project_gtd: yml improvement bzr revid: hpa@tinyerp.com-20111128103056-ldrcaujjik4zmwqd --- addons/project_gtd/test/task_timebox.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/project_gtd/test/task_timebox.yml b/addons/project_gtd/test/task_timebox.yml index 84de7bda953..8efa7219b21 100644 --- a/addons/project_gtd/test/task_timebox.yml +++ b/addons/project_gtd/test/task_timebox.yml @@ -40,6 +40,6 @@ I set Next Timebox on task - !python {model: project.task}: | - nexts_timebox = self.next_timebox(cr, uid, [ref("project.project_task_10")], + next_timebox = self.next_timebox(cr, uid, [ref("project.project_task_10")], {'active_ids': [ref("project_gtd.menu_open_gtd_timebox_tree")],}) - assert nexts_timebox == True, "I set Previous Timebox on task" \ No newline at end of file + assert next_timebox == True, "I set Next Timebox on task" \ No newline at end of file From 5ea00d2f0c270cd6315251f241d4c51674be9bfa Mon Sep 17 00:00:00 2001 From: "Harry (OpenERP)" Date: Mon, 28 Nov 2011 18:23:28 +0530 Subject: [PATCH 030/117] [IMP] project_long_term: improve YML test cases of phase bzr revid: hmo@tinyerp.com-20111128125328-vd4ovcibw844y0d7 --- addons/project_long_term/__openerp__.py | 4 +- .../project_long_term_demo.xml | 5 ++ .../test/draft2open2close_phase.yml | 40 ---------- .../project_long_term/test/phase_process.yml | 79 +++++++++++++++++++ .../test/schedule_project_phases.yml | 63 --------------- .../test/schedule_project_tasks.yml | 25 ------ 6 files changed, 85 insertions(+), 131 deletions(-) delete mode 100644 addons/project_long_term/test/draft2open2close_phase.yml create mode 100644 addons/project_long_term/test/phase_process.yml delete mode 100644 addons/project_long_term/test/schedule_project_phases.yml delete mode 100644 addons/project_long_term/test/schedule_project_tasks.yml diff --git a/addons/project_long_term/__openerp__.py b/addons/project_long_term/__openerp__.py index f4dd4637f0f..9c6e1410b41 100644 --- a/addons/project_long_term/__openerp__.py +++ b/addons/project_long_term/__openerp__.py @@ -43,9 +43,7 @@ Features "init_xml": [], "demo_xml": ["project_long_term_demo.xml"], "test": [ - 'test/schedule_project_phases.yml', - 'test/schedule_project_tasks.yml', - 'test/draft2open2close_phase.yml', + 'test/phase_process.yml', ], "update_xml": [ "security/ir.model.access.csv", diff --git a/addons/project_long_term/project_long_term_demo.xml b/addons/project_long_term/project_long_term_demo.xml index ac15249499e..4cd6d5cdec4 100644 --- a/addons/project_long_term/project_long_term_demo.xml +++ b/addons/project_long_term/project_long_term_demo.xml @@ -5,6 +5,10 @@ This Demo data file Human Resources, Phases and Resources,Tasks allocation and also run scheduling of phase and tasks. --> + + + + @@ -13,6 +17,7 @@ 30 + diff --git a/addons/project_long_term/test/draft2open2close_phase.yml b/addons/project_long_term/test/draft2open2close_phase.yml deleted file mode 100644 index 610ccb8180a..00000000000 --- a/addons/project_long_term/test/draft2open2close_phase.yml +++ /dev/null @@ -1,40 +0,0 @@ -- - I make "Collect Requirement and Make SRS" in open state. -- - !python {model: project.phase}: | - self.set_open(cr, uid, [ref("project_phase_1")]) -- - I check state of phase after put in open. -- - !assert {model: project.phase, id: project_phase_1, severity: error, string: Phase should be in open state}: - - state == "open" -- - I make Phase in pending state because of resource problem. -- - !python {model: project.phase}: | - self.set_pending(cr, uid, [ref("project_phase_1")]) -- - I check state of phase after put in pending. -- - !assert {model: project.phase, id: project_phase_1, severity: error, string: Phase should be in pending state}: - - state == "pending" -- - I make Phase in cancel state. -- - !python {model: project.phase}: | - self.set_cancel(cr, uid, [ref("project_phase_1")]) -- - I check state of phase after put in cancel. -- - !assert {model: project.phase, id: project_phase_1, severity: error, string: Phase should be in cancel state}: - - state == "cancelled" -- - I make Phase "Design Model" in done state. -- - !python {model: project.phase}: | - self.set_done(cr, uid, [ref("project_phase_2")]) -- - I check state of phase after put in done. -- - !assert {model: project.phase, id: project_phase_2, severity: error, string: Phase should be in done state}: - - state == "done" \ No newline at end of file diff --git a/addons/project_long_term/test/phase_process.yml b/addons/project_long_term/test/phase_process.yml new file mode 100644 index 00000000000..77d7b6bce1a --- /dev/null +++ b/addons/project_long_term/test/phase_process.yml @@ -0,0 +1,79 @@ +- + In order to test process of Phases, +- + I create a record to schedule the phase of project. +- + !record {model: project.compute.phases, id: project_compute_phases01}: + target_project: 'one' + project_id: project.project_integrate_openerp +- + I schedule the phases. +- + !python {model: project.compute.phases}: | + self.check_selection(cr, uid, [ref("project_compute_phases01")]) +- + I check the starting date and ending date on the phases after scheduling. +- + !python {model: project.project}: | + project = self.browse(cr, uid, ref("project.project_integrate_openerp"), context=context) + def _convert(date): + import time + return time.strptime(date, '%Y-%m-%d %H:%M:%S') + def _check(phase, _convert, _check): #TOFIX: why need to pass function ? + for next_phase in phase.next_phase_ids: + assert _convert(next_phase.date_start) >= _convert(phase.date_end), "Phase does not start in proper date." + _check(next_phase, _convert, _check) + return True + + for phase in project.phase_ids: + + assert phase.date_start, "Start date should be computed." + assert phase.date_end, "End date should be computed." + if not phase.previous_phase_ids and phase.constraint_date_start: + assert _convert(phase.date_start) >= _convert(phase.constraint_date_start), "Phase does not start in proper date." + _check(phase, _convert, _check) +- + I open phase. +- + !python {model: project.phase}: | + self.set_open(cr, uid, [ref("project_phase_1")]) +- + I check state of phase after opened. +- + !assert {model: project.phase, id: project_phase_1, severity: error, string: Phase should be in open state}: + - state == "open" +- + I put phase in pending state. +- + !python {model: project.phase}: | + self.set_pending(cr, uid, [ref("project_phase_1")]) +- + I check state of phase after put in pending. +- + !assert {model: project.phase, id: project_phase_1, severity: error, string: Phase should be in pending state}: + - state == "pending" +- + I make Phase in cancel state. +- + !python {model: project.phase}: | + self.set_cancel(cr, uid, [ref("project_phase_1")]) +- + I check state of phase after cancelled. +- + !assert {model: project.phase, id: project_phase_1, severity: error, string: Phase should be in cancel state}: + - state == "cancelled" +- + I put again in draft phase. +- + !python {model: project.phase}: | + self.set_draft(cr, uid, [ref("project_phase_1")]) +- + I close phase. +- + !python {model: project.phase}: | + self.set_done(cr, uid, [ref("project_phase_1")]) +- + I check state of phase after closed. +- + !assert {model: project.phase, id: project_phase_1, severity: error, string: Phase should be in done state}: + - state == "done" diff --git a/addons/project_long_term/test/schedule_project_phases.yml b/addons/project_long_term/test/schedule_project_phases.yml deleted file mode 100644 index c7a2addddb2..00000000000 --- a/addons/project_long_term/test/schedule_project_phases.yml +++ /dev/null @@ -1,63 +0,0 @@ -- - I Set working period to Project 'Integrate a Sale and Warehouse Management' -- - !python {model: project.project}: | - self.write(cr, uid, [ref("project.project_integrate_openerp")], {'resource_calendar_id': ref("resource.timesheet_group1")}) -- - I update the constrain and the "Collect Requirement and Make SRS" to not start before 4 days. -- - !python {model : project.phase }: | - pass - import datetime - from dateutil.relativedelta import * - start = datetime.date.today() + relativedelta(days=4) - self.write(cr,uid, [(ref("project_phase_1"))], {'constraint_date_start': start}) -- - I Schedule Phases of Project. -- - !python {model: project.project}: | - self.schedule_phases(cr, uid, ref("project.project_integrate_openerp")) -- - Now I create a record to compute the phase of project. -- - !record {model: project.compute.phases, id: project_compute_phases01}: - target_project: 'one' - project_id: project.project_integrate_openerp -- - I schedule the phases. -- - !python {model: project.compute.phases}: | - self.check_selection(cr, uid, [ref("project_compute_phases01")]) -- - Check if phases scheduled, check that either of phase's start_date, end_date and user_id is not null -- - !python {model: project.project}: | - prj=self.browse(cr, uid, [ref("project.project_integrate_openerp")])[0] - for phase in prj.phase_ids: - if (not phase.date_start) or (not phase.date_end): - raise AssertionError("Phase not scheduled") -- - After scheduling, I check the starting date and ending date on the phases are correct. -- - !python {model: project.phase}: | - import datetime - from dateutil.relativedelta import * - minstart = (datetime.date.today() + relativedelta(days=4)).strftime('%Y-%m-%d') - minend = (datetime.date.today() + relativedelta(days=5)).strftime('%Y-%m-%d') - - phase1=self.browse(cr, uid, ref('project_phase_1')) - assert phase1.date_start>=minstart, 'Error, the Collect Requirement and Make SRS phase '+phase1.date_start+' should start after '+str(minstart) - assert phase1.date_end>=minend, 'Error, the Collect Requirement and Make SRS phase should end after '+str(minend) - - phase2=self.browse(cr, uid, ref('project_phase_2')) - assert phase2.date_start>=phase1.date_end, 'Error, the phase Design Model should start after the end of the Collect Requirement and Make SRS phase' - - phase3=self.browse(cr, uid, ref('project_phase_3')) - assert phase3.date_start>=phase2.date_end, 'Error, the phase Development and Integration should start after the end of the Design Model phase' - - phase4=self.browse(cr, uid, ref('project_phase_4')) - assert phase4.date_start>=phase3.date_end, 'Error, the phase Review and Testing should start after the end of the Development and Integration phase' - - phase5=self.browse(cr, uid, ref('project_phase_5')) - assert phase5.date_start>=phase4.date_end, 'Error, the phase Deployement and Training start after the end of the Review and Testing phase' - assert phase5.date_start Date: Mon, 28 Nov 2011 18:25:47 +0530 Subject: [PATCH 031/117] [IMP] project_long_term: indetation in yml bzr revid: hmo@tinyerp.com-20111128125547-sy83re0c5vjb51sy --- addons/project_long_term/test/phase_process.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/project_long_term/test/phase_process.yml b/addons/project_long_term/test/phase_process.yml index 77d7b6bce1a..725c5b2a97d 100644 --- a/addons/project_long_term/test/phase_process.yml +++ b/addons/project_long_term/test/phase_process.yml @@ -41,7 +41,7 @@ I check state of phase after opened. - !assert {model: project.phase, id: project_phase_1, severity: error, string: Phase should be in open state}: - - state == "open" + - state == "open" - I put phase in pending state. - @@ -51,7 +51,7 @@ I check state of phase after put in pending. - !assert {model: project.phase, id: project_phase_1, severity: error, string: Phase should be in pending state}: - - state == "pending" + - state == "pending" - I make Phase in cancel state. - @@ -61,7 +61,7 @@ I check state of phase after cancelled. - !assert {model: project.phase, id: project_phase_1, severity: error, string: Phase should be in cancel state}: - - state == "cancelled" + - state == "cancelled" - I put again in draft phase. - From 6ced5c16c1b269f3820588156c0ba197c55e498e Mon Sep 17 00:00:00 2001 From: "Harry (OpenERP)" Date: Fri, 2 Dec 2011 12:57:55 +0530 Subject: [PATCH 032/117] [REF] purchase_requisition: purchase_requisition/wizard/purchase_requisition_partner.py * [REF] In create_order() method, move stuff of creating purchase order into 'purchase.requisition' object. purchase_requisition/purchase_requisition.py * [ADD] introduce new method: make_purchase_order() - to create new RFQ of specified supplier with plannned date, price bzr revid: hmo@tinyerp.com-20111202072755-e3ura2cmnh78utet --- .../purchase_requisition.py | 88 ++++++++++++++++- .../test/purchase_requisition.yml | 9 +- .../wizard/purchase_requisition_partner.py | 95 +------------------ 3 files changed, 95 insertions(+), 97 deletions(-) diff --git a/addons/purchase_requisition/purchase_requisition.py b/addons/purchase_requisition/purchase_requisition.py index 8570f4ba7bb..cc0956b8755 100644 --- a/addons/purchase_requisition/purchase_requisition.py +++ b/addons/purchase_requisition/purchase_requisition.py @@ -19,7 +19,8 @@ # along with this program. If not, see . # ############################################################################## - +from datetime import datetime +from dateutil.relativedelta import relativedelta import time import netsvc @@ -83,6 +84,89 @@ class purchase_requisition(osv.osv): self.write(cr, uid, ids, {'state':'done', 'date_end':time.strftime('%Y-%m-%d %H:%M:%S')}, context=context) return True + def _planned_date(self, requisition, delay=0.0): + company = requisition.company_id + date_planned = False + if requisition.date_start: + date_planned = datetime.strptime(requisition.date_start, '%Y-%m-%d %H:%M:%S') - relativedelta(days=company.po_lead) + else: + date_planned = datetime.today() - relativedelta(days=company.po_lead) + if delay: + date_planned -= relativedelta(days=delay) + return date_planned and date_planned.strftime('%Y-%m-%d %H:%M:%S') or False + + def _seller_details(self, cr, uid, requisition_line, supplier, context=None): + product_uom = self.pool.get('product.uom') + pricelist = self.pool.get('product.pricelist') + supplier_info = self.pool.get("product.supplierinfo") + product = requisition_line.product_id + default_uom_po_id = product.uom_po_id.id + qty = product_uom._compute_qty(cr, uid, requisition_line.product_uom_id.id, requisition_line.product_qty, default_uom_po_id) + seller_delay = 0.0 + seller_price = False + seller_qty = False + for product_supplier in product.seller_ids: + if supplier.id == product_supplier.name and qty >= product_supplier.qty: + seller_delay = product_supplier.delay + seller_qty = product_supplier.qty + supplier_pricelist = supplier.property_product_pricelist_purchase or False + seller_price = pricelist.price_get(cr, uid, [supplier_pricelist.id], product.id, qty, False, {'uom': default_uom_po_id})[supplier_pricelist.id] + if seller_qty: + qty = max(qty,seller_qty) + date_planned = self._planned_date(requisition_line.requisition_id, seller_delay) + return seller_price, qty, default_uom_po_id, date_planned + + def make_purchase_order(self, cr, uid, ids, partner_id, context=None): + """ + Create New RFQ for Supplier + """ + if context is None: + context = {} + assert partner_id, 'Supplier should be specified' + purchase_order = self.pool.get('purchase.order') + purchase_order_line = self.pool.get('purchase.order.line') + res_partner = self.pool.get('res.partner') + fiscal_position = self.pool.get('account.fiscal.position') + supplier = res_partner.browse(cr, uid, partner_id, context=context) + delivery_address_id = res_partner.address_get(cr, uid, [supplier.id], ['delivery'])['delivery'] + supplier_pricelist = supplier.property_product_pricelist_purchase or False + res = {} + for requisition in self.browse(cr, uid, ids, context=context): + if supplier.id in filter(lambda x: x, [rfq.state <> 'cancel' and rfq.partner_id.id or None for rfq in requisition.purchase_ids]): + raise osv.except_osv(_('Warning'), _('You have already one %s purchase order for this partner, you must cancel this purchase order to create a new quotation.') % supp_record.state) + location_id = requisition.warehouse_id.lot_input_id.id + purchase_id = purchase_order.create(cr, uid, { + 'origin': requisition.name, + 'partner_id': supplier.id, + 'partner_address_id': delivery_address_id, + 'pricelist_id': supplier_pricelist.id, + 'location_id': location_id, + 'company_id': requisition.company_id.id, + 'fiscal_position': supplier.property_account_position and supplier.property_account_position.id or False, + 'requisition_id':requisition.id, + 'notes':requisition.description, + 'warehouse_id':requisition.warehouse_id.id , + }) + res[requisition.id] = purchase_id + for line in requisition.line_ids: + product = line.product_id + seller_price, qty, default_uom_po_id, date_planned = self._seller_details(cr, uid, line, supplier, context=context) + taxes_ids = product.supplier_taxes_id + taxes = fiscal_position.map_tax(cr, uid, supplier.property_account_position, taxes_ids) + purchase_order_line.create(cr, uid, { + 'order_id': purchase_id, + 'name': product.partner_ref, + 'product_qty': qty, + 'product_id': product.id, + 'product_uom': default_uom_po_id, + 'price_unit': seller_price, + 'date_planned': date_planned, + 'notes': product.description_purchase, + 'taxes_id': [(6, 0, taxes)], + }, context=context) + + return res + purchase_requisition() class purchase_requisition_line(osv.osv): @@ -96,7 +180,7 @@ class purchase_requisition_line(osv.osv): 'product_uom_id': fields.many2one('product.uom', 'Product UoM'), 'product_qty': fields.float('Quantity', digits_compute=dp.get_precision('Product UoM')), 'requisition_id' : fields.many2one('purchase.requisition','Purchase Requisition', ondelete='cascade'), - 'company_id': fields.many2one('res.company', 'Company', required=True), + 'company_id': fields.related('requisition_id','company_id',type='many2one',relation='res.company',string='Company', store=True, readonly=True), } def onchange_product_id(self, cr, uid, ids, product_id,product_uom_id, context=None): diff --git a/addons/purchase_requisition/test/purchase_requisition.yml b/addons/purchase_requisition/test/purchase_requisition.yml index a2f9d5851d1..a2e5b743965 100644 --- a/addons/purchase_requisition/test/purchase_requisition.yml +++ b/addons/purchase_requisition/test/purchase_requisition.yml @@ -50,6 +50,7 @@ I check that the RFQ details which created for supplier. - !python {model: purchase.order}: | + purchase_requisition = self.pool.get("purchase.requisition") purchase_ids = self.search(cr, uid, [('requisition_id','=',ref("requisition1"))]) assert purchase_ids, "RFQ is not created." rfq = self.browse(cr, uid, purchase_ids[0], context=context) @@ -60,10 +61,10 @@ for rfq_line in rfq.order_line: for line in requisition.line_ids: if rfq_line.product_id.id == line.product_id.id: - product = line.product_id - uom_id = line.product_uom_id.id or False - assert rfq_line.product_qty == line.product_qty, "Quantity is not correspond." - assert rfq_line.product_uom.id == uom_id, "UOM is not correspond." + seller_price, qty, default_uom_po_id, date_planned = purchase_requisition._seller_details(cr, uid, line, supplier, context=context) + assert rfq_line.product_qty == qty, "Quantity is not correspond." + assert rfq_line.product_uom.id == default_uom_po_id, "UOM is not correspond." + assert rfq_line.price_unit == seller_price, "Unit Price is not correspond." - I confirmed RFQ which has best price. - diff --git a/addons/purchase_requisition/wizard/purchase_requisition_partner.py b/addons/purchase_requisition/wizard/purchase_requisition_partner.py index 3a758fc46a9..043ed749f4b 100644 --- a/addons/purchase_requisition/wizard/purchase_requisition_partner.py +++ b/addons/purchase_requisition/wizard/purchase_requisition_partner.py @@ -20,8 +20,6 @@ ############################################################################## import time -from datetime import datetime -from dateutil.relativedelta import relativedelta from osv import fields, osv from osv.orm import browse_record, browse_null from tools.translate import _ @@ -42,7 +40,7 @@ class purchase_requisition_partner(osv.osv_memory): tender = self.pool.get('purchase.requisition').browse(cr, uid, record_id, context=context) if not tender.line_ids: raise osv.except_osv(_('Error!'), _('No Product in Tender')) - True + return res def onchange_partner_id(self, cr, uid, ids, partner_id): if not partner_id: @@ -52,94 +50,9 @@ class purchase_requisition_partner(osv.osv_memory): return {'value':{'partner_address_id': addr['default']}} def create_order(self, cr, uid, ids, context=None): - """ - To Create a purchase orders . - - @param self: The object pointer. - @param cr: A database cursor - @param uid: ID of the user currently logged in - @param ids: the ID or list of IDs - @param context: A standard dictionary - @return: {} - - """ - if context is None: - context = {} - record_ids = context and context.get('active_ids', False) - if record_ids: - data = self.browse(cr, uid, ids,context=context)[0] - company = self.pool.get('res.users').browse(cr, uid, uid, context).company_id - order_obj = self.pool.get('purchase.order') - order_line_obj = self.pool.get('purchase.order.line') - partner_obj = self.pool.get('res.partner') - tender_line_obj = self.pool.get('purchase.requisition.line') - pricelist_obj = self.pool.get('product.pricelist') - prod_obj = self.pool.get('product.product') - tender_obj = self.pool.get('purchase.requisition') - acc_pos_obj = self.pool.get('account.fiscal.position') - partner_id = data.partner_id.id - supplier_data = data.partner_id - address_id = partner_obj.address_get(cr, uid, [partner_id], ['delivery'])['delivery'] - list_line=[] - purchase_order_line={} - for tender in tender_obj.browse(cr, uid, record_ids, context=context): - for supp_record in tender.purchase_ids: - if supp_record.partner_id.id == partner_id and supp_record.state <> 'cancel': - raise osv.except_osv(_('Warning'), _('You have already one %s purchase order for this partner, you must cancel this purchase order to create a new quotation.') % supp_record.state) - for line in tender.line_ids: - partner_list = sorted([(partner.sequence, partner) for partner in line.product_id.seller_ids if partner]) - partner_rec = partner_list and partner_list[0] and partner_list[0][1] or False - uom_id = line.product_id.uom_po_id and line.product_id.uom_po_id.id or False - - if tender.date_start: - newdate = datetime.strptime(tender.date_start, '%Y-%m-%d %H:%M:%S') - relativedelta(days=company.po_lead) - else: - newdate = datetime.today() - relativedelta(days=company.po_lead) - delay = partner_rec and partner_rec.delay or 0.0 - if delay: - newdate -= relativedelta(days=delay) - - partner = partner_rec and partner_rec.name or supplier_data - pricelist_id = partner.property_product_pricelist_purchase and partner.property_product_pricelist_purchase.id or False - price = pricelist_obj.price_get(cr, uid, [pricelist_id], line.product_id.id, line.product_qty, False, {'uom': uom_id})[pricelist_id] - product = prod_obj.browse(cr, uid, line.product_id.id, context=context) - location_id = self.pool.get('stock.warehouse').read(cr, uid, [tender.warehouse_id.id], ['lot_input_id'])[0]['lot_input_id'][0] - - purchase_order_line= { - 'name': product.partner_ref, - 'product_qty': line.product_qty, - 'product_id': line.product_id.id, - 'product_uom': uom_id, - 'price_unit': price, - 'date_planned': newdate.strftime('%Y-%m-%d %H:%M:%S'), - 'notes': product.description_purchase, - } - taxes_ids = line.product_id.product_tmpl_id.supplier_taxes_id - taxes = acc_pos_obj.map_tax(cr, uid, partner.property_account_position, taxes_ids) - purchase_order_line.update({ - 'taxes_id': [(6,0,taxes)] - }) - list_line.append(purchase_order_line) - purchase_id = order_obj.create(cr, uid, { - 'origin': tender.purchase_ids and tender.purchase_ids[0].origin or tender.name, - 'partner_id': partner_id, - 'partner_address_id': address_id, - 'pricelist_id': pricelist_id, - 'location_id': tender.purchase_ids and tender.purchase_ids[0].location_id.id or line.product_id.product_tmpl_id.property_stock_production.id, - 'company_id': tender.company_id.id, - 'fiscal_position': partner.property_account_position and partner.property_account_position.id or False, - 'requisition_id':tender.id, - 'notes':tender.description, - 'warehouse_id':tender.warehouse_id.id and tender.warehouse_id.id , - 'location_id':location_id, - 'company_id':tender.company_id.id, - }) - order_ids=[] - for order_line in list_line: - order_line.update({ - 'order_id': purchase_id - }) - order_line_obj.create(cr,uid,order_line) + active_ids = context and context.get('active_ids', []) + data = self.browse(cr, uid, ids, context=context)[0] + self.pool.get('purchase.requisition').make_purchase_order(cr, uid, active_ids, data.partner_id.id, context=context) return {'type': 'ir.actions.act_window_close'} purchase_requisition_partner() From 9ee2c1d66c13c50366503df087ac1c8ce649e037 Mon Sep 17 00:00:00 2001 From: "Vidhin Mehta (OpenERP)" Date: Wed, 7 Dec 2011 13:00:45 +0530 Subject: [PATCH 033/117] [fix]disable create button. lp bug: https://launchpad.net/bugs/900805 fixed bzr revid: vme@tinyerp.com-20111207073045-67n2zaizvyulu1lp --- addons/web/static/src/js/view_list.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js index de7dd1a77f5..626b7af6411 100644 --- a/addons/web/static/src/js/view_list.js +++ b/addons/web/static/src/js/view_list.js @@ -212,7 +212,7 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# this.$element.find('.oe-list-add') .click(this.do_add_record) - .attr('disabled', grouped && this.options.editable); + .attr('disabled', grouped && !this.options.editable); this.$element.find('.oe-list-delete') .attr('disabled', true) .click(this.do_delete_selected); From c4655794a1c688e100e85957f2940189f4d1e3a9 Mon Sep 17 00:00:00 2001 From: "Vidhin Mehta (OpenERP)" Date: Wed, 7 Dec 2011 18:22:00 +0530 Subject: [PATCH 034/117] [fix]fix code. bzr revid: vme@tinyerp.com-20111207125200-qhcbvs557cjerg4x --- addons/web/static/src/js/views.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js index db64865c266..93cf029731c 100644 --- a/addons/web/static/src/js/views.js +++ b/addons/web/static/src/js/views.js @@ -455,6 +455,9 @@ session.web.ViewManagerAction = session.web.ViewManager.extend(/** @lends oepner }, on_mode_switch: function (view_type) { var self = this; + if (!_.include(_.pluck(this.views_src,"view_type"),view_type)) + return; + return $.when( this._super(view_type), this.shortcut_check(this.views[view_type]) From b93b2f402587f30020675e7ee492bf62a0594611 Mon Sep 17 00:00:00 2001 From: "Vidhin Mehta (OpenERP)" Date: Thu, 8 Dec 2011 11:29:09 +0530 Subject: [PATCH 035/117] [fix]fix code according to suggestion. bzr revid: vme@tinyerp.com-20111208055909-coh3vxbbqxo7j250 --- addons/web/static/src/js/view_list.js | 2 +- addons/web/static/src/js/views.js | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js index 0025bd6e83c..6e62955f0b1 100644 --- a/addons/web/static/src/js/view_list.js +++ b/addons/web/static/src/js/view_list.js @@ -212,7 +212,7 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# this.$element.find('.oe-list-add') .click(this.do_add_record) - .attr('disabled', grouped && !this.options.editable); + .attr('disabled', grouped && this.options.editable); this.$element.find('.oe-list-delete') .attr('disabled', true) .click(this.do_delete_selected); diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js index f723c54da5d..2e595146d0d 100644 --- a/addons/web/static/src/js/views.js +++ b/addons/web/static/src/js/views.js @@ -243,12 +243,16 @@ session.web.ViewManager = session.web.Widget.extend(/** @lends session.web.View */ on_mode_switch: function(view_type, no_store) { var self = this, + view = this.views[view_type], view_promise; + if(!view) + return $.Deferred().reject(); + if (!no_store) { this.views_history.push(view_type); } this.active_view = view_type; - var view = this.views[view_type]; + if (!view.controller) { // Lazy loading of views var controllerclass = this.registry.get_object(view_type); @@ -471,8 +475,8 @@ session.web.ViewManagerAction = session.web.ViewManager.extend(/** @lends oepner }, on_mode_switch: function (view_type, no_store) { var self = this; - if (!_.include(_.pluck(this.views_src,"view_type"),view_type)) - return; + if (!(view_type in this.views)) + return $.Deferred().reject(); var switched = $.when(this._super(view_type, no_store)).then(function () { self.$element.find('.oe-view-manager-logs:first') From 2848db3c64defd5b483266d8993c794d641f42ad Mon Sep 17 00:00:00 2001 From: Minh Tran Date: Thu, 8 Dec 2011 18:56:37 +0100 Subject: [PATCH 036/117] Added some icons for the kanban modules bzr revid: mit@openerp.com-20111208175637-xn0dnldpolakluub --- addons/account_voucher/static/icon.png | Bin 0 -> 9306 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 addons/account_voucher/static/icon.png diff --git a/addons/account_voucher/static/icon.png b/addons/account_voucher/static/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..afad1331e2e0cec8386bf5fedca813f53323ccfe GIT binary patch literal 9306 zcmZ`9PI7W) zzR8(n@@10AnMA58%b+0>Awxkyp~=aD)c>*Ae?Wx)*H+p%ZT=&8GX)tC)W?4%zo#te zUjzv(tLO4hvGgCHB^a_i{|mZ<#jXCa*#F|>_R$0iirPpHB(CYXdhUaut7X-B(aQ7? zq>HDGBLxjD4iv`(K$kG~ct9Wb{N40PVq}m474vmPW`0$S;fUmLz)o7v{&X}sDSR{; zbNTk(!WT7S(fupO<#N*N!Y_Bp|MFn10%3+9^BKXt>EksR`xT~ z%paGv&yLHgy7LE@ddfbkR;mlU{6xECSE{pjlmh>k(BXCQC#me|>9iRwUCW%3KJ!D(VKw)XbF08ycJLr|Ud;HW#eU=i7{_>GlyL@q-C ztaYF+^Z+Ild1<$Uycrq=;OXF0Po;z&J8LC|x38uT8cGInEM@y9+bVD!2yn8rU#y!O zItKFashUm1CJTbG7pB)21avNPq%kh0Z5%Ipv>h+pqv<`mR&spW662NxUHDE&I;wac znAmjIrf4GQ92>1d#kAGg1y|K*3k1~vI_2iA&g)ufnU?otvah=3u@B1_q!SmjF~_pw zX%D3%R_!ToqFV)D^O_DURdtv1*wkr z5t07eF;~?(BC86UmY}b9#oUNh_1R-gB(iOwn2J-P*!R2QKHh9LK zS%Z^6m(W`Nti1@l=kwSKUhAnwN&gCLIz~GYN|@r2pEUrOsq{ zZx!h;WnkOiW*#_rQ@WVH-p?QP}oJlAz!taot&}&Q5De(KAHZ zKmw*Vytov7XHZZ?!1qS1?A~38f~*VVA-y`u(lz(rqr_&-99ZU7O=_u!C`Hsh{pXti zx!9TnZuJrMtT)}W%IHv$@P_STj>Gvhg^(->s-G}e4XFvT%|W0jG@6L-k#-1^6D|W- z`nbU^D_32=0cqC)y69=m*i|*3qwjMCa-gEi0 zX|Qko66x{DgMQt3Mrp)A*BZ12zAj9!4m4s7l6wAS#0eO5^Uy6y+2=oIC1t$D>&^8) zEk%FJPRaF#%kH=nd}_gpOVtHa)21c?CXdiRF=GnYvWXWTBM<4~y?`*KTKZr=w&$d(dP=87AdE)x?bxmS#9&BFK-UWKx zBY7@851b~G53Cld^5}-hOPKnTH9j{ctY^ig=URlgj}AhZ;K@jVU9&VmiGYZqn1bD+-u6l|);@#os@>Gg5nWn*;R92`u?WWzUZ?u)`?Apgs4ahn%n(Zd_>x8hD z$~e(+LeKIfGdgDh(ZdgSeu8&+t2+_}=fq;8(V#z;N1QW0J_;mGi6Y_O520S{9!OE| za)MJF2rA9Mqt>wqBeudE%6s6*5^(uU2r(n)3l9v99MTWjX8lmq(fcu%G;yhX&go*J z9c>lf-d7WXB^d#=1ZONicZ6-nnlQjGSO#P+kWw`;Q)6=Ghi|fs#t)8@y*nqyMJTPE z)$%C*h(=5$9E1yMYl_Pd>0c`!mOfP! zqcVhW^b2a+5QLKc%vUR|5K=LvJIddn<3h^*2$P7^xx>EAwiK8!<=^@>I; zMgaf<$NdW+IB55m1POFQEH9k<@zi~MZT>9F;0F=|*ZruO&yhj~t_N#7B$9!oB`iMK zY_4J$l8Mw_0o20~?BQOnXZf62Njb4v5Go4B(zx<+4yHLdH& zrL@Wo*pZ8E{OdoT+b`p{mukMQHJGTXE^9mT*YgYq)DMDnE*4y{*F4L5Qy z3t{`>myosZ2cG`*$mFOxdxMGkzC-N#;ax>#SJwol-DH31h_1##)FK6UPsayz>yY)B z7ajepl?6PZc5k9QW82}QC4=jPt8IDe3zgs77hHxE1zGG%to(8t61iS`xc6iXEn<46&biQ(XD zEF;{vCz;TrdAAM}y=OCW7b@Zy#jgD8tGxg`pcFp|QQ`*jU zt%7)rZ?R5wvp5*j2}G-;R~E?;?Q2nG9&GtN)X=FMFBIpWLQCk=%q<&nv~_CxSDS1b z9;m`ws6(6vhCa|2d;3nV7ufx`VB&Ly#XO|g**=K(N!u!FA0xV>N`|95Mg}gpNiTfE zHnWf-=%322ZqlTCyJX+B-q*m4)(Dw{Qa6|Ks#1<8MyOxE&76>L>wJ7&p~<7wdS+N+i0I?@r;BQw59| zcZUQ>UFzuIjpI&7s({_R@h#>3_wLv4>959_#y-`Yok_oE(n{lY?35JuZTB)g@3-oB z21e0joFFTxc`f?8x2=1go{R9t?w|Ln9CU;(Zb#epoF37D*BcwGsK#T`y4i4dapUHB z$J&2Bj}KB=V;Evpw2m#vSXXcqGR9Mtt^yi(N+W7`qzr2^5Z%5;)Nvgpg5_hpT`U$f z)E2RV<6x{f6=gPQ!mETiG|weRn>+h59cTdKf1saMg-8DYRR@8B}iV29>2Fh zJ6q#SK)94G{9p-R*fWblCqf0<)hfdUwRRUA3l~J~;}GmeWuX@z3kTy6!9&zk+oveG zo^#{@^svyL?w^5>w{jrFYbL(S{JwnZN($2w-PnM1$cwm$dl8*9RD{40aj+)NGwKLO z-s-r0D=+W`mhjPzB55>OJd9b0;OD@R!xPqS;2)yB zm5f-QztBd7Q9qoPgZ_Au&DAS%88!;)<3EAnIMSKPGz(IP}BDVZLN3mVr zZTq@V&S6tyk`l(9RV!vY*bEFkGKh5i<;WHJ9_0U&mUs2C^@a}lc-!i`^b5Z1Z4b4z zG6$DY$9xOJl+T*x&nsXP%F6F|qalC%3_W|u^mM{DpSZhaAI$LfG;wpiC2{TVUio5m zjz13ZoO_J{$B#pXQ8Dzl>Ys(l9!r;qRi1sN0H|P@-4~{D5D51D%9>=r z$DH5e5a)I92YBc+Q7XOjcH(kWd8J3f#;tIa%sajO$orm-n#aB9^<%iGX?0V=3BZG~ z9H#sT+}FYVWhcYatyWm=)(s|A9j*Sx^4)5IeApki1oFH+{;1RM<@6eF5xt%_{^6bi zE#fQnUby_R+p^&AJR44T8D16){pil0ju})oSm4Qt6Gl(1W|2Jm=uQO`?a_(!e=8&( zP#KYhMw@9tAHfs$XIR6PU^_&PJM=@E4|4Pa(g9BA=n0<0B2cFEtmT?$xLoN~z+yU; zwe>9SY%+|P!2E_-L{&oyS5ts0Q#K=SU(gb2J`40P1mxBGRqifC30}Pd&;8SODCZoL|>e`R?z-N zhLkPcTt9Bm{VwUE_^A~A42>XgNkeuAhy*^K@{>pWimdl2FE}Y|ZRfVGW1q4|NINfK zSS4KCXtB!)oGUDIKuFU7HWMAA&yAU)C8Y7g^_D|P5$5YC_VG_Z4I^B$=6#?U^N6Ls z5JD$i|C;y!Q`cEJi+(uU8+%w`iD^tc*d_IdKx9|d zYk04p+bz53)P&P-c=snw=_8JWB4iA-lmdi|e=x&w!qi40ZF7n3sr5daKYi@j0u*CE zF2`PTV>w_7uLeP=mH`BtP!OsPP8}GRuUi^+9$%hR$tfj~8wqskWuw?F<94;n z5W%Th$JoCH!cH}_;hm~XH0=yXZ;E_Q{i7CA0D{Web(3;Mz#k5n#T!Af4u`CW02YS7 zSrTH&<$&J4w7!>NEZ#L2+5A zDq^GzP0DL;nX{2~h?Cd)z{|1DR8?vjt5`tGxS~5}0+%Hko zSY~4_)Lx>Pgaj#5OA6q!I>d3K%q!j`Nv(D~H`g!%Ms_-qr!0cv+Y$LG4z<0gFd7X{ zvP4|6B`oZ#B^86nfCWxzMg@o)JpFK`Ni5_HPeM>nE?}(?<*HfYXo9~ z1T!$M@Tuu$a&#T2ZE z!LEm(NVGFlj7%pN@oz=0T)C0AP(!i*WUr-omeJ$SDp!JqyOH2}8TqjxVpuVT#G-66$dR@8;fFAAgU8%J7H(CbeP)YG!eG0=fIMBd>t`XWKL7r0m z9YLgHh2HbEGHq?%ghYA{770d;Wa^PJx73BSZ48n4z2mNHGh_M7peiA*IFbye1l^zS z7T8Bttx^;W^6u#l%~n&ql2m;uh!M@n(m@;2#RB%?ab3(&zWb^>5Nx;pDC;=YftBTr z->ByWMkeGC{Ju*-gHgV-JRAEkB7Jm$3|mw|+5&|!dVG|ui9Duds5S7<6IZWt#DL1> z(zd*eKv4C8X;l-v&9r7V+;~y$z)cNiVP6uDs#&n~O#p)r+>RU^ z_2x7pcs4~My@T7#o|kGx96qDAaqRC8$&4-KX9+3puumFv%SsihvFZf^@J*Wu$i@Ua zrw3P6j3!3xE0`R#S36?4S8tCBLeyrut&ikw6YNfOaP%w(CN5&ga_GMcUy?o}um|JC zLtwPWd8HVN>XxH$OhWkSrA(KvYYdCe-2*9Rv>ZoFTNa$dQ_}p7Tvd_#zmgQjIf`}X zpsGh6lf<7h2sB`)Kqvc2q<{s!@vZJHJf2^@$Gq*sB7ifV#GVw$Jy$T*WR|Bj#Y|@o zUK{Dt=dd8E0}<&FYQS{PbhSov(aqXEYXza#$+kgdE1tJnmTr!v@H1b*dgauCd`LP@ zf?X7jhox!E25%+60~z3;{bF@;Y1A?pfC&Dr7YT)pZkl=uwC~AC-waZ0vmg7r8OZ4m z_Z$9_if%l>Yyr$_!^T=_qe@_HS}1n3z>ax|(A!Jj=hL681T;c=d+(+fvh;!7M~R6^ zGpF!>4bKWCu!|^tWkHbgwWd^;ksI?nNx_7!@YutfiNu;Av>i z!Qgf^Z^X7w#EO;M?zQUj>ojN4JOTBLXLuctBPI2KwSMD6KGOJi*z|? z3m!-xluNotY*>%5CMJAGwlD1>L6(I(fbLSouM9e5Fyk{KJ<{Noh0`aPn(t3BOGKvo z3s2u;!ii&4EF}#S3Oj*1NsvLLTf#s!XaG=0IHg!=aICY)ulh}%JCe1dM576)*!9h% zQ#$Eeqm)Dm_If6$aTPN!1j@tw4)GE}HVk9~nv~Y^-v*>Z5i7}gk{Y404Yq)SxM39e zD9)C@4z1ctMNPQxtG=^5Xn?d5I8O#Yjs8IH#QIy1<~OO@%InoHZpijI#9$wejT2^# z%!)>pLGef5fcQSrbT^SF6$3K?q21P%tvbAD;}U3ko+-nc?JlrumhLfgqL9vz^!o|| zM|N3sflv=5*6>RVZiD;`($u(&8dkeZ`Vk9VpJ)6lD$5hDAP7($kOmDDW4z+r-}bQ} z4VvVm8jy#-erUu&b{@M;l|hoLrvrsX0lz8j$wrM6{h>~kac-$#pDX#Pn#UFcD!5{z ziCE~1Fo7RW63>tT;3vu>s*GUGWFDcn4HAQI(n(H=KAqj%bEvtdkMc`4c=}SKf=kvz zyrGZsn8ajkMo~G%KTD=q?n5)}4C07g33cO%6bB_02VqVqMKrDifky4ez+2*U#Q}{_ zw7p%qTd_0o^}q4ZRNJRmY^#35FqUB zhshG@&97vwz#(Qe?Ub#|V~*@8OIDvrZ?ZJvHjhzRt!LHfG5i==l!a-{sFV>v&8CY+ zUet0W*ohuk98|xT1(YmEIO`_WBNJ5nQ#H25;T$Eg<2q^Ns?K1TuSzf}5^(KHYREKO zv^y5?3zb1RApvwhv0YF%AmRn&twY&vpsI&PEC}M zKid9tg(w^9oVO7{`BOLlW8ZBfc;m>@RNz-t;eDQt)Ujw?ERU}r8j-89q)!-ai6F+u2m|MUm!6!k*%0LX1 z6JlL!UuBj%NiyEov2YaOkIYqb_o8873+}Jqtt^nD9)**Kf(_fv1szLWpCquPacq}q zz07lG!E@*7$jhR!U}3{`W#nOLRjGbfUAnDfhgn6_ePe&_J?u||G^^UQA0|Gg^G_T3 zuvtec22Gk~n?YVKt#-+oN7WG9Yr?eP339lsnwMXgw{AEe20*h0=mL<~(6v%T18%59 z=NfuK%os*815ags;A?*D>o&7ipdV5#fIdjLKMb60BF;`rfQ^n-{)){^ zqqv7OMm@%y@!5Q3paX^GaC(#7W15-8X533;RS=)&^RcW5BIlQv%UPTcyIl^u;^wh$ zu&KDZ4Erw(g?GiA8M_YL(iiX02DNBt_Z{o znCk{MA6T^{PgHn$h37v<0ul5cib5RJ1C&9$;=%dSs#q$?_RscI)wImCleCkb99|E) zw3L{3xpGDO*~e9B@{>lL)|x~~CzdW7+^uYt?jr3sd*Em{e|h&*Sjox> z^kV*TszD_jWU1b+auHQ&`}8p!!Sb{2gi7(LA9N7gq2#^`QWIi&DxQc)3aNVUo!oTP zML9nKxI*)%rc#z5We!{?}JCgoZ+}qMRyR3fHeIwiH(6Ii!O3~qKBx*hdEbjbIS-+i0_>Yz_SPq5U% zp$OC=73NrH%i(UCs%}q(0@E=-u#u2gQ=8!vPslJt;He_sVFb3{{@k#?RqM8_Mqk8# zF>2TapEX<5AQPvc({9#~c%dfRIs0DQSfzgLX3elJ=U4QbmMZA$7$Sq{_zA3KujW@Y z4L%-4yRCpPAj>Y9Gl`P}D$;i|M(Ut*nuZw@i+bDW7)-K-@G_yYpvpmft%g!|O}#mm z)Hh&j7F(Q+(g0Zyr+BWIQm+YDAT_hs={V%LA?DGb?dxH)mb!~ot*(G$|1O-%;$#Mw zL8P<-ZHCk*WpCRNtaD30W;E3&Td92HZv(&8NQ;N~6j{_5cU$#9Fl!)7e2vkYArQ{V z)k|c|za%MR-7wxg7M=|9s%VaogeLx+W4+$TXgd82UvGH$xiYnZnZNk?rdlFT9nmnrRHe9Dtr$S_$2nv0g*Cj zMi$u9dSc;r|J)-gSq$HrG=$U7t3g2c&mp6<^S{Qu8g>2mGRMW89bw<>X_gdvs&J~4 z&u>-kQ(w~_5NLJxZyQ(n-j~s<=DgW_&vf`J!BD_|a~JMbTiyCBAzg3+oOL(APJGVu z<WgWPPoJZ}U--pr0wVtu}PParjYOuToOrhpIx)kA-;+sswrE2rtV znq165VSuRL0f8 zUZ5egi_QU34ZMHC?CI6E555^2j0xZ}n>TlYq~%MfVvfE^4)pKef2Vbv0yKXaxmNZak}&h`J9oQOPCI2YoRT zOw0edW!*n!g0H^}r<03=oD#jO2KoVCyU3r+7dxu$C&z#-f&#=>d*PKM1DK; zT;#Nhs`ji$p)AvN^ee}-N5w%7FJ(c82^Pn19@ z;N3$!IE=@DHXnMNYpJw5u2L$beI^^p)NS(-;h)H-boB#KJDFiBgJ(m+=C;sci~3Yr z;cegFE>iQ!R;G{+vav~2GPxD*DxjW7zQWQ`cDyWB@L68M&7{@CtH|>Jcc`@Ogxu?< z4x1x59(OigJDcNs<~Z;1Q-i~^?ThoeCB!~T^JU`LdQq$Lc8QYs@%)UG`)3jT1m-a1 zD!Y!ck!Z=X9t+-v= zST!P9r?t?%7uu>}CbsKeLQhMP>8x>k2fGUkUs}PXb(^)cWkE_yn-jOmZyHiF4xkmg z(DT5Q;g2(>58L?TUCma_vx`-f!>Oy8<=*-}INo7NR#}WTi$U!da zbg9A+T-<6S92drgp{TLjM5b5tM_2889k4-FaYU%W@%0P&2MX0h-WrFr{O5mPZfISl zbX_e>T`dL7oh| zT}TAE{{)2pjiBN9)z!n)*%Hdb!-Lhv!Pdpx6l}@r=xmjBAw=}A6O^2kGN@L Date: Fri, 9 Dec 2011 11:21:46 +0530 Subject: [PATCH 037/117] [IMP]improved code. bzr revid: vme@tinyerp.com-20111209055146-sbj4z1fb203yknop --- addons/web/static/src/js/views.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js index 2e595146d0d..5d55fffd281 100644 --- a/addons/web/static/src/js/views.js +++ b/addons/web/static/src/js/views.js @@ -475,17 +475,15 @@ session.web.ViewManagerAction = session.web.ViewManager.extend(/** @lends oepner }, on_mode_switch: function (view_type, no_store) { var self = this; - if (!(view_type in this.views)) - return $.Deferred().reject(); var switched = $.when(this._super(view_type, no_store)).then(function () { self.$element.find('.oe-view-manager-logs:first') .addClass('oe-folded').removeClass('oe-has-more') .find('ul').empty(); + self.shortcut_check(self.views[view_type]) }); return $.when( - switched, - this.shortcut_check(this.views[view_type]) + switched ).then(function() { var controller = self.views[self.active_view].controller, fvg = controller.fields_view, From 89d3a64d49d1b11fefb6f7b7712e8b62ebbcedcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Fri, 9 Dec 2011 10:04:02 +0100 Subject: [PATCH 038/117] [IMP] just connect to livechat when the user clicks on the icon bzr revid: rlo@openerp.com-20111209090402-uagx12w1ixkktxeq --- .../static/src/js/web_livechat.js | 55 +++++++++++++++---- 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/addons/web_livechat/static/src/js/web_livechat.js b/addons/web_livechat/static/src/js/web_livechat.js index 13c4bbe28d4..5b5c4b3778e 100644 --- a/addons/web_livechat/static/src/js/web_livechat.js +++ b/addons/web_livechat/static/src/js/web_livechat.js @@ -22,6 +22,7 @@ var __lc_buttons = []; openerp.web_livechat = function (openerp) { + openerp.web_livechat.Livechat = openerp.web.Widget.extend({ template: 'Header-LiveChat', @@ -33,7 +34,17 @@ openerp.web_livechat.Livechat = openerp.web.Widget.extend({ var pwc = new openerp.web.Model(self.session, "publisher_warranty.contract"); pwc.get_func('get_default_livechat_text')().then(function(text) { self.$element.html(text); + console.log('receiving text', text); self.do_update(); + }).then(function() { + pwc.get_func('is_livechat_enable')().then(function(res) { + console.log('result', res); + if(res) { + self.$element.find('a').click(self.do_load_livechat); + } else { + self.do_action({type: 'ir.act.url', url: 'http://www.openerp.com/support-or-publisher-warranty-contract'}); + } + }) }); openerp.webclient.header.do_update.add_last(this.do_update); @@ -45,7 +56,14 @@ openerp.web_livechat.Livechat = openerp.web.Widget.extend({ self.$element.remove(); return; } - + }, + + do_load_livechat: function(evt) { + evt.preventDefault(); + var self = this; + + this.$element.find('Header_Livechat').unbind('click', this.do_load_livechat); + var lc_id = _.uniqueId('livechat_'); this.$element.attr('id', lc_id); @@ -56,6 +74,8 @@ openerp.web_livechat.Livechat = openerp.web.Widget.extend({ if(!res) { //return; } + // connect to LiveChat + __lc_load(); __lc_buttons.push({ elementId: lc_id, //'livechat_status', @@ -77,17 +97,28 @@ if (openerp.webclient) { params = '', lang = 'en', skill = '0'; - __lc_load = function (p) { if (typeof __lc_loaded != 'function') - if (p) { var d = document, l = d.createElement('script'), s = - d.getElementsByTagName('script')[0], a = unescape('%26'), - h = ('https:' == d.location.protocol ? 'https://' : 'http://'); l.type = 'text/javascript'; l.async = true; - l.src = h + 'gis' + p +'.livechatinc.com/gis.cgi?serverType=control'+a+'licenseID='+license+a+'jsonp=__lc_load'; - if (!(typeof p['server'] !== 'string' || typeof __lc_serv === 'string')) { - l.src = h + (__lc_serv = p['server']) + '/licence/'+license+'/script.cgi?lang='+lang+a+'groups='+skill; - l.src += (params == '') ? '' : a+'params='+encodeURIComponent(encodeURIComponent(params)); s.parentNode.insertBefore(l, s); - } else setTimeout(__lc_load, 1000); if(typeof __lc_serv != 'string'){ s.parentNode.insertBefore(l, s);} - } else __lc_load(Math.ceil(Math.random()*5)); } - __lc_load(); + __lc_load = function (p) { + if (typeof __lc_loaded != 'function') + if (p) { + var d = document, + l = d.createElement('script'), + s = d.getElementsByTagName('script')[0], + a = unescape('%26'), + h = ('https:' == d.location.protocol ? 'https://' : 'http://'); + l.type = 'text/javascript'; + l.async = true; + l.src = h + 'gis' + p +'.livechatinc.com/gis.cgi?serverType=control'+a+'licenseID='+license+a+'jsonp=__lc_load'; + if (!(typeof p['server'] !== 'string' || typeof __lc_serv === 'string')) { + l.src = h + (__lc_serv = p['server']) + '/licence/'+license+'/script.cgi?lang='+lang+a+'groups='+skill; + l.src += (params == '') ? '' : a+'params='+encodeURIComponent(encodeURIComponent(params)); + s.parentNode.insertBefore(l, s); + } else + setTimeout(__lc_load, 1000); + if(typeof __lc_serv != 'string'){ + s.parentNode.insertBefore(l, s); + } + } else __lc_load(Math.ceil(Math.random()*5)); + } // and add widget to webclient openerp.webclient.livechat = new openerp.web_livechat.Livechat(openerp.webclient); From 3cb695540e5c9a4eca303c26832fcb2b90599084 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 9 Dec 2011 12:14:04 +0100 Subject: [PATCH 039/117] [IMP] stop hiding left menu bzr revid: xmo@openerp.com-20111209111404-sp53qc4q3ff80n0q --- addons/web/static/src/js/chrome.js | 6 +----- addons/web_dashboard/static/src/js/dashboard.js | 6 ++---- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js index d4a9ccc45f1..3c212616496 100644 --- a/addons/web/static/src/js/chrome.js +++ b/addons/web/static/src/js/chrome.js @@ -838,9 +838,8 @@ openerp.web.Menu = openerp.web.Widget.extend(/** @lends openerp.web.Menu# */{ this._super(parent, element_id); this.secondary_menu_id = secondary_menu_id; this.$secondary_menu = $("#" + secondary_menu_id); - this.$secondary_menu.hide(); this.menu = false; - this.folded = true; + this.folded = false; if (window.localStorage) { this.folded = localStorage.getItem('oe_menu_folded') === 'true'; } @@ -912,9 +911,6 @@ openerp.web.Menu = openerp.web.Widget.extend(/** @lends openerp.web.Menu# */{ sub_menu_visible = $sub_menu.is(':visible'); this.$secondary_menu.find('.oe_secondary_menu').hide(); - if (this.$secondary_menu.hasClass('oe_folded')) { - this.$secondary_menu.show(); - } $('.active', this.$element.add(this.$secondary_menu)).removeClass('active'); $main_menu.add($clicked_menu).add($sub_menu).addClass('active'); diff --git a/addons/web_dashboard/static/src/js/dashboard.js b/addons/web_dashboard/static/src/js/dashboard.js index ed9cd467666..c717d629656 100644 --- a/addons/web_dashboard/static/src/js/dashboard.js +++ b/addons/web_dashboard/static/src/js/dashboard.js @@ -443,16 +443,14 @@ openerp.web_dashboard.ApplicationInstaller = openerp.web.Widget.extend({ action_buttons: false, sidebar: false, pager: false - }, + } }); - $('.secondary_menu', this.$element.closest('.openerp')).hide(); return r; }, stop: function() { - $('.secondary_menu', this.$element.closest('.openerp')).show(); this.action_manager.stop(); return this._super(); - }, + } }); From 89eb1140918c7389a2d67e189b96a8a5697cbe6b Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 9 Dec 2011 12:40:02 +0100 Subject: [PATCH 040/117] [ADD] API for immediate installation of modules (modules kanban view), buttons everywhere, remove weird kanban image fallback bzr revid: xmo@openerp.com-20111209114002-dlz79hxft05bhnqx --- openerp/addons/base/module/module.py | 14 +++++++++++++- openerp/addons/base/module/module_view.xml | 11 ++++------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/openerp/addons/base/module/module.py b/openerp/addons/base/module/module.py index 5db21282c65..a2fa5084c39 100644 --- a/openerp/addons/base/module/module.py +++ b/openerp/addons/base/module/module.py @@ -321,7 +321,19 @@ class module(osv.osv): def button_install(self, cr, uid, ids, context=None): self.state_update(cr, uid, ids, 'to install', ['uninstalled'], context) return dict(ACTION_DICT, name=_('Install')) - + + def button_immediate_install(self, cr, uid, ids, context=None): + """ Installs the selected module(s) immediately and fully, + returns the next res.config action to execute + + :param ids: identifiers of the modules to install + :returns: next res.config item to execute + :rtype: dict[str, object] + """ + self.state_update(cr, uid, ids, 'to install', ['uninstalled'], context) + cr.commit() + db, pool = pooler.restart_pool(cr.dbname, update_module=True) + return pool.get('res.config').next(db.cursor(), uid, [], context=context) def button_install_cancel(self, cr, uid, ids, context=None): self.write(cr, uid, ids, {'state': 'uninstalled', 'demo':False}) diff --git a/openerp/addons/base/module/module_view.xml b/openerp/addons/base/module/module_view.xml index 76aec91b98e..99468493814 100644 --- a/openerp/addons/base/module/module_view.xml +++ b/openerp/addons/base/module/module_view.xml @@ -70,8 +70,9 @@ + - +

@@ -79,13 +80,9 @@
Complex

- Install - + +
-
From 80de80c7dd0bccf2963faef39b29b668b28f039f Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 9 Dec 2011 12:53:16 +0100 Subject: [PATCH 041/117] [IMP] reduce noise in setting default values of module descriptor file bzr revid: xmo@openerp.com-20111209115316-2gqwmn2pi34vzu29 --- openerp/modules/module.py | 46 ++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/openerp/modules/module.py b/openerp/modules/module.py index 78f1f831920..4b9771636c7 100644 --- a/openerp/modules/module.py +++ b/openerp/modules/module.py @@ -231,9 +231,32 @@ def load_information_from_description_file(module): if terp_file: info = {} if os.path.isfile(terp_file) or zipfile.is_zipfile(mod_path+'.zip'): + # default values for descriptor + info = { + 'active': False, + 'application': False, + 'author': '', + 'category': 'Uncategorized', + 'certificate': None, + 'complexity': 'normal', + 'depends': [], + 'description': '', + 'icon': None, + 'installable': True, + 'license': 'AGPL-3', + 'name': False, + 'post_load': None, + 'version': '0.0.0', + 'web': False, + 'website': '', + } + info.update(itertools.izip( + 'depends data demo test init_xml update_xml demo_xml'.split(), + iter(list, None))) + terp_f = tools.file_open(terp_file) try: - info = eval(terp_f.read()) + info.update(eval(terp_f.read())) except Exception: logger.notifyChannel('modules', netsvc.LOG_ERROR, 'module %s: exception while evaluating file %s' % @@ -241,27 +264,6 @@ def load_information_from_description_file(module): raise finally: terp_f.close() - # TODO the version should probably be mandatory - info.setdefault('version', '0') - info.setdefault('category', 'Uncategorized') - info.setdefault('depends', []) - info.setdefault('author', '') - info.setdefault('website', '') - info.setdefault('name', False) - info.setdefault('description', '') - info.setdefault('complexity', 'normal') - info.setdefault('application', False) - info.setdefault('icon', 'images/icon.png') - info['certificate'] = info.get('certificate') or None - info['web'] = info.get('web') or False - info['license'] = info.get('license') or 'AGPL-3' - info.setdefault('installable', True) - info.setdefault('active', False) - # If the following is provided, it is called after the module is --loaded. - info.setdefault('post_load', None) - for kind in ['data', 'demo', 'test', - 'init_xml', 'update_xml', 'demo_xml']: - info.setdefault(kind, []) return info #TODO: refactor the logger in this file to follow the logging guidelines From c25475879c1f2af06899bcef8f9c32ced93bc192 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 9 Dec 2011 13:02:07 +0100 Subject: [PATCH 042/117] [IMP] opening and getting data from module description file bzr revid: xmo@openerp.com-20111209120207-3kkyvwedbjez29rl --- openerp/modules/module.py | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/openerp/modules/module.py b/openerp/modules/module.py index 4b9771636c7..899fa6efece 100644 --- a/openerp/modules/module.py +++ b/openerp/modules/module.py @@ -254,16 +254,9 @@ def load_information_from_description_file(module): 'depends data demo test init_xml update_xml demo_xml'.split(), iter(list, None))) - terp_f = tools.file_open(terp_file) - try: + with tools.file_open(terp_file) as terp_f: info.update(eval(terp_f.read())) - except Exception: - logger.notifyChannel('modules', netsvc.LOG_ERROR, - 'module %s: exception while evaluating file %s' % - (module, terp_file)) - raise - finally: - terp_f.close() + return info #TODO: refactor the logger in this file to follow the logging guidelines From b240363efd1ea603b04d8c8200353637dd1f27fb Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 9 Dec 2011 13:27:07 +0100 Subject: [PATCH 043/117] [ADD] dummy icons to edi and acocunt_accountant bzr revid: xmo@openerp.com-20111209122707-b62m8tw4hltu8ba7 --- .../account_accountant/static/src/img/icon.png | Bin 0 -> 1132 bytes addons/edi/__openerp__.py | 1 + addons/edi/static/src/img/knowledge.png | Bin 0 -> 948 bytes 3 files changed, 1 insertion(+) create mode 100644 addons/account_accountant/static/src/img/icon.png create mode 100644 addons/edi/static/src/img/knowledge.png diff --git a/addons/account_accountant/static/src/img/icon.png b/addons/account_accountant/static/src/img/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..611053684cca588d3a15317fc9535ed50fec19ec GIT binary patch literal 1132 zcmV-y1e5!TP)Tb9HrfczAeyeSL$2gN%%f zl9G~^mX@2Fo1&tks;a8Iyu8Q9#?{r;+}zyZ;o;`y=IQC_>gww5?(X#T^!WDm`T6+$ z{QME)Y|a1x00DGTPE!Ct=GbNc00VeQL_t(|+U=L=a-%pDM$q{aXZsF<|-12L?V$$Boc}I34WfA#MfuS=(jE6 zk$4E)KOBF|a-41)Td&til5oyLFh=9BXZ(yY!qfEnG{f`V!*qh zZ%MFe>ZU=3zTn5XD=FP25VcSNW@@p#oi1sD#9nrk;F@r`V2Q5o>)Q{IRHe3EW5Z%g z>-tt@A0cr{S&&jH0A+k8*%43aEA zPf>{lEk!WKq$ZTuPL{Y)V$YISX0=$ZMwWy=O_t=BCBahY)pBI9SS=TatH}~8qy}T{ zMGK^YNCnfV*!?VtBFSZo%WX!LaU4oMS#sotB-+^Qe|X(Vf}GxlB#z%rm%tgxZ%cXJ z1Hv|TrX(DbcVU#!*$hddc{sh^iAZ41O4f>VA*51Drj%4th8#&n8fwf`G1hsL%(%xR zV=Q6eSu0tus2FD}V!aL-WJ!Wh2qTKP(4CJkqB5W^R2&rN31*md*Eufkt$(po z)uirhq#Dv)q&oHM?|k2PiX_o_{Ex^ASs^QAg{+VjvO-qKV}X45@ZG7?;puD3A)kDE z>l8o%5g>haN6oJVAfNN&5BX5Ic!0!Lj*58l&Xkbtm#-IroE-xX;_1o$(?5Uz#v#tk zK#s4&-M??Wy3Co`2;bxP#m>z4#FjfV3%M^Z@_r3Ky~i2fo^$8MTgxDK?@t@D{rV}k z-z|j98S>I!|Ad#9dopdv7k=gSW$SXl_Y zj8;u2vG};M8fYm+J;{L1lvKzvW$cyovn0bDR0nmWP{fV~Y3VvZW9K%p2J`?KNqmeE6=9(D={uEu1r~8#uGj2tY1QzglyubT`URJU9m6BVkMgp`*oj^+XlCf zGScW3A=YdkomW*gZ2pMSM%jsk2UXB3Ktw~_ee`iXWTbwK?pnALi9zKmN+gJec=NO2 z#_v}BXxS5}D!rm7iZ{ErN0i);3yVvQKQ^09efh{HjF(Ug<8kHWj_+EIBRVy*Nl1t_ zBPDHehf$Vijgz{bvVM9&>Ns43=%9hBvz`6w(v;Ee<&V5;9&?NEQCmU5@i1; znEMOP1jL%{qw}xM;1qy2(|1FAc|kzf*>BU)nlWBO+{x`v{{*1^X8*hD*Jh$MmoCu| zZf7CW(V8`0bg+mod(1>@9wN!;g^%?g0xM*NtdJG5LRQHC6Y?(^ WR?AX;M{L>v0000 Date: Fri, 9 Dec 2011 13:28:03 +0100 Subject: [PATCH 044/117] [IMP] icon management in modules * If icon is present in descriptor file, use that path * Else try to find #{module}/static/src/img/icon.png * Else fallback on /base/static/src/img/icon.png bzr revid: xmo@openerp.com-20111209122803-elwonegpl8kut7pf --- .../static/src/img/{kanban_partner.png => icon.png} | Bin openerp/modules/module.py | 7 ++++++- 2 files changed, 6 insertions(+), 1 deletion(-) rename openerp/addons/base/static/src/img/{kanban_partner.png => icon.png} (100%) diff --git a/openerp/addons/base/static/src/img/kanban_partner.png b/openerp/addons/base/static/src/img/icon.png similarity index 100% rename from openerp/addons/base/static/src/img/kanban_partner.png rename to openerp/addons/base/static/src/img/icon.png diff --git a/openerp/modules/module.py b/openerp/modules/module.py index 899fa6efece..7f934275894 100644 --- a/openerp/modules/module.py +++ b/openerp/modules/module.py @@ -218,6 +218,11 @@ def get_module_resource(module, *args): return resource_path return False +def get_module_icon(module): + iconpath = ['static', 'src', 'img', 'icon.png'] + if get_module_resource(module, *iconpath): + return ('/' + module + '/') + '/'.join(iconpath) + return '/base/' + '/'.join(iconpath) def load_information_from_description_file(module): """ @@ -241,7 +246,7 @@ def load_information_from_description_file(module): 'complexity': 'normal', 'depends': [], 'description': '', - 'icon': None, + 'icon': get_module_icon(module), 'installable': True, 'license': 'AGPL-3', 'name': False, From 7010922d50f5e1e37f2050dbee1a6a5c7e6de4d7 Mon Sep 17 00:00:00 2001 From: "Yogesh (OpenERP)" Date: Fri, 9 Dec 2011 18:05:14 +0530 Subject: [PATCH 045/117] [FIX] clear value of date and datetime widget in search view on clear button. lp bug: https://launchpad.net/bugs/901665 fixed bzr revid: ysa@tinyerp.com-20111209123514-c54e5ea9tqjuc34s --- addons/web/static/src/js/search.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/addons/web/static/src/js/search.js b/addons/web/static/src/js/search.js index c3e27fc52be..0be95af2571 100644 --- a/addons/web/static/src/js/search.js +++ b/addons/web/static/src/js/search.js @@ -7,7 +7,7 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search /** * @constructs openerp.web.SearchView * @extends openerp.web.Widget - * + * * @param parent * @param element_id * @param dataset @@ -155,7 +155,7 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search var ext = new openerp.web.search.ExtendedSearch(this, this.model); lines.push([ext]); this.inputs.push(ext); - + var render = QWeb.render("SearchView", { 'view': data.fields_view['arch'], 'lines': lines, @@ -177,7 +177,7 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search $.when.apply(null, widget_starts).then(function () { self.ready.resolve(); }); - + this.reload_managed_filters(); }, reload_managed_filters: function() { @@ -409,6 +409,11 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search this.$element.find('table:last').hide(); $('.searchview_extended_groups_list').empty(); + _.each(this.inputs, function (input) { + if(input.datewidget && input.datewidget.value) { + input.datewidget.value = false; + } + }); setTimeout(this.on_clear, 0); }, /** @@ -1209,7 +1214,7 @@ openerp.web.search.ExtendedSearchProposition = openerp.web.OldWidget.extend(/** this.$element.find('.searchview_extended_prop_value').html( this.value.render({})); this.value.start(); - + }, get_proposition: function() { if ( this.attrs.selected == null) @@ -1356,7 +1361,7 @@ openerp.web.search.custom_filters = new openerp.web.Registry({ 'one2many': 'openerp.web.search.ExtendedSearchProposition.Char', 'many2one': 'openerp.web.search.ExtendedSearchProposition.Char', 'many2many': 'openerp.web.search.ExtendedSearchProposition.Char', - + 'datetime': 'openerp.web.search.ExtendedSearchProposition.DateTime', 'date': 'openerp.web.search.ExtendedSearchProposition.Date', 'integer': 'openerp.web.search.ExtendedSearchProposition.Integer', From 1feae8fa0c7e2c167cecac2f2c2af5aeec27fef0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Fri, 9 Dec 2011 14:19:29 +0100 Subject: [PATCH 046/117] modified according to review bzr revid: rlo@openerp.com-20111209131929-l672qxik23y4pka4 --- addons/web_livechat/static/src/js/web_livechat.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/web_livechat/static/src/js/web_livechat.js b/addons/web_livechat/static/src/js/web_livechat.js index 5b5c4b3778e..36fd79cd1fa 100644 --- a/addons/web_livechat/static/src/js/web_livechat.js +++ b/addons/web_livechat/static/src/js/web_livechat.js @@ -40,7 +40,7 @@ openerp.web_livechat.Livechat = openerp.web.Widget.extend({ pwc.get_func('is_livechat_enable')().then(function(res) { console.log('result', res); if(res) { - self.$element.find('a').click(self.do_load_livechat); + self.$element.click(self.do_load_livechat); } else { self.do_action({type: 'ir.act.url', url: 'http://www.openerp.com/support-or-publisher-warranty-contract'}); } @@ -62,7 +62,7 @@ openerp.web_livechat.Livechat = openerp.web.Widget.extend({ evt.preventDefault(); var self = this; - this.$element.find('Header_Livechat').unbind('click', this.do_load_livechat); + this.$element.unbind('click', this.do_load_livechat); var lc_id = _.uniqueId('livechat_'); this.$element.attr('id', lc_id); From f9e55d29af050480911c15940daa057bb7da6000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Fri, 9 Dec 2011 14:20:37 +0100 Subject: [PATCH 047/117] modified according to review bzr revid: rlo@openerp.com-20111209132037-d431geng6nfk00pp --- addons/web_livechat/static/src/js/web_livechat.js | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/web_livechat/static/src/js/web_livechat.js b/addons/web_livechat/static/src/js/web_livechat.js index 36fd79cd1fa..d082734c456 100644 --- a/addons/web_livechat/static/src/js/web_livechat.js +++ b/addons/web_livechat/static/src/js/web_livechat.js @@ -22,7 +22,6 @@ var __lc_buttons = []; openerp.web_livechat = function (openerp) { - openerp.web_livechat.Livechat = openerp.web.Widget.extend({ template: 'Header-LiveChat', From 76ec7bea0598373d26f3e80d805b9c46a78585eb Mon Sep 17 00:00:00 2001 From: "Vidhin Mehta (OpenERP)" Date: Fri, 9 Dec 2011 19:18:09 +0530 Subject: [PATCH 048/117] [IMP]used pipe instead of then, bzr revid: vme@tinyerp.com-20111209134809-l7rh0th8lgk5gz2i --- addons/web/static/src/js/views.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js index 0d8621ddd49..2237665a10d 100644 --- a/addons/web/static/src/js/views.js +++ b/addons/web/static/src/js/views.js @@ -498,16 +498,16 @@ session.web.ViewManagerAction = session.web.ViewManager.extend(/** @lends oepner }, on_mode_switch: function (view_type, no_store) { var self = this; - - var switched = $.when(this._super(view_type, no_store)).then(function () { + + var switched = $.when(this._super(view_type, no_store)).pipe(function () { + self.shortcut_check(self.views[view_type]); self.$element.find('.oe-view-manager-logs:first') .addClass('oe-folded').removeClass('oe-has-more') .find('ul').empty(); - self.shortcut_check(self.views[view_type]); }); return $.when( switched - ).then(function() { + ).pipe(function() { var controller = self.views[self.active_view].controller, fvg = controller.fields_view, view_id = (fvg && fvg.view_id) || '--'; From c3bbd5c2d7db7f46fe1535edaaf60e314f553cf0 Mon Sep 17 00:00:00 2001 From: Antony Lesuisse Date: Fri, 9 Dec 2011 15:28:39 +0100 Subject: [PATCH 049/117] [MERGE] manual outlook plugin no binary yet bzr revid: al@openerp.com-20111209142839-wffacq9r3ckjxi3s --- addons/crm/crm_lead.py | 5 +- addons/hr_recruitment/hr_recruitment.py | 5 +- addons/mail/mail_message.py | 5 + addons/mail/mail_thread.py | 8 + addons/outlook/README | 29 - addons/outlook/__openerp__.py | 4 +- addons/outlook/installer.py | 17 +- addons/outlook/outlook_installer.xml | 4 +- .../Register-plugin.bat | 2 - .../Unregister-plugin.bat | 2 - .../plugin/openerp-outlook-plugin/addin.py | 301 - .../plugin/openerp-outlook-plugin/chilkat.py | 5609 ----------------- .../dialogs/__init__.py | 83 - .../dialogs/dialog_map.py | 1810 ------ .../openerp-outlook-plugin/dialogs/dlgcore.py | 325 - .../dialogs/dlgutils.py | 20 - .../dialogs/opt_processors.py | 320 - .../dialogs/processors.py | 147 - .../dialogs/resources/OpenERP_Logo.bmp | Bin 80062 -> 0 bytes .../dialogs/resources/__init__.py | 32 - .../dialogs/resources/dialogs.h | 224 - .../dialogs/resources/dialogs.py | 13 - .../dialogs/resources/dialogs.rc | 339 - .../dialogs/resources/openerp_logo.png | Bin 11053 -> 0 bytes .../dialogs/resources/openerp_logo1.bmp | Bin 306 -> 0 bytes .../dialogs/resources/rc2py.py | 41 - .../dialogs/resources/rcparser.py | 379 -- .../plugin/openerp-outlook-plugin/eml.py | 95 - .../plugin/openerp-outlook-plugin/manager.py | 195 - .../plugin/openerp-outlook-plugin/setup.iss | 105 - .../openerp-outlook-plugin/tiny_xmlrpc.py | 573 -- .../OpenERPClient/Model.cs | 78 + .../OpenERPClient/OpenERPClient.csproj | 69 + .../OpenERPClient/OpenERPConnect.cs | 397 ++ .../OpenERPClient/Properties/AssemblyInfo.cs | 36 + .../OpenERPClient/Record.cs | 69 + .../OpenERPClient/XMLRPCClient.cs | 388 ++ .../OpenERPOutlookPlugin.sln | 36 + .../OpenERPOutlookPlugin/AssemblyInfo.cs | 52 + .../OpenERPOutlookPlugin/Cache.cs | 55 + .../OpenERPOutlookPlugin/ConfigManager.cs | 109 + .../OpenERPOutlookPlugin/Connect.cs | 354 ++ .../OpenERPOutlookPlugin.cs | 223 + .../OpenERPOutlookPlugin.csproj | 235 + .../OpenERPOutlookPlugin.csproj.user | 12 + .../Properties/Resources.Designer.cs | 119 + .../Properties/Resources.resx | 145 + .../Properties/Settings.Designer.cs | 26 + .../Properties/Settings.settings | 6 + .../195737_152643643962_3595480_n.jpg | Bin 0 -> 6784 bytes .../Resources/Account.ico | Bin 0 -> 1150 bytes .../Resources/Account.png | Bin 0 -> 897 bytes .../Resources/Archive.png | Bin 0 -> 852 bytes .../OpenERPOutlookPlugin/Resources/Case.png | Bin 0 -> 816 bytes .../Resources/Contact.png | Bin 0 -> 703 bytes .../OpenERPOutlookPlugin/Resources/Create.png | Bin 0 -> 888 bytes .../OpenERPOutlookPlugin/Resources/Error.gif | Bin 0 -> 1037 bytes .../Resources/Invoice.png | Bin 0 -> 852 bytes .../OpenERPOutlookPlugin/Resources/Move.gif | Bin 0 -> 155 bytes .../Resources/MoveDown.png | Bin 0 -> 352 bytes .../Resources/MoveLeft.png | Bin 0 -> 363 bytes .../Resources/OpenERP_icon.ico | Bin 0 -> 12862 bytes .../Resources/Partner.png | Bin 0 -> 790 bytes .../Resources/Product.png | Bin 0 -> 796 bytes .../Resources/Project.png | Bin 0 -> 823 bytes .../OpenERPOutlookPlugin/Resources/Sale.png | Bin 0 -> 802 bytes .../OpenERPOutlookPlugin/Resources/Search.gif | Bin 0 -> 582 bytes .../Resources/Success.gif | Bin 0 -> 604 bytes .../OpenERPOutlookPlugin/Resources/Task.png | Bin 0 -> 867 bytes .../Resources/developped_by.png | Bin 0 -> 7192 bytes .../OpenERPOutlookPlugin/Resources/logo.png | Bin 0 -> 3981 bytes .../Resources/openerp.png | Bin 0 -> 2611 bytes .../Resources/perform.gif | Bin 0 -> 89 bytes .../Resources/settings.png | Bin 0 -> 2455 bytes .../OpenERPOutlookPlugin/Tools.cs | 173 + .../frm_choose_document_opt.Designer.cs | 137 + .../frm_choose_document_opt.cs | 98 + .../frm_choose_document_opt.resx | 153 + .../OpenERPOutlookPlugin/frm_contact.cs | 77 + .../frm_contact.designer.cs | 166 + .../OpenERPOutlookPlugin/frm_contact.resx | 180 + .../frm_create_doc.Designer.cs | 127 + .../OpenERPOutlookPlugin/frm_create_doc.cs | 79 + .../OpenERPOutlookPlugin/frm_create_doc.resx | 145 + .../frm_openerp_configuration.Designer.cs | 334 + .../frm_openerp_configuration.cs | 216 + .../frm_openerp_configuration.resx | 455 ++ .../frm_openerp_connection.Designer.cs | 162 + .../frm_openerp_connection.cs | 79 + .../frm_openerp_connection.resx | 180 + .../OpenERPOutlookPlugin/frm_partner.cs | 77 + .../frm_partner.designer.cs | 106 + .../OpenERPOutlookPlugin/frm_partner.resx | 180 + .../OpenERPOutlookPlugin/frm_push_mail.cs | 149 + .../frm_push_mail.designer.cs | 202 + .../OpenERPOutlookPlugin/frm_push_mail.resx | 145 + .../frm_select_partner.Designer.cs | 141 + .../frm_select_partner.cs | 121 + .../frm_select_partner.resx | 194 + .../OpenERPOutlookPluginSetup.vdproj | 988 +++ addons/plugin/plugin_handler.py | 44 +- 101 files changed, 7529 insertions(+), 10680 deletions(-) delete mode 100644 addons/outlook/README delete mode 100644 addons/outlook/plugin/openerp-outlook-plugin/Register-plugin.bat delete mode 100644 addons/outlook/plugin/openerp-outlook-plugin/Unregister-plugin.bat delete mode 100644 addons/outlook/plugin/openerp-outlook-plugin/addin.py delete mode 100644 addons/outlook/plugin/openerp-outlook-plugin/chilkat.py delete mode 100644 addons/outlook/plugin/openerp-outlook-plugin/dialogs/__init__.py delete mode 100644 addons/outlook/plugin/openerp-outlook-plugin/dialogs/dialog_map.py delete mode 100644 addons/outlook/plugin/openerp-outlook-plugin/dialogs/dlgcore.py delete mode 100644 addons/outlook/plugin/openerp-outlook-plugin/dialogs/dlgutils.py delete mode 100644 addons/outlook/plugin/openerp-outlook-plugin/dialogs/opt_processors.py delete mode 100644 addons/outlook/plugin/openerp-outlook-plugin/dialogs/processors.py delete mode 100644 addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/OpenERP_Logo.bmp delete mode 100644 addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/__init__.py delete mode 100644 addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/dialogs.h delete mode 100644 addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/dialogs.py delete mode 100644 addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/dialogs.rc delete mode 100644 addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/openerp_logo.png delete mode 100644 addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/openerp_logo1.bmp delete mode 100644 addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/rc2py.py delete mode 100644 addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/rcparser.py delete mode 100644 addons/outlook/plugin/openerp-outlook-plugin/eml.py delete mode 100644 addons/outlook/plugin/openerp-outlook-plugin/manager.py delete mode 100644 addons/outlook/plugin/openerp-outlook-plugin/setup.iss delete mode 100644 addons/outlook/plugin/openerp-outlook-plugin/tiny_xmlrpc.py create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPClient/Model.cs create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPClient/OpenERPClient.csproj create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPClient/OpenERPConnect.cs create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPClient/Properties/AssemblyInfo.cs create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPClient/Record.cs create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPClient/XMLRPCClient.cs create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin.sln create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/AssemblyInfo.cs create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Cache.cs create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/ConfigManager.cs create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Connect.cs create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/OpenERPOutlookPlugin.cs create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/OpenERPOutlookPlugin.csproj create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/OpenERPOutlookPlugin.csproj.user create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Properties/Resources.Designer.cs create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Properties/Resources.resx create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Properties/Settings.Designer.cs create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Properties/Settings.settings create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Resources/195737_152643643962_3595480_n.jpg create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Resources/Account.ico create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Resources/Account.png create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Resources/Archive.png create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Resources/Case.png create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Resources/Contact.png create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Resources/Create.png create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Resources/Error.gif create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Resources/Invoice.png create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Resources/Move.gif create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Resources/MoveDown.png create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Resources/MoveLeft.png create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Resources/OpenERP_icon.ico create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Resources/Partner.png create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Resources/Product.png create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Resources/Project.png create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Resources/Sale.png create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Resources/Search.gif create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Resources/Success.gif create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Resources/Task.png create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Resources/developped_by.png create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Resources/logo.png create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Resources/openerp.png create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Resources/perform.gif create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Resources/settings.png create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/Tools.cs create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/frm_choose_document_opt.Designer.cs create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/frm_choose_document_opt.cs create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/frm_choose_document_opt.resx create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/frm_contact.cs create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/frm_contact.designer.cs create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/frm_contact.resx create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/frm_create_doc.Designer.cs create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/frm_create_doc.cs create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/frm_create_doc.resx create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/frm_openerp_configuration.Designer.cs create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/frm_openerp_configuration.cs create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/frm_openerp_configuration.resx create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/frm_openerp_connection.Designer.cs create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/frm_openerp_connection.cs create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/frm_openerp_connection.resx create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/frm_partner.cs create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/frm_partner.designer.cs create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/frm_partner.resx create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/frm_push_mail.cs create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/frm_push_mail.designer.cs create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/frm_push_mail.resx create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/frm_select_partner.Designer.cs create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/frm_select_partner.cs create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPlugin/frm_select_partner.resx create mode 100644 addons/outlook/static/openerp-outlook-plugin/OpenERPOutlookPluginSetup/OpenERPOutlookPluginSetup.vdproj diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py index 49272c97576..216a898bc88 100644 --- a/addons/crm/crm_lead.py +++ b/addons/crm/crm_lead.py @@ -748,10 +748,11 @@ class crm_lead(crm_case, osv.osv): self.write(cr, uid, [res_id], vals, context) return res_id - def message_update(self, cr, uid, ids, msg, vals={}, default_act='pending', context=None): + def message_update(self, cr, uid, ids, msg, vals=None, default_act='pending', context=None): if isinstance(ids, (str, int, long)): ids = [ids] - + if vals == None: + vals = {} super(crm_lead, self).message_update(cr, uid, ids, msg, context=context) if msg.get('priority') in dict(crm.AVAILABLE_PRIORITIES): diff --git a/addons/hr_recruitment/hr_recruitment.py b/addons/hr_recruitment/hr_recruitment.py index dbf0930c6bd..f81a2a8cd52 100644 --- a/addons/hr_recruitment/hr_recruitment.py +++ b/addons/hr_recruitment/hr_recruitment.py @@ -365,10 +365,11 @@ class hr_applicant(crm.crm_case, osv.osv): self.write(cr, uid, [res_id], vals, context) return res_id - def message_update(self, cr, uid, ids, msg, vals={}, default_act='pending', context=None): + def message_update(self, cr, uid, ids, msg, vals=None, default_act='pending', context=None): if isinstance(ids, (str, int, long)): ids = [ids] - + if vals is None: + vals = {} msg_from = msg['from'] vals.update({ 'description': msg['body_text'] diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index 159259f151d..fd00135816e 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -380,12 +380,16 @@ class mail_message(osv.osv): if 'To' in fields: msg['to'] = decode(msg_txt.get('To')) + if 'Delivered-To' in fields: msg['to'] = decode(msg_txt.get('Delivered-To')) if 'CC' in fields: msg['cc'] = decode(msg_txt.get('CC')) + if 'Cc' in fields: + msg['cc'] = decode(msg_txt.get('Cc')) + if 'Reply-To' in fields: msg['reply'] = decode(msg_txt.get('Reply-To')) @@ -455,6 +459,7 @@ class mail_message(osv.osv): msg['sub_type'] = msg['subtype'] or 'plain' return msg + def send(self, cr, uid, ids, auto_commit=False, context=None): """Sends the selected emails immediately, ignoring their current state (mails that have already been sent should not be passed diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index c8f7da9a5bb..70b536296bf 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -58,6 +58,14 @@ class mail_thread(osv.osv): 'message_ids': fields.one2many('mail.message', 'res_id', 'Messages', readonly=True), } + def message_capable_models(self, cr, uid, context=None): + ret_dict = {} + for model_name in self.pool.obj_list(): + model = self.pool.get(model_name) + if 'mail.thread' in getattr(model, '_inherit', []): + ret_dict[model_name] = model._description + return ret_dict + def message_thread_followers(self, cr, uid, ids, context=None): """Returns a list of email addresses of the people following this thread, including the sender of each mail, and the diff --git a/addons/outlook/README b/addons/outlook/README deleted file mode 100644 index 93f735ac1f8..00000000000 --- a/addons/outlook/README +++ /dev/null @@ -1,29 +0,0 @@ -OpenERP Outlook PLUG-IN Installation Guide - -Pre requirements : -====================================================================================== - 1.Python 2.6+ . python can be downloaded from http://www.python.org/download/releases/ . - 2.Python for Windows extensions - PyWin32 this module for python must be installed for appropriate version of the Python. It can be downloaded from - http://sourceforge.net/projects/pywin32/ or - http://starship.python.net/crew/mhammond/win32/ - 3.If you are using MS Outlook 2007 than you are required to install "Microsoft Exchange Server MAPI Client and Collaboration Data Objects 1.2.1 (CDO 1.21)". It can be downloaded from - http://www.microsoft.com/downloads/en/details.aspx?FamilyID=2714320D-C997-4DE1-986F-24F081725D36&displaylang=en - and With MS Outlook2003 Install inbuilt Collaboration Data Objects(CDO) while installing Outlook. - To read more regarding Collaboration Data Objects(CDO) click following link: - + http://support.microsoft.com/kb/171440 - -How to install openerp-outlook plug-in? -====================================================================================== - 1. Save the executable plug-in file. - 2. Close Outlook Application if Running. - 3. Run executable plug-in file and the folllow the instruction. - -How to uninstall openerp-outlook plug-in? -===================================================================================== - 1. Go to Control Panel Click "Add/Remove Programmes" - 2. You will entry, you will find entry named 'OpenERP Outlook Addin 1.0' select it and click Uninstall. - -Note : Plug In has been successfully tested with MS Office 2003 and MS Offcie 2007. - -Enjoy Archiving your Outlook E-mails to OpenERP. - diff --git a/addons/outlook/__openerp__.py b/addons/outlook/__openerp__.py index beab5aca648..9d1c5a554f4 100644 --- a/addons/outlook/__openerp__.py +++ b/addons/outlook/__openerp__.py @@ -25,7 +25,7 @@ 'version' : '1.0', 'author' : 'OpenERP SA', 'website' : 'http://www.openerp.com/', - 'depends' : ['base', 'mail'], + 'depends' : ['base', 'mail','plugin'], 'category' : 'Customer Relationship Management', 'description': ''' This module provides the Outlook Plug-in. @@ -33,7 +33,7 @@ This module provides the Outlook Plug-in. Outlook plug-in allows you to select an object that you’d like to add to your email and its attachments from MS Outlook. You can select a partner, a task, a project, an analytical account, or any other object and archive selected -mail into email.messages with attachments. +mail into mail.message with attachments. ''', 'init_xml' : [], 'demo_xml' : [], diff --git a/addons/outlook/installer.py b/addons/outlook/installer.py index 061c27da5e5..602afe0845d 100644 --- a/addons/outlook/installer.py +++ b/addons/outlook/installer.py @@ -32,7 +32,7 @@ class outlook_installer(osv.osv_memory): def default_get(self, cr, uid, fields, context=None): data = super(outlook_installer, self).default_get(cr, uid, fields, context=context) data['doc_file'] = 'http://doc.openerp.com/book/2/2_6_Comms/2_6_Comms_outlook.html' - file = open(addons.get_module_resource('outlook','plugin','openerp-outlook-addin.exe'), 'r') + file = open(addons.get_module_resource('outlook','plugin','openerp-outlook-plugin_v2.0','OpenERPOutlookPluginSetup','Release','OpenERPOutlookPluginSetup.msi'), 'r') data['plugin_file'] = base64.encodestring(file.read()) return data @@ -47,21 +47,18 @@ class outlook_installer(osv.osv_memory): _defaults = { 'outlook' : True, - 'name' : 'Openerp-Outlook-Addin.exe', + 'name' : 'OpenERPOutlookPlugin.msi', 'doc_name' : 'Installation Guide to OpenERP Outlook Plug-in.doc', 'description' : """ System requirements: - 1. Python 2.6+. - 2. Python for Windows extensions (PyWin32); this module must be installed for the appropriate version of Python. - 3.1 With MS Outlook 2007, install the package Collaboration Data Objects, version 1.2.1, http://www.microsoft.com/downloads/en/details.aspx?FamilyID=2714320D-C997-4DE1-986F-24F081725D36 - 3.2 With MS Outlook 2003, install the builtin Collaboration Data Objects(CDO) while installing Outlook. + 1. MS Outlook 2005 or above. + 2. MS .Net Framework 3.5 . + Plugin installation: - 1. Save the executable plug-in file. + 1. Save the msi plug-in file. 2. Close the Outlook application if it is open. - 3. Run the executable plug-in file, and follow the given instructions. - -Please refer to the README file for dependencies (external link: openobject-addons/outlook/README). + 3. Run the executable plug-in file (OpenERPOutlookPlugin.msi). """ } outlook_installer() diff --git a/addons/outlook/outlook_installer.xml b/addons/outlook/outlook_installer.xml index 7e2b7cd6d58..4cdb0127631 100644 --- a/addons/outlook/outlook_installer.xml +++ b/addons/outlook/outlook_installer.xml @@ -14,7 +14,9 @@ Install Outlook Plug-In - This plug-in allows you to link your e-mail to OpenERP's documents. You can attach it to any existing one in OpenERP or create a new one. + This plug-in allows you to create new contact or link contact to an existing partner. +Also allows to link your e-mail to OpenERP's documents. +You can attach it to any existing one in OpenERP or create a new one.