-
+
diff --git a/addons/mrp/mrp_workflow.xml b/addons/mrp/mrp_workflow.xml
index 3a8ec11b353..365c1195c44 100644
--- a/addons/mrp/mrp_workflow.xml
+++ b/addons/mrp/mrp_workflow.xml
@@ -136,7 +136,7 @@
subflow.cancel
-
+ subflow.done
diff --git a/addons/mrp/product.py b/addons/mrp/product.py
index c3f9ee855df..1bc3bb749ce 100644
--- a/addons/mrp/product.py
+++ b/addons/mrp/product.py
@@ -25,37 +25,9 @@ from tools.translate import _
class product_product(osv.osv):
_inherit = "product.product"
-
- def get_product_accounts(self, cr, uid, product_id, context=None):
- """ To get the stock input account, stock output account and stock journal related to product.
- @param product_id: product id
- @return: dictionary which contains information regarding stock input account, stock output account and stock journal
- """
- product_obj = self.pool.get('product.product').browse(cr, uid, product_id, False)
- res = super(product_product,self).get_product_accounts(cr, uid, product_id, context=context)
- stock_input_acc = product_obj.property_stock_account_input and product_obj.property_stock_account_input.id or False
- if not stock_input_acc:
- stock_input_acc = product_obj.categ_id.property_stock_account_input_categ and product_obj.categ_id.property_stock_account_input_categ.id or False
-
- stock_output_acc = product_obj.property_stock_account_output and product_obj.property_stock_account_output.id or False
- if not stock_output_acc:
- stock_output_acc = product_obj.categ_id.property_stock_account_output_categ and product_obj.categ_id.property_stock_account_output_categ.id or False
-
- journal_id = product_obj.categ_id.property_stock_journal and product_obj.categ_id.property_stock_journal.id or False
-
- res.update({'stock_account_input': stock_input_acc})
- res.update({'stock_account_output': stock_output_acc})
- res.update({'stock_journal': journal_id})
-
- return res
-
-
_columns = {
"bom_ids": fields.one2many('mrp.bom', 'product_id','Bill of Materials'),
}
-
-# Removed do_change_standard_price for the fix of lp:747056
-
def copy(self, cr, uid, id, default=None, context=None):
if not default:
default = {}
diff --git a/addons/mrp/test/cancel_order.yml b/addons/mrp/test/cancel_order.yml
new file mode 100644
index 00000000000..d10b8c1780b
--- /dev/null
+++ b/addons/mrp/test/cancel_order.yml
@@ -0,0 +1,25 @@
+-
+ I first confirm order for shirt.
+-
+ !workflow {model: mrp.production, action: button_confirm, ref: mrp_production_shirt}
+-
+ In order to cancel the production order, I first cancel its picking.
+-
+ !function {model: stock.picking, name: action_cancel}:
+ - model: mrp.production
+ eval: "[obj(ref('mrp_production_shirt')).picking_id.id]"
+-
+ Now I cancel the production order.
+-
+ !workflow {model: mrp.production, action: button_cancel, ref: mrp_production_shirt}
+-
+ Now I check that the production order is cancelled.
+-
+ !assert {model: mrp.production, id: mrp_production_shirt}:
+ - state == 'cancel'
+-
+ I remove cancelled production order.
+-
+ !python {model: mrp.production}: |
+ order = self.browse(cr, uid, ref("mrp_production_shirt"), context=context)
+ self.unlink(cr, uid, [order.id])
diff --git a/addons/mrp/test/mrp_packs.yml b/addons/mrp/test/mrp_packs.yml
deleted file mode 100644
index 800d4f56476..00000000000
--- a/addons/mrp/test/mrp_packs.yml
+++ /dev/null
@@ -1,103 +0,0 @@
--
- In order to test the Packs in OpenERP, we will try to sell a "Pack of 24
- beers" which is composed of 24 "Beers" and a "Beers Pack".
--
- I start by creating the Beers product.
--
- !record {model: product.product, id: product_product_beers0}:
- categ_id: product.cat1
- name: Beers
- procure_method: make_to_stock
- seller_ids:
- - delay: 1
- name: base.res_partner_agrolait
- min_qty: 2.0
- supply_method: buy
- type: product
- uom_id: product.product_uom_unit
- uom_po_id: product.product_uom_unit
--
- I create the "Beers Pack" product.
--
- !record {model: product.product, id: product_product_beerspack0}:
- categ_id: product.cat1
- name: Beers Pack
- procure_method: make_to_stock
- seller_ids:
- - delay: 1
- name: base.res_partner_asus
- min_qty: 2.0
- supply_method: buy
- type: product
- uom_id: product.product_uom_unit
- uom_po_id: product.product_uom_unit
--
- I create the "Pack of 24 beers" product
--
- !record {model: product.product, id: product_product_packofbeers0}:
- categ_id: product.cat1
- name: Pack of 24 Beers
- procure_method: make_to_order
- supply_method: produce
- type: product
- uom_id: product.product_uom_unit
- uom_po_id: product.product_uom_unit
--
- I define the Phantom Bill of Material for the "Pack of 24 beers"
--
- !record {model: mrp.bom, id: mrp_bom_packofbeers0}:
- bom_lines:
- - company_id: base.main_company
- name: Beers
- product_id: product_product_beers0
- product_qty: 24.0
- product_uom: product.product_uom_unit
- type: normal
- - company_id: base.main_company
- name: Beers Pack
- product_id: product_product_beerspack0
- product_qty: 1.0
- product_uom: product.product_uom_unit
- type: normal
- name: Pack of 24 Beers
- product_id: product_product_packofbeers0
- product_qty: 1.0
- product_uom: product.product_uom_unit
- type: phantom
--
- As all my data are created, I will create an outgoing order picking for a
- "Pack of 24 Beers"
--
- !record {model: stock.picking, id: picking_out}:
- address_id: base.res_partner_address_tang
- company_id: base.main_company
- invoice_state: none
- move_lines:
- - company_id: base.main_company
- location_dest_id: stock.stock_location_customers
- location_id: stock.stock_location_stock
- name: Pack of 24 Beers
- product_id: product_product_packofbeers0
- product_qty: 2.0
- product_uom: product.product_uom_unit
- move_type: direct
- type: out
--
- I validate the newly created picking.
--
- !python {model: stock.picking}: |
- self.draft_validate(cr, uid, [ref("picking_out")], {
- "active_ids": [ref("stock.menu_action_picking_tree")],
- "active_id": ref("stock.menu_action_picking_tree"), }
- )
--
- I check that my Picking of a "Pack of 24 beers" has been automatically
- converted to a picking of 24 beers and a pack of beer, so that my
- stock of beers remains exact.
--
- !assert {model: stock.picking, id: picking_out, string: pack_of_beer_splitted}:
- - len(move_lines) >= 2
- - move_lines[0].product_id.id <> move_lines[1].product_id.id
- - move_lines[0].product_id.id in (ref('product_product_beers0'), ref('product_product_beerspack0'))
- - move_lines[1].product_id.id in (ref('product_product_beers0'), ref('product_product_beerspack0'))
-
diff --git a/addons/mrp/test/mrp_phantom_bom.yml b/addons/mrp/test/mrp_phantom_bom.yml
deleted file mode 100644
index ca29b24ea23..00000000000
--- a/addons/mrp/test/mrp_phantom_bom.yml
+++ /dev/null
@@ -1,273 +0,0 @@
--
- In order to test the mrp phantom bom type in OpenERP, I will create products
- and then I will create Phantom bom structure for those products.
--
- I create BOM category fluid for Orange Juice
--
- !record {model: product.uom.categ, id: product_uom_categ_fluid}:
- name: Fluid
--
- I create the products required to produce some orange juices with Oranges, Sugar and Water.
--
- !record {model: product.uom, id: product_uom_litre0}:
- category_id: product_uom_categ_fluid
- factor: 1.0
- name: Litre
- rounding: 0.01
--
- I create record for product Orange Juice.
--
- !record {model: product.product, id: product_product_orangejuice0}:
- categ_id: product.cat1
- name: Orange Juice
- procure_method: make_to_order
- supply_method: produce
- type: product
- uom_id: product_uom_litre0
- uom_po_id: product_uom_litre0
- property_stock_inventory: stock.location_inventory
- property_stock_procurement: stock.location_procurement
- property_stock_production: stock.location_production
--
- I create record for product Orange.
--
- !record {model: product.product, id: product_product_orange0}:
- categ_id: product.cat1
- name: Orange
- procure_method: make_to_stock
- seller_ids:
- - delay: 1
- name: base.res_partner_asus
- min_qty: 1.0
- product_uom: product.product_uom_kgm
- supply_method: buy
- type: product
- uom_id: product.product_uom_kgm
- uom_po_id: product.product_uom_kgm
- property_stock_inventory: stock.location_inventory
- property_stock_procurement: stock.location_procurement
- property_stock_production: stock.location_production
--
- I create record for product Sugar.
--
- !record {model: product.product, id: product_product_sugar0}:
- categ_id: product.cat1
- name: Sugar
- procure_method: make_to_stock
- seller_ids:
- - delay: 1
- name: base.res_partner_desertic_hispafuentes
- min_qty: 2.0
- product_uom: product.product_uom_kgm
- supply_method: buy
- type: product
- uom_id: product.product_uom_kgm
- uom_po_id: product.product_uom_kgm
- property_stock_inventory: stock.location_inventory
- property_stock_procurement: stock.location_procurement
- property_stock_production: stock.location_production
--
- I create record for product Water.
--
- !record {model: product.product, id: product_product_water0}:
- categ_id: product.cat1
- name: Water
- procure_method: make_to_order
- seller_ids:
- - delay: 1
- name: base.res_partner_agrolait
- product_uom: product_uom_litre0
- min_qty: 2.0
- supply_method: buy
- type: consu
- uom_id: product_uom_litre0
- uom_po_id: product_uom_litre0
- property_stock_inventory: stock.location_inventory
- property_stock_procurement: stock.location_procurement
- property_stock_production: stock.location_production
--
- I define the BoM to produce an orange juice.
--
- !record {model: mrp.bom, id: mrp_bom_orangejuice0}:
- company_id: base.main_company
- name: Orange Juice
- product_efficiency: 1.0
- product_id: product_product_orangejuice0
- product_qty: 1.0
- product_uom: product_uom_litre0
- type: phantom
--
- changes UOM and name if product change.
--
- !python {model: mrp.bom}: |
- production_id = self.browse(cr, uid, [ref('mrp_bom_orangejuice0')], context=context)[0]
- self.onchange_product_id(cr, uid, [ref('mrp_bom_orangejuice0')], production_id.product_id.id, False)
--
- I create bom lines for BoM for Orange Juice.
--
- !record {model: mrp.bom, id: mrp_bom_orangejuice0}:
- bom_lines:
- - bom_id: mrp_bom_orangejuice0
- company_id: base.main_company
- name: Orange
- product_efficiency: 1.0
- product_id: product_product_orange0
- product_qty: 0.5
- product_uom: product.product_uom_kgm
- type: normal
- - bom_id: mrp_bom_orangejuice0
- company_id: base.main_company
- name: Sugar
- product_efficiency: 1.0
- product_id: product_product_sugar0
- product_qty: 0.02
- product_uom: product.product_uom_kgm
- type: normal
- - bom_id: mrp_bom_orangejuice0
- company_id: base.main_company
- name: Water
- product_efficiency: 1.0
- product_id: product_product_water0
- product_qty: 0.80000000000000004
- product_uom: product_uom_litre0
- type: normal
--
- I define Minimum stock rules for my stockable product "Orange".
--
- !record {model: stock.warehouse.orderpoint, id: stock_warehouse_orderpoint_op0}:
- company_id: base.main_company
- location_id: stock.stock_location_stock
- logic: max
- name: OP/00002
- product_id: product_product_orange0
- product_max_qty: 10.0
- product_min_qty: 5.0
- product_uom: product.product_uom_kgm
- qty_multiple: 1
- warehouse_id: stock.warehouse0
--
- I define Minimum stock rules for my stockable product "Sugar".
--
- !record {model: stock.warehouse.orderpoint, id: stock_warehouse_orderpoint_op1}:
- company_id: base.main_company
- location_id: stock.stock_location_stock
- logic: max
- name: OP/00003
- product_id: product_product_sugar0
- product_max_qty: 4.0
- product_min_qty: 2.0
- product_uom: product.product_uom_kgm
- qty_multiple: 1
- warehouse_id: stock.warehouse0
--
- I want to produce 100 litres of Orange juice. I am creating a manufacturing order for this.
- I want to see how much quantities of sub products I need, to produce the Orange juice.
--
- I compute the data. I get the bill of material of Orange juice and list of
- scheduled products according to my bom.
--
- !record {model: mrp.production, id: mrp_production_mo0}:
- company_id: base.main_company
- date_planned: !eval datetime.today().strftime("%Y-%m-%d %H:%M:%S")
- location_dest_id: stock.stock_location_output
- location_src_id: stock.stock_location_stock
- product_id: product_product_orangejuice0
- product_qty: 100.0
- product_uom: product_uom_litre0
--
- Creating an mrp.production record. Computing Bills of materials.
--
- !record {model: mrp.production, id: mrp_production_mo0}:
- bom_id: mrp.mrp_bom_orangejuice0
- date_planned: !eval datetime.today().strftime("%Y-%m-%d %H:%M:%S")
- location_dest_id: stock.stock_location_output
- location_src_id: stock.stock_location_stock
- product_id: mrp.product_product_orangejuice0
- product_lines:
- - name: Orange
- product_id: mrp.product_product_orange0
- product_qty: 50.0
- product_uom: product.product_uom_kgm
- production_id: mrp_production_mo0
- - name: Sugar
- product_id: mrp.product_product_sugar0
- product_qty: 2.0
- product_uom: product.product_uom_kgm
- production_id: mrp_production_mo0
- - name: Water
- product_id: mrp.product_product_water0
- product_qty: 80.0
- product_uom: mrp.product_uom_litre0
- production_id: mrp_production_mo0
- product_qty: 100.0
- product_uom: mrp.product_uom_litre0
--
- I confirm the order.
--
- !workflow {model: mrp.production, action: button_confirm, ref: mrp_production_mo0}
--
- I am checking Procurement orders. There are 3 orders generated for Oranges, Sugar and Water.
--
- !python {model: procurement.order}: |
- proc_ids = self.search(cr, uid, [('product_id','in',[ref('product_product_orange0'),ref('product_product_sugar0'),ref('product_product_water0')])])
- assert proc_ids, 'No Procurements!'
--
- The scheduler runs.
--
- !function {model: procurement.order, name: run_scheduler}:
- - model: procurement.order
- search: "[]"
--
- I am checking Internal picking. I see one picking for Orange juice and its
- stock moves for Oranges, Sugar and Water made correctly.
--
- !python {model: stock.picking}: |
- pick_ids = self.search(cr, uid, [('type','=','internal')])
- assert pick_ids, 'No Internal Pickings!'
--
- According to minimum stock rules. I have 2 purchase orders for
- Sugar with 6 Kg from Axelor and Orange 60 Kg from ASUStek.
--
- I confirm the purchase order of Sugar and Orange.
--
- !python {model: purchase.order}: |
- import netsvc
- purch_ids = self.search(cr, uid, [('state','=','draft')])
- assert purch_ids, 'No Purchase Orders were made!'
- wf_service = netsvc.LocalService("workflow")
- for p_id in purch_ids:
- wf_service.trg_validate(uid, 'purchase.order', p_id, 'purchase_confirm', cr)
--
- I see two incoming pickings for Orange and Sugar, and receive them.
--
- !python {model: stock.picking}: |
- pick_ids = self.search(cr, uid, [('type','=','in')])
- assert pick_ids, 'No Incoming Shipments found!'
- stock_partial_picking = self.pool.get('stock.partial.picking')
- for pick_id in pick_ids:
- partial_id = stock_partial_picking.create(cr, uid, {},
- context={'active_model': 'stock.picking',
- 'active_ids': [pick_id]})
- stock_partial_picking.do_partial(cr, uid, [partial_id])
--
- Again the scheduler runs.
--
- !function {model: procurement.order, name: run_scheduler}:
- - model: procurement.order
- search: "[]"
--
- I check my internal picking of "Orange Juice" is done.
--
- !python {model: stock.picking}: |
- pick_ids = self.search(cr, uid, [('type','=','internal'),('state','=','done')])
- assert pick_ids, 'Internal Picking is not done yet!'
--
- I check my manufacturing order for "Orange Juice" is ready or not.
--
- !python {model: mrp.production}: |
- prod_ids = self.search(cr, uid, [('state','=','ready'),('id','=',ref('mrp_production_mo0'))])
- assert prod_ids, 'Manufacturing order is not ready!'
--
- I start the production order.
--
- !workflow {model: mrp.production, action: button_produce, ref: mrp_production_mo0}
diff --git a/addons/mrp/test/mrp_procurement.yml b/addons/mrp/test/mrp_procurement.yml
deleted file mode 100644
index f5bcf4f767a..00000000000
--- a/addons/mrp/test/mrp_procurement.yml
+++ /dev/null
@@ -1,278 +0,0 @@
--
- In order to test the flow of procurement orders. I will put some orders with
- different procurement methods. I have installed sale, mrp and purchase modules.
--
- I am creating products.
--
- I create record for product Shirt.
--
- !record {model: product.product, id: product_product_shirt0}:
- categ_id: product.cat1
- cost_method: standard
- list_price: 350.0
- mes_type: fixed
- name: Shirt
- procure_method: make_to_stock
- property_stock_inventory: stock.location_inventory
- property_stock_procurement: stock.location_procurement
- property_stock_production: stock.location_production
- seller_delay: '1'
- standard_price: 300.0
- supply_method: produce
- 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 record for product Cloth.
--
- !record {model: product.product, id: product_product_cloth0}:
- categ_id: product.cat1
- cost_method: standard
- mes_type: fixed
- name: Cloth
- procure_method: make_to_order
- property_stock_inventory: stock.location_inventory
- property_stock_procurement: stock.location_procurement
- property_stock_production: stock.location_production
- seller_delay: '1'
- seller_ids:
- - delay: 1
- name: base.res_partner_maxtor
- product_uom: product.product_uom_unit
- min_qty: 300.0
- standard_price: 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
--
- I create record for product Buttons.
--
- !record {model: product.product, id: product_product_buttons0}:
- categ_id: product.cat1
- cost_method: standard
- mes_type: fixed
- name: Buttons
- procure_method: make_to_stock
- property_stock_inventory: stock.location_inventory
- property_stock_procurement: stock.location_procurement
- property_stock_production: stock.location_production
- seller_delay: '1'
- seller_ids:
- - delay: 1
- name: base.res_partner_asus
- product_uom: product.product_uom_kgm
- min_qty: 100.0
- standard_price: 1.0
- supply_method: buy
- type: product
- uom_id: product.product_uom_kgm
- uom_po_id: product.product_uom_kgm
- volume: 0.0
- warranty: 0.0
- weight: 0.0
- weight_net: 0.0
--
- I am creating bills of material for 'Shirt'.
--
- I create bills of material for Shirt.
--
- !record {model: mrp.bom, id: mrp_bom_shirt0}:
- bom_lines:
- - company_id: base.main_company
- name: Cloth
- product_efficiency: 1.0
- product_id: product_product_cloth0
- product_qty: 1.0
- product_uom: product.product_uom_unit
- product_uos_qty: 0.0
- sequence: 0.0
- type: normal
- - company_id: base.main_company
- name: Buttons
- product_efficiency: 1.0
- product_id: product_product_buttons0
- product_qty: 8.0
- product_uom: product.product_uom_kgm
- product_uos_qty: 0.0
- sequence: 0.0
- type: normal
- company_id: base.main_company
- name: Shirt
- product_efficiency: 1.0
- product_id: product_product_shirt0
- product_qty: 1.0
- product_uom: product.product_uom_unit
- product_uos_qty: 0.0
- sequence: 0.0
- type: normal
--
- I create minimum stock rule for product Buttons
--
- !record {model: stock.warehouse.orderpoint, id: stock_warehouse_orderpoint_op0}:
- company_id: base.main_company
- location_id: stock.stock_location_stock
- logic: max
- name: OP/00007
- product_id: mrp.product_product_buttons0
- product_max_qty: 50.0
- product_min_qty: 10.0
- product_uom: product.product_uom_kgm
- qty_multiple: 1
- warehouse_id: stock.warehouse0
--
- I create a procurement order for product Shirt.
--
- !record {model: procurement.order, id: procurement_order_shirt0}:
- name: 'PROC: Shirt'
- product_id: product_product_shirt0
- product_qty: 5.00
- location_id: stock.stock_location_stock
- product_uom: product.product_uom_unit
--
- I confirm the procurement order.
--
- !workflow {model: procurement.order, action: button_confirm, ref: procurement_order_shirt0}
--
- I run the procurement.
--
- !workflow {model: procurement.order, action: button_check, ref: procurement_order_shirt0}
--
- I see that there is a manufacturing order for Shirt.
--
- !python {model: mrp.production}: |
- from tools.translate import _
- order_ids = self.search(cr, uid, [('product_id','=',ref('product_product_shirt0'))])
- assert order_ids, 'No Manufacturing Order.'
--
- I also check that there are two more procurement orders for sub products Cloth and Buttons.
--
- !python {model: procurement.order}: |
- from tools.translate import _
- proc_ids = self.search(cr, uid, [('product_id','in',[ref('product_product_cloth0'),ref('product_product_buttons0')])])
- assert proc_ids, 'No Procurements.'
--
- The scheduler runs.
--
- !function {model: procurement.order, name: run_scheduler}:
- - model: procurement.order
- search: "[]"
--
- I check that there is one purchase order for Cloth.
--
- !python {model: purchase.order}: |
- purch_ids = self.search(cr, uid, [('partner_id.name','=','Maxtor')])
- assert purch_ids, 'No Purchase Orders.'
--
- I confirm purchase order for Cloth.
--
- !python {model: purchase.order}: |
- import netsvc
- purch_ids = self.search(cr, uid, [('partner_id.name','=','Maxtor')])
- wf_service = netsvc.LocalService("workflow")
- for p_id in purch_ids:
- wf_service.trg_validate(uid, 'purchase.order', p_id, 'purchase_confirm', cr)
-
--
- I confirm purchase order for Buttons.
--
- !python {model: purchase.order}: |
- import netsvc
- purch_ids = self.search(cr, uid, [('partner_id.name','=','ASUStek')])
- wf_service = netsvc.LocalService("workflow")
- for p_id in purch_ids:
- wf_service.trg_validate(uid, 'purchase.order', p_id, 'purchase_confirm', cr)
-
--
- I Check incoming shipments for cloth. And receive products.
--
- !python {model: stock.picking}: |
- pick_ids = self.search(cr, uid, [('address_id.name','=','Wong'),('state','=','assigned')])
- assert pick_ids, 'No Incoming Shipments found!'
- stock_partial_picking = self.pool.get('stock.partial.picking')
- for pick_id in pick_ids:
- partial_id = stock_partial_picking.create(cr, uid, {},
- context={'active_model': 'stock.picking',
- 'active_ids': [pick_id]})
- stock_partial_picking.do_partial(cr, uid, [partial_id])
--
- I Check incoming shipments for buttons and receive products.
--
- !python {model: stock.picking}: |
- pick_ids = self.search(cr, uid, [('address_id.name','=','Tang'),('state','=','assigned')])
- assert pick_ids, 'No Incoming Shipments found!'
- stock_partial_picking = self.pool.get('stock.partial.picking')
- for pick_id in pick_ids:
- partial_id = stock_partial_picking.create(cr, uid, {},
- context={'active_model': 'stock.picking',
- 'active_ids': [pick_id]})
- stock_partial_picking.do_partial(cr, uid, [partial_id])
--
- Run scheduler again.
--
- !function {model: procurement.order, name: run_scheduler}:
- - model: procurement.order
- search: "[]"
--
- Check state of manufacturing order for Shirt.
--
- !python {model: mrp.production}: |
- from tools.translate import _
- order_ids = self.search(cr, uid, [('product_id','=',ref('product_product_shirt0')),('state','=','ready')])
- assert order_ids, 'No Manufacturing Order in Ready state.'
--
- I start production order for Shirt.
--
- !python {model: mrp.production}: |
- from tools.translate import _
- import netsvc
- prod_ids = self.search(cr, uid, [('state','=','ready')])
- assert prod_ids, _('No Ready Manufacturing Orders found!')
- wf_service = netsvc.LocalService("workflow")
- for p_id in prod_ids:
- wf_service.trg_validate(uid, 'mrp.production', p_id, 'button_produce', cr)
--
- I create record for producing products with quantity 5.00.
--
- !record {model: mrp.product.produce, id: mrp_product_produce0}:
- product_qty: 2.00
- mode: 'consume_produce'
--
- I produce 2 products with 5.00 quantities each.
--
- !python {model: mrp.product.produce}: |
- prod_obj = self.pool.get('mrp.production')
- prod_ids = prod_obj.search(cr, uid, [('product_id.name','=','Shirt')])
- self.do_produce(cr, uid, [ref('mrp_product_produce0')], context={'active_ids': prod_ids})
--
- I create record for remaining products with quantity 35.00.
--
- !record {model: stock.move.consume, id: stock_move_consume0}:
- product_id: product_product_buttons0
- product_qty: 35.00
- product_uom: product.product_uom_unit
- location_id: stock.stock_location_stock
--
- I produce remaining product Buttons with 35.00 quantity.
--
- !python {model: stock.move.consume}: |
- from tools.translate import _
- stock_obj = self.pool.get('stock.move')
- stock_ids = stock_obj.search(cr, uid, [('product_id.name','=','Buttons')])
- self.do_move_consume(cr, uid, [ref('stock_move_consume0')], context={'active_ids': stock_ids})
--
- And finally production order is done.
--
- !python {model: mrp.product.produce}: |
- prod_obj = self.pool.get('mrp.production')
- prod_ids = prod_obj.search(cr, uid, [('product_id.name','=','Shirt')])
- self.do_produce(cr, uid, [ref('mrp_product_produce0')], context={'active_ids': prod_ids})
-
diff --git a/addons/mrp/test/mrp_production_cancel.yml b/addons/mrp/test/mrp_production_cancel.yml
deleted file mode 100644
index 1dc20a215d1..00000000000
--- a/addons/mrp/test/mrp_production_cancel.yml
+++ /dev/null
@@ -1,29 +0,0 @@
--
- In order to test the manufacturing order in Openerp,
- I am creating one manufacturing order
--
- !record {model: mrp.production, id: mrp_production_mo1}:
- company_id: base.main_company
- date_planned: !eval datetime.today().strftime("%Y-%m-%d %H:%M:%S")
- location_dest_id: stock.stock_location_stock
- location_src_id: stock.stock_location_stock
- product_id: product.product_product_pc1
- name: MO/01234
- product_qty: 5.0
- product_uom: product.product_uom_unit
- product_uos_qty: 0.0
--
- I confirm the order.
--
- !workflow {model: mrp.production, action: button_confirm, ref: mrp_production_mo1}
--
- In order to cancel the MO, I first cancel its picking.
--
- !python {model: stock.picking}: |
- mrp_obj = self.pool.get('mrp.production')
- mo = mrp_obj.browse(cr, uid, ref("mrp_production_mo1"))
- self.action_cancel(cr, uid, [mo.picking_id.id], context=None)
--
- Then I Cancel the production order and related stock moves.
--
- !workflow {model: mrp.production, action: button_cancel, ref: mrp_production_mo1}
\ No newline at end of file
diff --git a/addons/mrp/test/mrp_production_order.yml b/addons/mrp/test/mrp_production_order.yml
deleted file mode 100644
index 57d75e1c1a5..00000000000
--- a/addons/mrp/test/mrp_production_order.yml
+++ /dev/null
@@ -1,119 +0,0 @@
--
- In order to test the manufacturing order working with procurements I will use
- some products with different supply method and procurement method, also check
- the bills of material for the products.
--
- I am creating one manufacturing order.
--
- !record {model: mrp.production, id: mrp_production_mo1}:
- company_id: base.main_company
- date_planned: !eval datetime.today().strftime("%Y-%m-%d %H:%M:%S")
- location_dest_id: stock.stock_location_stock
- location_src_id: stock.stock_location_stock
- product_id: product.product_product_pc1
- name: MO/0123
- product_qty: 5.0
- product_uom: product.product_uom_unit
- product_uos_qty: 0.0
--
- I compute the data.
--
- !python {model: mrp.production}: |
- self.action_compute(cr, uid, [ref("mrp_production_mo1")])
--
- I confirm the order.
--
- !workflow {model: mrp.production, action: button_confirm, ref: mrp_production_mo1}
--
- I create record for changing production quantity to 6.00
--
- !record {model: change.production.qty, id: mrp_production_qty}:
- product_qty: 6.0
--
- Changes the Quantity of Product.
--
- !python {model: change.production.qty}: |
- context = {"lang": 'en_US', "active_model":"mrp.production", "active_ids": [ref("mrp_production_mo1")], "tz": False, "active_id":ref('mrp_production_mo1')}
- self.default_get(cr, uid, ["product_qty"], context)
- self.change_prod_qty(cr, uid, [ref("mrp_production_qty")], context=context)
--
- I check now quantity of the production order is 6 or not.
--
- !assert {model: mrp.production, id: mrp_production_mo1}:
- - product_qty == 6
--
- I am checking Procurement orders for components of PC1.
--
- !python {model: procurement.order}: |
- from tools.translate import _
- production_obj = self.pool.get('mrp.production')
- production = production_obj.browse(cr, uid, ref('mrp_production_mo1'))
- product_ids = map(lambda x:x.product_id.id, production.move_lines)
- proc_ids = self.search(cr, uid, [('product_id','in',product_ids)])
- assert proc_ids, _('No Procurements!')
--
- The scheduler runs.
--
- !function {model: procurement.order, name: run_scheduler}:
- - model: procurement.order
- search: "[]"
--
- I am checking Internal picking.
--
- !python {model: stock.picking}: |
- from tools.translate import _
- pick_ids = self.search(cr, uid, [('type','=','internal')])
- assert pick_ids, _('No Internal Pickings!')
--
- I see that there is a manufacturing order for the sub product CPU_GEN with ready state and I start production of it.
--
- !python {model: mrp.production}: |
- from tools.translate import _
- order_ids = self.search(cr, uid, [('state','=','ready'), ('product_id', '=', ref('product.product_product_cpu_gen'))])
- assert order_ids, _('No manufacturing order in Ready state!')
- import netsvc
- wf_service = netsvc.LocalService("workflow")
- for order in order_ids:
- wf_service.trg_validate(uid, 'mrp.production', order, 'button_produce', cr)
--
- I create record for producing products with quantity 1.00.
--
- !record {model: mrp.product.produce, id: mrp_product_produce0}:
- product_qty: 1.00
- mode: 'consume_produce'
--
- I produce the product.
--
- !python {model: mrp.product.produce}: |
- prod_obj = self.pool.get('mrp.production')
- prod_ids = prod_obj.search(cr, uid, [('state','=','in_production'), ('product_id', '=', ref('product.product_product_cpu_gen'))])
- self.do_produce(cr, uid, [ref('mrp_product_produce0')], context={'active_ids': prod_ids})
--
- Now the manufacturing order for subproduct CPU_GEN is done and manufacturing
- order for PC1 is in ready state.
--
- !python {model: mrp.production}: |
- from tools.translate import _
- prod_ids = self.search(cr, uid, [('state','=','done'), ('product_id', '=', ref('product.product_product_cpu_gen'))])
- assert prod_ids, _('Manufacturing order for CPU_GEN is yet not done!')
--
- I start producing the product PC1.
--
- !workflow {model: mrp.production, action: button_produce, ref: mrp_production_mo1}
--
- I create record for producing products with quantity 6.00.
--
- !record {model: mrp.product.produce, id: mrp_product_produce1}:
- product_qty: 6.00
- mode: 'consume_produce'
--
- Finally my production order is done.
--
- !python {model: mrp.product.produce}: |
- context = {"lang": 'en_US', "active_model":"mrp.production", "active_ids": [ref("mrp_production_mo1")], "tz": False, "active_id":ref('mrp_production_mo1')}
- self.do_produce(cr, uid, [ref('mrp_product_produce1')], context=context)
--
- I check now the production order for PC1 is done.
--
- !assert {model: mrp.production, id: mrp_production_mo1}:
- - state == 'done'
diff --git a/addons/mrp/test/mrp_report.yml b/addons/mrp/test/mrp_report.yml
deleted file mode 100644
index 48126b5edcd..00000000000
--- a/addons/mrp/test/mrp_report.yml
+++ /dev/null
@@ -1,38 +0,0 @@
--
- In order to test the PDF reports defined on a MRP, we will print a BOM Structure Report
--
- !python {model: mrp.bom}: |
- import netsvc, tools, os
- (data, format) = netsvc.LocalService('report.bom.structure').create(cr, uid, [ref('mrp.mrp_bom_0'),ref('mrp.mrp_bom_1'),ref('mrp.mrp_bom_2'),ref('mrp.mrp_bom_23'),ref('mrp.mrp_bom_1901'),ref('mrp.mrp_bom_assemblysection0'),ref('mrp.mrp_bom_sidepanel0'),ref('mrp.mrp_bom_defaultbomforshelfofcm1'),ref('mrp.mrp_bom_sidepanel3')], {}, {})
- if tools.config['test_report_directory']:
- file(os.path.join(tools.config['test_report_directory'], 'mrp-bom_structure_report.'+format), 'wb+').write(data)
-
--
- In order to test the PDF reports defined on a MRP, we will print Production Order Report
--
- !python {model: mrp.production}: |
- import netsvc, tools, os
- (data, format) = netsvc.LocalService('report.mrp.production.order').create(cr, uid, [ref('mrp.mrp_production_mo1')], {}, {})
- if tools.config['test_report_directory']:
- file(os.path.join(tools.config['test_report_directory'], 'mrp-production_order_report.'+format), 'wb+').write(data)
-
--
- Print Product Price Report through the wizard
--
- !python {model: product.product}: |
- ctx={}
- ctx.update({'model': 'product.product','active_ids': [1,2,3,5]})
- data_dict = {'number': 1}
- from tools import test_reports
- test_reports.try_report_action(cr, uid, 'action_view_mrp_product_price_wizard',wiz_data=data_dict, context=ctx, our_module='mrp')
-
--
- Print Work Center Load Report through the wizard
--
- !python {model: mrp.workcenter}: |
- ctx={}
- ctx.update({'model': 'mrp.workcenter','active_ids': [ref('mrp_workcenter_0'),ref('mrp_workcenter_1')]})
- data_dict = {'time_unit': 'day', 'measure_unit': 'hours'}
- from tools import test_reports
- test_reports.try_report_action(cr, uid, 'action_mrp_workcenter_load_wizard',wiz_data=data_dict, context=ctx, our_module='mrp')
-
diff --git a/addons/mrp/test/order_demo.yml b/addons/mrp/test/order_demo.yml
new file mode 100644
index 00000000000..9c7b8720904
--- /dev/null
+++ b/addons/mrp/test/order_demo.yml
@@ -0,0 +1,27 @@
+-
+ In order to test process of production order, I create Bill of material of Shelf 100cm.
+-
+ !record {model: mrp.bom, id: mrp_bom_defaultbomforshelfofcm0}:
+ product_id: product.product_product_shelfofcm0
+-
+ !record {model: mrp.bom, id: mrp_bom_assemblysection1}:
+ routing_id: mrp.mrp_routing_0
+-
+ !record {model: mrp.bom, id: mrp_bom_rearpanelarm1}:
+ routing_id: mrp.mrp_routing_0
+-
+ I create Production Order of Shelf 100cm to produce 5.0 Dozen PCE.
+-
+ !record {model: mrp.production, id: mrp_production_shelf100cm}:
+ location_src_id: stock.stock_location_stock
+ location_dest_id: stock.stock_location_output
+ product_id: product.product_product_shelfofcm0
+ bom_id: mrp_bom_defaultbomforshelfofcm0
+ routing_id: mrp.mrp_routing_1
+ product_uom: product.product_uom_dozen
+ product_qty: 5.0
+-
+ !record {model: mrp.workcenter, id: mrp_workcenter_0}:
+ product_id: product.product_assembly
+
+
diff --git a/addons/mrp/test/order_process.yml b/addons/mrp/test/order_process.yml
new file mode 100644
index 00000000000..0c970d7d196
--- /dev/null
+++ b/addons/mrp/test/order_process.yml
@@ -0,0 +1,309 @@
+-
+ I compute the production order.
+-
+ !python {model: mrp.production}: |
+ order = self.browse(cr, uid, ref("mrp_production_shelf100cm"), context=context)
+ order.action_compute(context=context)
+-
+ I check production lines after compute.
+-
+ !python {model: mrp.production}: |
+ order = self.browse(cr, uid, ref("mrp_production_shelf100cm"), context=context)
+ assert len(order.product_lines) == 5, "Production lines are not generated proper."
+ factor = 12.0*5.0
+ sidepanel = False
+ woodlintelm = False
+ woodmm0 = False
+ woodmm10 = False
+ metalcleats = False
+ for line in order.product_lines:
+ if line.product_id.id == ref('product.product_product_sidepanel0'): #SIDEPAN 2 PCE
+ assert not sidepanel, "Production line is already generated for SIDEPAN."
+ assert line.product_qty == (2.0*factor), "Qty is not correspond."
+ assert line.product_uom.id == ref('product.product_uom_unit'), "UOM is not correspond"
+ sidepanel = True
+ elif line.product_id.id == ref('product.product_product_woodlintelm0'): #LIN40 4*0.25 Meter
+ assert not woodlintelm, "Production line is already generated for LIN40."
+ assert line.product_qty == (4*0.25*factor), "Qty is not correspond."
+ assert line.product_uom.id == ref('product.product_uom_meter'), "UOM is not correspond"
+ woodlintelm = True
+ elif line.product_id.id == ref('product.product_product_woodmm0'): #WOOD002 0.25 m
+ assert not woodmm0, "Production line is already generated for WOOD002."
+ assert line.product_qty == (0.25*factor), "Qty is not correspond."
+ assert line.product_uom.id == ref('product.product_uom_meter'), "UOM is not correspond"
+ woodmm0 = True
+ elif line.product_id.id == ref('product.product_product_metalcleats0'): #METC000 4*3 PCE
+ assert not metalcleats, "Production line is already generated for METC000."
+ assert line.product_qty == (4*3*factor), "Qty is not correspond."
+ assert line.product_uom.id == ref('product.product_uom_unit'), "UOM is not correspond"
+ metalcleats = True
+ elif line.product_id.id == ref('product.product_product_woodmm10'): #WOOD010 0.083*3 m
+ assert not woodmm10, "Production line is already generated for WOOD010."
+ assert line.product_qty == (0.083*3*factor), "Qty is not correspond."
+ assert line.product_uom.id == ref('product.product_uom_meter'), "UOM is not correspond"
+ woodmm10 = True
+ else:
+ raise AssertionError('unknown order line: %s' % line)
+ assert sidepanel, "Production line is not generated for SIDEPAN."
+ assert woodlintelm, "Production line is not generated for LIN40."
+ assert woodmm0, "Production line is not generated for WOOD002."
+ assert metalcleats, "Production line is not generated for METC000."
+ assert woodmm10, "Production line is not generated for WOOD010."
+
+-
+ Now I check workcenter lines.
+-
+ !python {model: mrp.production}: |
+ order = self.browse(cr, uid, ref("mrp_production_shelf100cm"), context=context)
+ assert len(order.workcenter_lines), "Workcenter lines are not generated proper."
+ for line in order.workcenter_lines:
+ wc = line.workcenter_id
+ hours = ((wc.time_start or 0.0)+(wc.time_stop or 0.0)+line.cycle*(wc.time_cycle or 0.0)) * (wc.time_efficiency or 1.0)
+ factor = 5*12
+ d, m = divmod(factor, wc.capacity_per_cycle)
+ cycle = (d + (m and 1.0 or 0.0))
+ if line.name == "Short time assembly - Assembly Section":
+ assert line.sequence, "Sequence is not correspond: %s" % (line.name)
+ assert line.cycle == (4*cycle), "Cycle is not correspond: %s" % (line.name)
+ assert line.hour == (2*cycle*4 + hours), "Hours is not correspond: %s"% (line.name)
+ elif line.name == "Short time assembly - Rear Panel SHE100":
+ assert line.sequence, "Sequence is not correspond: %s" % (line.name)
+ assert line.cycle == (1*cycle), "Cycle is not correspond: %s" % (line.name)
+ assert line.hour == (2*cycle + hours), "Hours is not correspond: %s"% (line.name)
+ elif line.name == "long time assembly - Shelf of 100cm":
+ assert line.sequence, "Sequence is not correspond: %s" % (line.name)
+ assert line.cycle == (2*cycle), "Cycle is not correspond: %s" % (line.name)
+ assert line.hour == (5*cycle + hours), "Hours is not correspond: %s"% (line.name)
+ elif line.name == "Testing - Shelf of 100cm":
+ assert line.sequence, "Sequence is not correspond: %s" % (line.name)
+ assert line.cycle == (1*cycle), "Cycle is not correspond: %s" % (line.name)
+ assert line.hour == (1*cycle + hours), "Hours is not correspond: %s"% (line.name)
+ elif line.name == "Packing - Shelf of 100cm":
+ assert line.sequence, "Sequence is not correspond: %s" % (line.name)
+ assert line.cycle == (1*cycle), "Cycle is not correspond: %s" % (line.name)
+ assert line.hour == (0.5*cycle + hours), "Hours is not correspond: %s"% (line.name)
+ else:
+ raise AssertionError('unknown workcenter line: %s' % line)
+-
+ I confirm the Production Order.
+-
+ !workflow {model: mrp.production, action: button_confirm, ref: mrp_production_shelf100cm}
+-
+ I check details of Produce Move of Production Order to trace Final Product.
+-
+ !python {model: mrp.production}: |
+ order = self.browse(cr, uid, ref("mrp_production_shelf100cm"))
+ assert order.state == 'confirmed', "Production order should be confirmed."
+ assert order.move_created_ids, "Trace Record is not created for Final Product."
+ move = order.move_created_ids[0]
+ source_location_id = order.product_id.product_tmpl_id.property_stock_production.id
+ assert move.date == order.date_planned, "Planned date is not correspond."
+ assert move.product_id.id == order.product_id.id, "Product is not correspond."
+ assert move.product_uom.id == order.product_uom.id, "UOM is not correspond."
+ assert move.product_qty == order.product_qty, "Qty is not correspond."
+ assert move.product_uos_qty == order.product_uos and order.product_uos_qty or order.product_qty, "UOS qty is not correspond."
+ if order.product_uos:
+ assert move.product_uos.id == order.product_uos.id, "UOS is not correspond."
+ assert move.location_id.id == source_location_id, "Source Location is not correspond."
+ assert move.location_dest_id.id == order.location_dest_id.id, "Destination Location is not correspond."
+ routing_loc = None
+ if order.bom_id.routing_id and order.bom_id.routing_id.location_id:
+ routing_loc = order.bom_id.routing_id.location_id.id
+ date_planned = order.date_planned
+ for move_line in order.move_lines:
+ for order_line in order.product_lines:
+ if move_line.product_id.type not in ('product', 'consu'):
+ continue
+ if move_line.product_id.id == order_line.product_id.id:
+ assert move_line.date == date_planned, "Planned date is not correspond in 'To consume line'."
+ assert move_line.product_qty == order_line.product_qty, "Qty is not correspond in 'To consume line'."
+ assert move_line.product_uom.id == order_line.product_uom.id, "UOM is not correspond in 'To consume line'."
+ assert move_line.product_uos_qty == order_line.product_uos and order_line.product_uos_qty or order_line.product_qty, "UOS qty is not correspond in 'To consume line'."
+ if order_line.product_uos:
+ assert move_line.product_uos.id == order_line.product_uos.id, "UOS is not correspond in 'To consume line'."
+ assert move_line.location_id.id == routing_loc or order.location_src_id.id, "Source location is not correspond in 'To consume line'."
+ assert move_line.location_dest_id.id == source_location_id, "Destination Location is not correspond in 'To consume line'."
+
+-
+ I check details of an Internal Shipment after confirmed production order to bring components in Raw Materials Location.
+-
+ !python {model: mrp.production}: |
+ procurement = self.pool.get('procurement.order')
+ order = self.browse(cr, uid, ref("mrp_production_shelf100cm"))
+ assert order.picking_id, 'Internal Shipment should be created!'
+
+ routing_loc = None
+ pick_type = 'internal'
+ address_id = False
+ if order.bom_id.routing_id and order.bom_id.routing_id.location_id:
+ routing_loc = order.bom_id.routing_id.location_id
+ if routing_loc.usage <> 'internal':
+ pick_type = 'out'
+ address_id = routing_loc.address_id and routing_loc.address_id.id or False
+ routing_loc = routing_loc.id
+ assert order.picking_id.type == pick_type, "Shipment should be Internal."
+ assert order.picking_id.address_id.id == address_id, "Shipment Address is not correspond with Adderss of Routing Location."
+ date_planned = order.date_planned
+ for move_line in order.picking_id.move_lines:
+ for order_line in order.product_lines:
+ if move_line.product_id.type not in ('product', 'consu'):
+ continue
+ if move_line.product_id.id == order_line.product_id.id:
+ assert move_line.date == date_planned, "Planned date is not correspond."
+ assert move_line.product_qty == order_line.product_qty, "Qty is not correspond."
+ assert move_line.product_uom.id == order_line.product_uom.id, "UOM is not correspond."
+ assert move_line.product_uos_qty == order_line.product_uos and order_line.product_uos_qty or order_line.product_qty, "UOS qty is not correspond."
+ if order_line.product_uos:
+ assert move_line.product_uos.id == order_line.product_uos.id, "UOS is not correspond."
+ assert move_line.location_id.id == order.location_src_id.id, "Source location is not correspond."
+ assert move_line.location_dest_id.id == routing_loc or order.location_src_id.id, "Destination Location is not correspond."
+ procurement_ids = procurement.search(cr, uid, [('move_id','=',move_line.id)])
+ assert procurement_ids, "Procurement should be created for shipment line of raw materials."
+ shipment_procurement = procurement.browse(cr, uid, procurement_ids[0], context=context)
+ assert shipment_procurement.date_planned == date_planned, "Planned date is not correspond in procurement."
+ assert shipment_procurement.product_id.id == order_line.product_id.id, "Product is not correspond in procurement."
+ assert shipment_procurement.product_qty == order_line.product_qty, "Qty is not correspond in procurement."
+ assert shipment_procurement.product_uom.id == order_line.product_uom.id, "UOM is not correspond in procurement."
+ assert shipment_procurement.product_uos_qty == order_line.product_uos and order_line.product_uos_qty or order_line.product_qty, "UOS qty is not correspond in procurement."
+ if order_line.product_uos:
+ assert shipment_procurement.product_uos.id == order_line.product_uos.id, "UOS is not correspond in procurement."
+ assert shipment_procurement.location_id.id == order.location_src_id.id, "Location is not correspond in procurement."
+ assert shipment_procurement.procure_method == order_line.product_id.procure_method, "Procure method is not correspond in procurement."
+
+-
+ I change production qty with 3 Dozen Shelf 100cm.
+-
+ !python {model: change.production.qty}: |
+ context.update({'active_id': ref('mrp_production_shelf100cm')})
+-
+ !record {model: change.production.qty, id: mrp_production_qty}:
+ product_qty: 3.0
+-
+ !python {model: change.production.qty}: |
+ self.change_prod_qty(cr, uid, [ref("mrp_production_qty")], context=context)
+-
+ I check qty after changed in production order.
+-
+ !python {model: mrp.production}: |
+ order = self.browse(cr, uid, ref("mrp_production_shelf100cm"))
+ assert order.product_qty == 3, "Qty is not changed in order."
+ move = order.move_created_ids[0]
+ assert move.product_qty == order.product_qty, "Qty is not changed in move line."
+-
+ I run scheduler.
+-
+ !python {model: procurement.order}: |
+ self.run_scheduler(cr, uid)
+-
+ The production order is Waiting Goods, I forcefully done internal shipment.
+-
+ !python {model: mrp.production}: |
+ self.force_production(cr, uid, [ref("mrp_production_shelf100cm")])
+-
+ I check that production order in ready state after forcefully done internal shipment.
+-
+ !python {model: mrp.production}: |
+ order = self.browse(cr, uid, ref("mrp_production_shelf100cm"))
+ assert order.state == 'ready', 'Production order should be in Ready State.'
+ assert order.picking_id.state == 'done', 'Internal shipment should be done.'
+-
+ Now I start production.
+-
+ !workflow {model: mrp.production, action: button_produce, ref: mrp_production_shelf100cm}
+-
+ I check that production order in production state after start production.
+-
+ !python {model: mrp.production}: |
+ order = self.browse(cr, uid, ref("mrp_production_shelf100cm"))
+ assert order.state == 'in_production', 'Production order should be in production State.'
+-
+ I consume raw materials and put one material in scrap location due to waste it.
+-
+ !python {model: mrp.production}: |
+ scrap_location_ids = self.pool.get('stock.location').search(cr, uid, [('scrap_location','=',True)])
+ scrap_location_id = scrap_location_ids[0]
+ order = self.browse(cr, uid, ref("mrp_production_shelf100cm"))
+ for move in order.move_lines:
+ move.action_consume(move.product_qty)
+ if move.product_id.id == ref("product.product_product_metalcleats0"):
+ move.action_scrap(5.0, scrap_location_id)
+-
+ I produce product.
+-
+ !python {model: mrp.product.produce}: |
+ context.update({'active_id': ref('mrp_production_shelf100cm')})
+-
+ !record {model: mrp.product.produce, id: mrp_product_produce1}:
+ mode: 'consume_produce'
+-
+ !python {model: mrp.product.produce}: |
+ self.do_produce(cr, uid, [ref('mrp_product_produce1')], context=context)
+-
+ I check production order after produced.
+-
+ !python {model: mrp.production}: |
+ order = self.browse(cr, uid, ref("mrp_production_shelf100cm"))
+ assert order.state == 'done', "Production order should be closed."
+-
+ I check Total Costs at End of Production.
+-
+ !python {model: mrp.production}: |
+ order = self.browse(cr, uid, ref("mrp_production_shelf100cm"))
+ account_analytic_line = self.pool.get('account.analytic.line')
+ def rounding(f, r):
+ import math
+ if not r:
+ return f
+ return math.ceil(f / r) * r
+
+ for wc_line in order.workcenter_lines:
+ wc = wc_line.workcenter_id
+ accounts = [wc.costs_hour_account_id, wc.costs_cycle_account_id]
+ cost_per_cyle = wc_line.cycle * wc.costs_cycle
+ cost_per_hours = wc_line.hour * wc.costs_hour
+ if accounts and wc.costs_journal_id and wc.costs_general_account_id and (cost_per_cyle or cost_per_hours):
+ line_ids = account_analytic_line.search(cr, uid, [('name','ilike',wc_line.name)])
+ assert line_ids, 'Costs lines are not generated.'
+ for line in account_analytic_line.browse(cr, uid, line_ids, context=context):
+ if wc.costs_hour_account_id and line.account_id.id == wc.costs_hour_account_id.id:
+ assert rounding(line.unit_amount, 3) == rounding(wc_line.hour, 3), "Cost Unit Amount is not correspond."
+ assert rounding(line.amount, 3) == rounding(cost_per_hours, 3), "Cost amount is not correspond."
+ elif wc.costs_cycle_account_id and line.account_id.id == wc.costs_cycle_account_id.id:
+ assert rounding(line.unit_amount, 3) == rounding(wc_line.cycle, 3), "Cost Unit Amount is not correspond."
+ assert rounding(line.amount, 3) == rounding(cost_per_cyle, 3), "Cost Amount is not correspond."
+ else:
+ raise AssertionError('unknown cost line: %s' % line)
+ assert line.general_account_id.id == wc.costs_general_account_id.id, "General Account is not correspond."
+ assert line.journal_id.id == wc.costs_journal_id.id, "Account Journal is not correspond."
+ assert line.product_id.id == wc.product_id.id, "Product is not correspond."
+ assert line.product_uom_id.id == wc.product_id.uom_id.id, "UOM is not correspond."
+
+-
+ I print a "BOM Structure".
+-
+ !python {model: mrp.production}: |
+ import netsvc, tools, os
+ order = self.browse(cr, uid, ref("mrp_production_shelf100cm"))
+ (data, format) = netsvc.LocalService('report.bom.structure').create(cr, uid, [order.bom_id.id], {}, {})
+ if tools.config['test_report_directory']:
+ file(os.path.join(tools.config['test_report_directory'], 'mrp-bom_structure_report.'+format), 'wb+').write(data)
+
+-
+ I print "Production Order".
+-
+ !python {model: mrp.production}: |
+ import netsvc, tools, os
+ (data, format) = netsvc.LocalService('report.mrp.production.order').create(cr, uid, [ref("mrp_production_shelf100cm")], {}, {})
+ if tools.config['test_report_directory']:
+ file(os.path.join(tools.config['test_report_directory'], 'mrp-production_order_report.'+format), 'wb+').write(data)
+
+-
+ I print "Work Center Load Report".
+-
+ !python {model: mrp.workcenter}: |
+ ctx = context.copy()
+ ctx.update({'model': 'mrp.workcenter','active_ids': [ref('mrp_workcenter_0'),ref('mrp_workcenter_1')]})
+ data_dict = {'time_unit': 'day', 'measure_unit': 'hours'}
+ from tools import test_reports
+ test_reports.try_report_action(cr, uid, 'action_mrp_workcenter_load_wizard',wiz_data=data_dict, context=ctx, our_module='mrp')
+
diff --git a/addons/mrp/wizard/mrp_product_produce.py b/addons/mrp/wizard/mrp_product_produce.py
index dc9a235ff63..db4d6e77691 100644
--- a/addons/mrp/wizard/mrp_product_produce.py
+++ b/addons/mrp/wizard/mrp_product_produce.py
@@ -60,22 +60,11 @@ class mrp_product_produce(osv.osv_memory):
}
def do_produce(self, cr, uid, ids, context=None):
- """ To check the product type
- @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 if we want more than one
- @param context: A standard dictionary
- @return:
- """
- if context is None:
- context = {}
- prod_obj = self.pool.get('mrp.production')
- move_ids = context.get('active_ids', [])
- for data in self.browse(cr, uid, ids, context=context):
- for move_id in move_ids:
- prod_obj.action_produce(cr, uid, move_id,
- data.product_qty, data.mode, context=context)
+ production_id = context.get('active_id', False)
+ assert production_id, "Production Id should be specified in context as a Active ID"
+ data = self.browse(cr, uid, ids[0], context=context)
+ self.pool.get('mrp.production').action_produce(cr, uid, production_id,
+ data.product_qty, data.mode, context=context)
return {}
mrp_product_produce()
diff --git a/addons/mrp_operations/__openerp__.py b/addons/mrp_operations/__openerp__.py
index caa33cc6556..10d82cfb8c4 100644
--- a/addons/mrp_operations/__openerp__.py
+++ b/addons/mrp_operations/__openerp__.py
@@ -65,8 +65,11 @@ So that we can compare the theoretic delay and real delay.
'process/mrp_operation_process.xml',
'mrp_operations_workflow_instance.xml'
],
- 'demo_xml': ['mrp_operation_data.xml'],
- 'test': ['test/mrp_operations.yml', 'test/mrp_operations_report.yml','test/mrp_operation_test.yml'],
+ 'demo_xml': ['mrp_operation_data.xml',
+ 'mrp_operations_demo.yml'],
+ 'test': [
+ 'test/workcenter_operations.yml',
+ ],
'installable': True,
'active': False,
'certificate': '0056233813133',
diff --git a/addons/mrp_operations/mrp_operations.py b/addons/mrp_operations/mrp_operations.py
index e6f5aa00f28..7bdb883e98e 100644
--- a/addons/mrp_operations/mrp_operations.py
+++ b/addons/mrp_operations/mrp_operations.py
@@ -350,6 +350,7 @@ class mrp_production(osv.osv):
if l.production_id and (l.production_id.date_start < po.date_finished):
self.write(cr, uid, [l.production_id.id], {'date_start': po.date_finished})
break
+ return True
def write(self, cr, uid, ids, vals, context=None, update=True, mini=True):
@@ -371,13 +372,13 @@ class mrp_production(osv.osv):
pass
return result
- def action_compute(self, cr, uid, ids, properties=[]):
+ def action_compute(self, cr, uid, ids, properties=[], context=None):
""" Computes bills of material of a product and planned date of work order.
@param properties: List containing dictionaries of properties.
@return: No. of products.
"""
- result = super(mrp_production, self).action_compute(cr, uid, ids, properties=properties)
- self._compute_planned_workcenter(cr, uid, ids, context={})
+ result = super(mrp_production, self).action_compute(cr, uid, ids, properties=properties, context=context)
+ self._compute_planned_workcenter(cr, uid, ids, context=context)
return result
mrp_production()
diff --git a/addons/mrp_operations/mrp_operations_demo.yml b/addons/mrp_operations/mrp_operations_demo.yml
new file mode 100644
index 00000000000..7bfef8a4c7b
--- /dev/null
+++ b/addons/mrp_operations/mrp_operations_demo.yml
@@ -0,0 +1,24 @@
+-
+ !record {model: mrp.production, id: mrp_production_op}:
+ location_src_id: stock.stock_location_stock
+ product_id: product.product_product_cpu3
+ product_qty: 5.0
+ allow_reorder: True
+-
+ !record {model: mrp.production, id: mrp_production_op1}:
+ location_src_id: stock.stock_location_stock
+ product_id: product.product_product_cpu3
+ product_qty: 2.0
+-
+ !function {model: mrp.production, name: action_compute, id: mrp_production_op1}:
+ - model: mrp.production
+ eval: "[obj(ref('mrp_production_op1')).id]"
+-
+ !workflow {model: mrp.production, action: button_confirm, ref: mrp_production_op1}
+-
+ !record {model: mrp.production, id: mrp_production_mo1}:
+ location_src_id: stock.stock_location_stock
+ product_id: product.product_product_cpu_gen
+ product_qty: 5.0
+-
+ !workflow {model: mrp.production, action: button_confirm, ref: mrp_production_mo1}
diff --git a/addons/mrp_operations/test/mrp_operation_test.yml b/addons/mrp_operations/test/mrp_operation_test.yml
deleted file mode 100644
index 9cb81abebde..00000000000
--- a/addons/mrp_operations/test/mrp_operation_test.yml
+++ /dev/null
@@ -1,56 +0,0 @@
--
- In order to test mrp_operations module in OpenERP,
- I create a production order.
--
- !record {model: mrp.production, id: mrp_production_mo1}:
- company_id: base.main_company
- date_planned: !eval datetime.today().strftime("%Y-%m-%d %H:%M:%S")
- location_dest_id: stock.stock_location_stock
- location_src_id: stock.stock_location_stock
- name: MO/01234567
- product_id: product.product_product_pc1
- product_qty: 5.0
- product_uom: product.product_uom_unit
- product_uos_qty: 5.0
--
- Now I confirm the production order.
--
- !workflow {model: mrp.production, action: button_confirm, ref: mrp_production_mo1}
--
- I check that there is one Work order generated related to the production order.
--
- !python {model: mrp.production.workcenter.line}: |
- from tools.translate import _
- order_id = self.search(cr, uid, [('production_id','=', ref('mrp_production_mo1')),('state','=','draft')])
- assert order_id, _('No work order defined for this production order!')
--
- The scheduler runs.
--
- !function {model: procurement.order, name: run_scheduler}:
- - model: procurement.order
- search: "[('state','=','confirmed')]"
--
- I am checking Internal picking.
--
- !python {model: mrp.production}: |
- from tools.translate import _
- pick_ids = self.browse(cr, uid, ref("mrp_production_mo1"))
- assert pick_ids.picking_id.id, _('No Internal Picking generated!')
--
- In order to cancel the MO, first cancel its picking
--
- !python {model: stock.picking}: |
- mrp_obj = self.pool.get('mrp.production')
- mo = mrp_obj.browse(cr, uid, ref("mrp_production_mo1"))
- self.action_cancel(cr, uid, [mo.picking_id.id], context=None)
--
- Then cancel The Manufacturing order.
--
- !workflow {model: mrp.production, action: button_cancel, ref: mrp_production_mo1}
--
- I check that there is one Work order generated related to the production order that is cancelled or not.
--
- !python {model: mrp.production.workcenter.line}: |
- from tools.translate import _
- order_id = self.search(cr, uid, [('production_id','=', ref('mrp_production_mo1')),('state','=','cancel')])
- assert order_id, _('Work order is not cancelled for this production order!')
diff --git a/addons/mrp_operations/test/mrp_operations.yml b/addons/mrp_operations/test/mrp_operations.yml
deleted file mode 100644
index ce6aac5cdbf..00000000000
--- a/addons/mrp_operations/test/mrp_operations.yml
+++ /dev/null
@@ -1,158 +0,0 @@
--
- In order to test mrp_operations module in OpenERP I will put a Production order
- and check its effects on Work orders.
--
- I create a production order.
--
- !record {model: mrp.production, id: mrp_production_mo0}:
- company_id: base.main_company
- date_planned: !eval datetime.today().strftime("%Y-%m-%d %H:%M:%S")
- location_dest_id: stock.stock_location_stock
- location_src_id: stock.stock_location_stock
- name: MO/0123456
- product_id: product.product_product_pc1
- product_qty: 5.0
- product_uom: product.product_uom_unit
- product_uos_qty: 5.0
- allow_reorder: True
--
- I am computing the data.
--
- !python {model: mrp.production}: |
- self.action_compute(cr, uid, [ref("mrp_production_mo0")], {"lang": "en_US", "tz":
- False, "search_default_current": 1, "active_model": "ir.ui.menu", "active_ids":
- [ref("mrp.menu_mrp_production_action")], "active_id": ref("mrp.menu_mrp_production_action"),
- })
--
- Now I confirm my production order.
--
- !workflow {model: mrp.production, action: button_confirm, ref: mrp_production_mo0}
--
- I check that there is one Work order generated related to my production order.
--
- !python {model: mrp.production.workcenter.line}: |
- from tools.translate import _
- order_id = self.search(cr, uid, [('production_id','=', ref('mrp_production_mo0')),('state','=','draft')])
- assert order_id, _('No Work order define for this production order!')
--
- The scheduler runs.
--
- !function {model: procurement.order, name: run_scheduler}:
- - model: procurement.order
- search: "[('state','=','confirmed')]"
--
- I am checking Internal picking.
--
- !python {model: stock.picking}: |
- from tools.translate import _
- pick_ids = self.search(cr, uid, [('state','!=','done'),('type','=','internal')])
- assert pick_ids, _('No Internal Pickings!')
--
- I see that there is a manufacturing order for the sub product CPU_GEN of PC1 with ready state.
--
- !python {model: mrp.production}: |
- from tools.translate import _
- order_ids = self.search(cr, uid, [('state','=','ready'),('origin','like','%MO/0123456')])
- assert order_ids, _('No new manufacturing order!')
--
- I check that there one more work order created for new production order.
--
- !python {model: mrp.production.workcenter.line}: |
- from tools.translate import _
- prod_obj = self.pool.get('mrp.production')
- prod_order_ids = prod_obj.search(cr, uid, [('state','=','ready'),('origin','like','%MO/0123456')])
- workorder_id = self.search(cr, uid, [('production_id','=', prod_order_ids[0]),('state','=','draft')])
- assert workorder_id, _('No Work order define for this production order!')
--
- I start the second production order of the CPU_GEN product.
--
- !python {model: mrp.production}: |
- import netsvc
- wf_service = netsvc.LocalService("workflow")
- prod_order_ids = self.search(cr, uid, [('state','=','ready'),('origin','like','%MO/0123456')])
- for po in prod_order_ids:
- wf_service.trg_validate(uid, 'mrp.production', po, 'button_produce', cr)
--
- I am creating a mrp.product.produce record
--
- !record {model: mrp.product.produce, id: mrp_product_produce_0}:
- mode: consume_produce
- product_qty: 5.0
--
- I produce the product CPU_GEN.
--
- !python {model: mrp.product.produce}: |
- prod_obj = self.pool.get('mrp.production')
- prod_order_ids = prod_obj.search(cr, uid, [('origin','like','%MO/0123456')])
- self.do_produce(cr, uid, [ref("mrp_product_produce_0")], {"lang": "en_US", "tz":
- False, "search_default_current": 1, "active_model": "mrp.production", "active_ids":
- prod_order_ids, "active_id": prod_order_ids[0], })
--
- I check that my production order and its related work order is in done state.
--
- !python {model: mrp.production.workcenter.line}: |
- from tools.translate import _
- prod_obj = self.pool.get('mrp.production')
- prod_order_ids = prod_obj.search(cr, uid, [('origin','like','%MO/0123456')])
- assert prod_order_ids, _('Workorder not found')
- workorder_id = self.search(cr, uid, [('production_id','=', prod_order_ids[0])])
- workorder_bro = self.browse(cr, uid, workorder_id[0])
- assert workorder_bro.state == 'done', _('Work order is not done! It is %s') % workorder_bro.state
--
- Now I check my original production order is now ready.
--
- !python {model: mrp.production}: |
- from tools.translate import _
- prod_ids = self.search(cr, uid, [('id','=',ref('mrp_production_mo0')),('state','=','ready')])
- assert prod_ids, _('Production order is not ready!')
--
- I check that both internal pickings are done.
--
- !python {model: stock.picking}: |
- from tools.translate import _
- pick_ids = self.search(cr, uid, [('state','=','done'),('type','=','internal')])
- assert pick_ids, _('Internal pickings are not done!')
--
- Now I start my first production order.
--
- !workflow {model: mrp.production, action: button_produce, ref: mrp_production_mo0}
--
- I check that the related work order is in progress state.
--
- !python {model: mrp.production.workcenter.line}: |
- from tools.translate import _
- order_id = self.search(cr, uid, [('production_id','=', ref('mrp_production_mo0')),('state','=','startworking')])
- assert order_id, _('Work order not started yet!')
--
- I am creating a mrp.product.produce record.
--
- !record {model: mrp.product.produce, id: mrp_product_produce_0}:
- mode: consume_produce
- product_qty: 5.0
--
- I produce the product PC1.
--
- !python {model: mrp.product.produce}: |
- prod_obj = self.pool.get('mrp.production')
- prod_order_ids = prod_obj.search(cr, uid, [('state','=','in_production')])
- self.do_produce(cr, uid, [ref("mrp_product_produce_0")], {"lang": "en_US", "tz":
- False, "search_default_current": 1, "active_model": "mrp.production", "active_ids":
- [ref("mrp_production_mo0")], "active_id": ref("mrp_production_mo0"), })
--
- I check the related work order is done.
--
- !python {model: mrp.production.workcenter.line}: |
- from tools.translate import _
- order_id = self.search(cr, uid, [('production_id','=', ref('mrp_production_mo0')),('state','=','done')])
- assert order_id, _('Work order not done yet!')
--
- Calculates start date for stock moves finding interval from resource calendar.
--
- !python {model: mrp.production}: |
- self._move_pass(cr, uid, [ref('mrp_production_mo0')], context=None)
--
- Calculates planned end date of production order.
--
- !python {model: mrp.production}: |
- mo = self.browse(cr, uid, ref("mrp_production_mo0"))
- self._production_date_end(cr, uid, [ref("mrp_production_mo0")], mo.date_planned, False, context=None)
diff --git a/addons/mrp_operations/test/mrp_operations_report.yml b/addons/mrp_operations/test/mrp_operations_report.yml
deleted file mode 100644
index f0a646adf4e..00000000000
--- a/addons/mrp_operations/test/mrp_operations_report.yml
+++ /dev/null
@@ -1,17 +0,0 @@
--
- In order to test the PDF reports defined on a MRP Operations, we will print a Barcode Report
--
- !python {model: mrp_operations.operation.code}: |
- import netsvc, tools, os
- (data, format) = netsvc.LocalService('report.mrp.code.barcode').create(cr, uid, [ref('mrp_operations.mrp_op_1'),ref('mrp_operations.mrp_op_2'),ref('mrp_operations.mrp_op_3'),ref('mrp_operations.mrp_op_4'),ref('mrp_operations.mrp_op_5')], {}, {})
- if tools.config['test_report_directory']:
- file(os.path.join(tools.config['test_report_directory'], 'mrp_operations-barcode_report.'+format), 'wb+').write(data)
-
--
- In order to test the PDF reports defined on a MRP Operations, we will print Workcenter's Barcode Report
--
- !python {model: mrp.workcenter}: |
- import netsvc, tools, os
- (data, format) = netsvc.LocalService('report.mrp.wc.barcode').create(cr, uid, [ref('mrp.mrp_workcenter_0'),ref('mrp.mrp_workcenter_1')], {}, {})
- if tools.config['test_report_directory']:
- file(os.path.join(tools.config['test_report_directory'], 'mrp_operations-workcenter_barcode_report.'+format), 'wb+').write(data)
diff --git a/addons/mrp_operations/test/workcenter_operations.yml b/addons/mrp_operations/test/workcenter_operations.yml
new file mode 100644
index 00000000000..23fbe15c37d
--- /dev/null
+++ b/addons/mrp_operations/test/workcenter_operations.yml
@@ -0,0 +1,120 @@
+-
+ I compute the production order.
+-
+ !python {model: mrp.production}: |
+ order = self.browse(cr, uid, ref("mrp.mrp_production_shelf100cm"), context=context)
+ order.action_compute(context=context)
+-
+ I check planned date in workcenter lines of production order.
+-
+ !python {model: mrp.production}: |
+ order = self.browse(cr, uid, ref("mrp.mrp_production_shelf100cm"), context=context)
+ for line in order.workcenter_lines:
+ #TODO: to check start date of next line should be end of date of previous line.
+ assert line.date_planned, "Planned Start date is not computed: %s" %(line)
+ assert line.date_planned_end, "Planned End date is not computed: %s" %(line)
+
+-
+ I confirm the Production Order.
+-
+ !workflow {model: mrp.production, action: button_confirm, ref: mrp.mrp_production_shelf100cm}
+-
+ I run scheduler.
+-
+ !python {model: procurement.order}: |
+ self.run_scheduler(cr, uid)
+-
+ I forcefully close internal shipment.
+-
+ !python {model: mrp.production}: |
+ self.force_production(cr, uid, [ref("mrp.mrp_production_shelf100cm")])
+-
+ I start production.
+-
+ !workflow {model: mrp.production, action: button_produce, ref: mrp.mrp_production_shelf100cm}
+-
+ Production start on first work center, so I start work operation on first work center.
+-
+ !python {model: mrp.production}: |
+ import netsvc
+ order = self.browse(cr, uid, ref("mrp.mrp_production_shelf100cm"), context=context)
+ wf_service = netsvc.LocalService("workflow")
+ wf_service.trg_validate(uid, 'mrp.production.workcenter.line', order.workcenter_lines[0].id, 'button_start_working', cr)
+-
+ Now I pause first work operation due to technical fault of work center.
+-
+ !python {model: mrp.production}: |
+ import netsvc
+ order = self.browse(cr, uid, ref("mrp.mrp_production_shelf100cm"), context=context)
+ wf_service = netsvc.LocalService("workflow")
+ wf_service.trg_validate(uid, 'mrp.production.workcenter.line', order.workcenter_lines[0].id, 'button_pause', cr)
+ wf_service.trg_validate(uid, 'mrp.production.workcenter.line', order.workcenter_lines[0].id, 'button_resume', cr)
+-
+ I resume first work operation.
+-
+ !python {model: mrp.production}: |
+ import netsvc
+ order = self.browse(cr, uid, ref("mrp.mrp_production_shelf100cm"), context=context)
+ wf_service = netsvc.LocalService("workflow")
+ wf_service.trg_validate(uid, 'mrp.production.workcenter.line', order.workcenter_lines[0].id, 'button_resume', cr)
+
+-
+ I cancel first work operation.
+-
+ !python {model: mrp.production}: |
+ import netsvc
+ order = self.browse(cr, uid, ref("mrp.mrp_production_shelf100cm"), context=context)
+ wf_service = netsvc.LocalService("workflow")
+ wf_service.trg_validate(uid, 'mrp.production.workcenter.line', order.workcenter_lines[0].id, 'button_cancel', cr)
+-
+ I reset first work operation and start after resolve techninal fault of work center.
+-
+ !python {model: mrp.production}: |
+ import netsvc
+ order = self.browse(cr, uid, ref("mrp.mrp_production_shelf100cm"), context=context)
+ wf_service = netsvc.LocalService("workflow")
+ wf_service.trg_validate(uid, 'mrp.production.workcenter.line', order.workcenter_lines[0].id, 'button_draft', cr)
+ wf_service.trg_validate(uid, 'mrp.production.workcenter.line', order.workcenter_lines[0].id, 'button_start_working', cr)
+-
+ Now Finished work of first work operation so I close that operation.
+-
+ !python {model: mrp.production}: |
+ import netsvc
+ order = self.browse(cr, uid, ref("mrp.mrp_production_shelf100cm"), context=context)
+ wf_service = netsvc.LocalService("workflow")
+ wf_service.trg_validate(uid, 'mrp.production.workcenter.line', order.workcenter_lines[0].id, 'button_done', cr)
+-
+ Now I close other operations after start one by one.
+-
+ !python {model: mrp.production}: |
+ import netsvc
+ order = self.browse(cr, uid, ref("mrp.mrp_production_shelf100cm"), context=context)
+ wf_service = netsvc.LocalService("workflow")
+ for work_line in order.workcenter_lines[1:]:
+ wf_service.trg_validate(uid, 'mrp.production.workcenter.line', work_line.id, 'button_start_working', cr)
+ wf_service.trg_validate(uid, 'mrp.production.workcenter.line', work_line.id, 'button_done', cr)
+
+-
+ I check that the production order is now done.
+-
+ !python {model: mrp.production}: |
+ order = self.browse(cr, uid, ref("mrp.mrp_production_shelf100cm"), context=context)
+ print order.state
+ assert order.state == 'done', "Production should be closed after finished all operations."
+-
+ I print a Barcode Report of Operation line.
+-
+ !python {model: mrp_operations.operation.code}: |
+ import netsvc, tools, os
+ (data, format) = netsvc.LocalService('report.mrp.code.barcode').create(cr, uid, [ref('mrp_operations.mrp_op_1'),ref('mrp_operations.mrp_op_2'),ref('mrp_operations.mrp_op_3'),ref('mrp_operations.mrp_op_4'),ref('mrp_operations.mrp_op_5')], {}, {})
+ if tools.config['test_report_directory']:
+ file(os.path.join(tools.config['test_report_directory'], 'mrp_operations-barcode_report.'+format), 'wb+').write(data)
+
+-
+ I print Workcenter's Barcode Report.
+-
+ !python {model: mrp.workcenter}: |
+ import netsvc, tools, os
+ (data, format) = netsvc.LocalService('report.mrp.wc.barcode').create(cr, uid, [ref('mrp.mrp_workcenter_0'),ref('mrp.mrp_workcenter_1')], {}, {})
+ if tools.config['test_report_directory']:
+ file(os.path.join(tools.config['test_report_directory'], 'mrp_operations-workcenter_barcode_report.'+format), 'wb+').write(data)
diff --git a/addons/point_of_sale/point_of_sale.py b/addons/point_of_sale/point_of_sale.py
index 74f6fb54368..304b325128c 100644
--- a/addons/point_of_sale/point_of_sale.py
+++ b/addons/point_of_sale/point_of_sale.py
@@ -325,7 +325,11 @@ class pos_order(osv.osv):
}
return abs
+ def action_invoice_state(self, cr, uid, ids, context=None):
+ return self.write(cr, uid, ids, {'state':'invoiced'}, context=context)
+
def action_invoice(self, cr, uid, ids, context=None):
+ wf_service = netsvc.LocalService("workflow")
inv_ref = self.pool.get('account.invoice')
inv_line_ref = self.pool.get('account.invoice.line')
product_obj = self.pool.get('product.product')
@@ -341,7 +345,7 @@ class pos_order(osv.osv):
acc = order.partner_id.property_account_receivable.id
inv = {
- 'name': 'Invoice from POS: '+order.name,
+ 'name': order.name,
'origin': order.name,
'account_id': acc,
'journal_id': order.sale_journal.id or None,
@@ -379,6 +383,7 @@ class pos_order(osv.osv):
and [(6, 0, inv_line['invoice_line_tax_id'])] or []
inv_line_ref.create(cr, uid, inv_line, context=context)
inv_ref.button_reset_taxes(cr, uid, [inv_id], context=context)
+ wf_service.trg_validate(uid, 'pos.order', order.id, 'invoice', cr)
if not inv_ids: return {}
@@ -682,10 +687,44 @@ pos_order_line()
class pos_category(osv.osv):
_name = 'pos.category'
- _inherit = 'product.category'
+ _description = "PoS Category"
+ _order = "sequence, name"
+ def _check_recursion(self, cr, uid, ids, context=None):
+ level = 100
+ while len(ids):
+ cr.execute('select distinct parent_id from pos_category where id IN %s',(tuple(ids),))
+ ids = filter(None, map(lambda x:x[0], cr.fetchall()))
+ if not level:
+ return False
+ level -= 1
+ return True
+
+ _constraints = [
+ (_check_recursion, 'Error ! You cannot create recursive categories.', ['parent_id'])
+ ]
+
+ def name_get(self, cr, uid, ids, context=None):
+ if not len(ids):
+ return []
+ reads = self.read(cr, uid, ids, ['name','parent_id'], context=context)
+ res = []
+ for record in reads:
+ name = record['name']
+ if record['parent_id']:
+ name = record['parent_id'][1]+' / '+name
+ res.append((record['id'], name))
+ return res
+
+ def _name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None):
+ res = self.name_get(cr, uid, ids, context=context)
+ return dict(res)
+
_columns = {
+ 'name': fields.char('Name', size=64, required=True, translate=True),
+ 'complete_name': fields.function(_name_get_fnc, type="char", string='Name'),
'parent_id': fields.many2one('pos.category','Parent Category', select=True),
- 'child_id': fields.one2many('pos.category', 'parent_id', string='Child Categories'),
+ 'child_id': fields.one2many('pos.category', 'parent_id', string='Children Categories'),
+ 'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of product categories."),
}
pos_category()
diff --git a/addons/point_of_sale/point_of_sale_view.xml b/addons/point_of_sale/point_of_sale_view.xml
index 2d9345ffd83..5e5c23bf7e9 100644
--- a/addons/point_of_sale/point_of_sale_view.xml
+++ b/addons/point_of_sale/point_of_sale_view.xml
@@ -16,8 +16,8 @@
-
-
+
+
@@ -587,9 +587,12 @@
form
-
-
-
+
+
+
+
+
+
@@ -609,6 +612,20 @@
+
+ pos.category.form
+ pos.category
+ form
+
+
+
+
+
+
+
+
+
+ pos.category.treepos.category
@@ -616,7 +633,8 @@
-
+
+
diff --git a/addons/point_of_sale/point_of_sale_workflow.xml b/addons/point_of_sale/point_of_sale_workflow.xml
index 4058af2696f..4daa2d17099 100644
--- a/addons/point_of_sale/point_of_sale_workflow.xml
+++ b/addons/point_of_sale/point_of_sale_workflow.xml
@@ -34,7 +34,7 @@
invoicedTrue
- action_invoice()
+ action_invoice_state()function
diff --git a/addons/procurement/__openerp__.py b/addons/procurement/__openerp__.py
index 30198b56f83..d10e1874d68 100644
--- a/addons/procurement/__openerp__.py
+++ b/addons/procurement/__openerp__.py
@@ -59,6 +59,7 @@ depending on the product's configuration.
'board_mrp_procurement_view.xml',
],
'demo_xml': ['stock_orderpoint.xml'],
+ 'test': ['test/procurement.yml'],
'installable': True,
'active': False,
'certificate': '00954248826881074509',
diff --git a/addons/procurement/procurement.py b/addons/procurement/procurement.py
index 9556b1aa081..91461f794cc 100644
--- a/addons/procurement/procurement.py
+++ b/addons/procurement/procurement.py
@@ -63,7 +63,6 @@ mrp_property()
class StockMove(osv.osv):
_inherit = 'stock.move'
-
_columns= {
'procurements': fields.one2many('procurement.order', 'move_id', 'Procurements'),
}
@@ -154,11 +153,11 @@ class procurement_order(osv.osv):
return {'value': v}
return {}
- def check_product(self, cr, uid, ids):
+ def check_product(self, cr, uid, ids, context=None):
""" Checks product type.
@return: True or False
"""
- return all(procurement.product_id.type in ('product', 'consu') for procurement in self.browse(cr, uid, ids))
+ return all(proc.product_id.type in ('product', 'consu') for proc in self.browse(cr, uid, ids, context=context))
def check_move_cancel(self, cr, uid, ids, context=None):
""" Checks if move is cancelled or not.
@@ -174,9 +173,9 @@ class procurement_order(osv.osv):
""" Checks if move is done or not.
@return: True or False.
"""
- if not context:
- context = {}
- return all(not procurement.move_id or procurement.move_id.state == 'done' for procurement in self.browse(cr, uid, ids, context=context))
+ return all(proc.product_id.type == 'service' or (proc.move_id and proc.move_id.state == 'done') \
+ for proc in self.browse(cr, uid, ids, context=context))
+
#
# This method may be overrided by objects that override procurement.order
# for computing their own purpose
@@ -258,26 +257,25 @@ class procurement_order(osv.osv):
def check_produce(self, cr, uid, ids, context=None):
""" Checks product type.
- @return: True or Product Id.
+ @return: True or False
"""
- res = True
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
for procurement in self.browse(cr, uid, ids, context=context):
- if procurement.product_id.product_tmpl_id.supply_method <> 'produce':
- partner_list = sorted([(partner_id.sequence, partner_id) for partner_id in procurement.product_id.seller_ids if partner_id])
- if partner_list:
- partner = partner_list and partner_list[0] and partner_list[0][1] and partner_list[0][1].name or False
- if user.company_id and user.company_id.partner_id:
- if partner.id == user.company_id.partner_id.id:
- return True
+ product = procurement.product_id
+ #TOFIX: if product type is 'service' but supply_method is 'buy'.
+ if product.supply_method <> 'produce':
+ supplier = product.seller_id
+ if supplier and user.company_id and user.company_id.partner_id:
+ if supplier.id == user.company_id.partner_id.id:
+ continue
return False
- if procurement.product_id.product_tmpl_id.type=='service':
- res = res and self.check_produce_service(cr, uid, procurement, context)
+ if product.type=='service':
+ res = self.check_produce_service(cr, uid, procurement, context)
else:
- res = res and self.check_produce_product(cr, uid, procurement, context)
+ res = self.check_produce_product(cr, uid, procurement, context)
if not res:
return False
- return res
+ return True
def check_buy(self, cr, uid, ids):
""" Checks product type.
@@ -483,7 +481,7 @@ class StockPicking(osv.osv):
if move.state == 'done' and move.procurements:
for procurement in move.procurements:
wf_service.trg_validate(user, 'procurement.order',
- procurement.id, 'button_check', cursor)
+ procurement.id, 'button_check', cursor)
return res
StockPicking()
diff --git a/addons/procurement/procurement_workflow.xml b/addons/procurement/procurement_workflow.xml
index 23b0a08af78..53b6608fa6f 100644
--- a/addons/procurement/procurement_workflow.xml
+++ b/addons/procurement/procurement_workflow.xml
@@ -50,12 +50,14 @@
produce_check
+
produce_servicefunctionaction_produce_assign_service()
+
ready
@@ -163,18 +165,28 @@
check_produce()
-
-
-
- not check_product()
-
+
-
+ True
+
+
+
+
+
+
+
+ not check_product()
+
@@ -184,6 +196,7 @@
+
diff --git a/addons/procurement/test/procurement.yml b/addons/procurement/test/procurement.yml
new file mode 100644
index 00000000000..4c59d0c7b7c
--- /dev/null
+++ b/addons/procurement/test/procurement.yml
@@ -0,0 +1,88 @@
+-
+ For test the procurement process, First I have to apply a minimum stock rule on product
+-
+ I create minimum stock rule for product.
+-
+ !record {model: stock.warehouse.orderpoint, id: stock_warehouse_orderpoint_op0}:
+ company_id: base.main_company
+ location_id: stock.stock_location_stock
+ logic: max
+ name: OP/00008
+ product_id: product.product_product_cpu2
+ product_max_qty: 15.0
+ product_min_qty: 5.0
+ product_uom: product.product_uom_kgm
+ qty_multiple: 1
+ warehouse_id: stock.warehouse0
+-
+ Check product quantity and update it, if needed for apply a minimum stock rule.
+-
+ !python {model: product.product}: |
+ product = self.browse(cr, uid, ref('product.product_product_cpu2'))
+ if product.virtual_available < 5.0:
+ change_qty = self.pool.get('stock.change.product.qty')
+ id = change_qty.create(cr, uid, {'location_id' : ref('stock.stock_location_stock'), 'new_quantity': 4, 'product_id': product.id})
+ change_qty.change_product_qty(cr, uid, [id], {'active_model':'product.product', 'active_id': product.id, 'active_ids':[product.id]})
+ assert product.qty_available == 4,"Product quantity is not updated."
+ assert product.virtual_available < 5.0,'Virtual stock have more quantities.'
+-
+ I run the scheduler.
+-
+ !python {model: procurement.order}: |
+ self.run_scheduler(cr, uid)
+-
+ I check that procurement order is based on minimum stock rule.
+-
+ !python {model: procurement.order}: |
+ proc_ids = self.search(cr, uid, [('product_id','=', ref('product.product_product_cpu2'))])
+ assert proc_ids, 'No Procurement created.'
+ proc_order = self.browse(cr, uid, proc_ids)[0]
+ assert proc_order.product_qty == 11.0,"Procurement product quantity is not corresponded."
+-
+ I check product quantity.
+-
+ !python {model: product.product}: |
+ product = self.browse(cr, uid, ref('product.product_product_cpu2'))
+ assert product.virtual_available == 15.0,"After run the scheduler product's virtual stock is not updated."
+-
+ For test the Procurement Request wizard, Again I have to update product quantity.
+-
+ !python {model: product.product}: |
+ mk_procure = self.pool.get('make.procurement')
+ procur_order = self.pool.get('procurement.order')
+ product = self.browse(cr, uid, ref('product.product_product_cpu2'))
+
+ context.update({'active_model': 'product.product','active_id':ref('product.product_product_cpu2')})
+ values = {'warehouse_id': ref('base.main_company'), 'uom_id': ref('product.product_uom_unit'), 'qty': 5}
+ id = mk_procure.create(cr, uid, values, context)
+ procurement = mk_procure.make_procurement(cr, uid, [id], context)
+ assert product.virtual_available == 20.0, 'Virtual stock should be updated'
+
+ proc_id = procurement.get('res_id')
+ for procurement in procur_order.browse(cr, uid, [proc_id]):
+ if procurement.state == 'confirmed':
+ assert procurement.state == 'confirmed',"Procurement state should be 'Confirmed'."
+ assert procurement.product_id.id == ref('product.product_product_cpu2'),"Product is not correspond."
+ assert procurement.product_qty == 5,"Product Quantity is not correspond."
+ assert procurement.product_uom.id == ref('product.product_uom_unit'),"Product's UOM is not correspond."
+ context.update({'proc': proc_id})
+-
+ I run the scheduler.
+-
+ !python {model: procurement.order}: |
+ self.run_scheduler(cr, uid)
+-
+ I check the current state of procurement.
+-
+ !python {model: procurement.order}: |
+ proc_id = context.get('proc')
+ proc = self.browse(cr, uid, [proc_id])[0]
+ assert proc.state == 'ready' or 'exception',"Procurement should be in Ready or Exception state"
+-
+ I compute minimum stock.
+-
+ !python {model: procurement.orderpoint.compute}: |
+ proc_id = context.get('proc')
+ context.update({'active_model': 'procurement.order', 'active_id': proc_id})
+ id = self.create(cr, uid, {'automatic': True}, context)
+ self.procure_calculation(cr, uid, [id], context)
diff --git a/addons/product/product_demo.xml b/addons/product/product_demo.xml
index 3aebec13715..99347667f80 100644
--- a/addons/product/product_demo.xml
+++ b/addons/product/product_demo.xml
@@ -442,6 +442,16 @@
product
+
+ SPAN100
+ produce
+
+
+
+ Shelf Panel
+ product
+
+ WOOD002buy
@@ -455,6 +465,19 @@
+
+ WOOD010
+ buy
+ 7.0
+
+
+ Wood 10mm
+
+
+ product
+
+
+
PROJproduce
@@ -509,7 +532,7 @@
RPAN100
- buy
+ produce10.0
@@ -548,7 +571,7 @@
RCK100
- buy
+ produce5.0
diff --git a/addons/product/product_view.xml b/addons/product/product_view.xml
index 6d9483f81ab..38b9d2d0ed1 100644
--- a/addons/product/product_view.xml
+++ b/addons/product/product_view.xml
@@ -56,7 +56,7 @@
-
+
@@ -100,9 +100,10 @@
-
-
+
+
@@ -637,8 +638,9 @@
-
+
diff --git a/addons/project/wizard/project_task_delegate.py b/addons/project/wizard/project_task_delegate.py
index efadc3f124b..544165dc02b 100644
--- a/addons/project/wizard/project_task_delegate.py
+++ b/addons/project/wizard/project_task_delegate.py
@@ -63,25 +63,25 @@ class project_task_delegate(osv.osv_memory):
task_name =tools.ustr(task.name)
if 'project_id' in fields:
- res.update({'project_id': task.project_id and task.project_id.id})
+ res['project_id'] = int(task.project_id.id) if task.project_id else False
if 'name' in fields:
if task_name.startswith(_('CHECK: ')):
newname = tools.ustr(task_name).replace(_('CHECK: '), '')
else:
newname = tools.ustr(task_name or '')
- res.update({'name': newname})
+ res['name'] = newname
if 'planned_hours' in fields:
- res.update({'planned_hours': task.remaining_hours or 0.0})
+ res['planned_hours'] = task.remaining_hours or 0.0
if 'prefix' in fields:
if task_name.startswith(_('CHECK: ')):
newname = tools.ustr(task_name).replace(_('CHECK: '), '')
else:
newname = tools.ustr(task_name or '')
prefix = _('CHECK: %s') % newname
- res.update({'prefix': prefix})
+ res['prefix'] = prefix
if 'new_task_description' in fields:
- res.update({'new_task_description': task.description})
+ res['new_task_description'] = task.description
return res
diff --git a/addons/project_long_term/project_long_term.py b/addons/project_long_term/project_long_term.py
index b6647b6de2b..d5c091a8796 100644
--- a/addons/project_long_term/project_long_term.py
+++ b/addons/project_long_term/project_long_term.py
@@ -180,7 +180,7 @@ class project_phase(osv.osv):
'months': 'm', 'month':'month', 'm':'m',
'weeks': 'w', 'week': 'w', 'w':'w',
'hours': 'H', 'hour': 'H', 'h':'H',
- }.get(phase.product_uom.name.lower(), "h")
+ }.get(phase.product_uom.name.lower(), "H")
duration = str(phase.duration) + duration_uom
result += '''
def Phase_%s():
diff --git a/addons/project_mrp/__openerp__.py b/addons/project_mrp/__openerp__.py
index e5722b92da9..c36b3229a81 100644
--- a/addons/project_mrp/__openerp__.py
+++ b/addons/project_mrp/__openerp__.py
@@ -54,7 +54,7 @@ task is completed.
'depends': ['project', 'procurement', 'sale', 'mrp_jit'],
'init_xml': [],
'update_xml': ['project_mrp_workflow.xml', 'process/project_mrp_process.xml', 'project_mrp_view.xml'],
- 'demo_xml': [],
+ 'demo_xml': ['project_mrp_demo.xml'],
'test': ['test/project_task_procurement.yml'],
'installable': True,
'active': False,
diff --git a/addons/project_mrp/project_mrp.py b/addons/project_mrp/project_mrp.py
index 3bbb0658b11..a3cde855b6c 100644
--- a/addons/project_mrp/project_mrp.py
+++ b/addons/project_mrp/project_mrp.py
@@ -31,10 +31,10 @@ class project_task(osv.osv):
}
def _validate_subflows(self, cr, uid, ids):
+ wf_service = netsvc.LocalService("workflow")
for task in self.browse(cr, uid, ids):
if task.procurement_id:
- wf_service = netsvc.LocalService("workflow")
- wf_service.trg_validate(uid, 'procurement.order', task.procurement_id.id, 'subflow.done', cr)
+ wf_service.trg_write(uid, 'procurement.order', task.procurement_id.id, cr)
def do_close(self, cr, uid, ids, *args, **kwargs):
res = super(project_task, self).do_close(cr, uid, ids, *args, **kwargs)
diff --git a/addons/project_mrp/project_mrp_demo.xml b/addons/project_mrp/project_mrp_demo.xml
new file mode 100644
index 00000000000..fcc0b27d31f
--- /dev/null
+++ b/addons/project_mrp/project_mrp_demo.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+ Advance
+
+
+ 150.0
+ 5.0
+ make_to_order
+
+
+
+
diff --git a/addons/project_mrp/project_mrp_workflow.xml b/addons/project_mrp/project_mrp_workflow.xml
index 751634816e3..18962cde0ee 100644
--- a/addons/project_mrp/project_mrp_workflow.xml
+++ b/addons/project_mrp/project_mrp_workflow.xml
@@ -1,10 +1,12 @@
-
-
-
- subflow.done
+
+
+
+ action_check_finished()
+ project.task
+ task_id and [task_id.id] or []
diff --git a/addons/project_mrp/project_procurement.py b/addons/project_mrp/project_procurement.py
index 2c9732478fb..7d3045aede0 100644
--- a/addons/project_mrp/project_procurement.py
+++ b/addons/project_mrp/project_procurement.py
@@ -29,29 +29,46 @@ class procurement_order(osv.osv):
'sale_line_id': fields.many2one('sale.order.line', 'Sale order line')
}
- def check_produce_service(self, cr, uid, procurement, context=None):
+ def action_check_finished(self, cr, uid, ids):
+ res = super(procurement_order, self).action_check_finished(cr, uid, ids)
+ return res and self.check_task_done(cr, uid, ids)
+
+ def check_task_done(self, cr, uid, ids, context=None):
+ """ Checks if task is done or not.
+ @return: True or False.
+ """
+ return all(proc.product_id.type != 'service' or (proc.task_id and proc.task_id.state in ('done', 'cancelled')) \
+ for proc in self.browse(cr, uid, ids, context=context))
+
+ def check_produce_service(self, cr, uid, procurement, context=None):
return True
- def action_produce_assign_service(self, cr, uid, ids, context=None):
- project_obj = self.pool.get('project.project')
- uom_obj = self.pool.get('product.uom')
- default_uom = self.pool.get('res.users').browse(cr, uid, uid).company_id.project_time_mode_id.id
- for procurement in self.browse(cr, uid, ids, context=context):
- project_id = False
- if procurement.product_id.project_id:
- project_id = procurement.product_id.project_id.id
- elif procurement.sale_line_id:
- account_id = procurement.sale_line_id.order_id.project_id.id
- if account_id:
- project_ids = project_obj.search(cr, uid, [('analytic_account_id', '=', account_id)])
- project_id = project_ids and project_ids[0] or False
- if procurement.product_uom.id != default_uom:
- planned_hours = uom_obj._compute_qty(cr, uid, procurement.product_uom.id, procurement.product_qty, default_uom)
- else:
- planned_hours = procurement.product_qty
+ def _convert_qty_company_hours(self, cr, uid, procurement, context=None):
+ product_uom = self.pool.get('product.uom')
+ company_time_uom_id = self.pool.get('res.users').browse(cr, uid, uid).company_id.project_time_mode_id.id
+ if procurement.product_uom.id != company_time_uom_id:
+ planned_hours = product_uom._compute_qty(cr, uid, procurement.product_uom.id, procurement.product_qty, company_time_uom_id)
+ else:
+ planned_hours = procurement.product_qty
+ return planned_hours
- self.write(cr, uid, [procurement.id], {'state': 'running'})
- task_id = self.pool.get('project.task').create(cr, uid, {
+ def _get_project(self, cr, uid, procurement, context=None):
+ project_project = self.pool.get('project.project')
+ project = procurement.product_id.project_id
+ if not project and procurement.sale_line_id:
+ # find the project corresponding to the analytic account of the sale order
+ account = procurement.sale_line_id.order_id.project_id
+ project_ids = project_project.search(cr, uid, [('analytic_account_id', '=', account.id)])
+ projects = project_project.browse(cr, uid, project_ids, context=context)
+ project = projects and projects[0] or False
+ return project
+
+ def action_produce_assign_service(self, cr, uid, ids, context=None):
+ project_task = self.pool.get('project.task')
+ for procurement in self.browse(cr, uid, ids, context=context):
+ project = self._get_project(cr, uid, procurement, context=context)
+ planned_hours = self._convert_qty_company_hours(cr, uid, procurement, context=context)
+ task_id = project_task.create(cr, uid, {
'name': '%s:%s' % (procurement.origin or '', procurement.product_id.name),
'date_deadline': procurement.date_planned,
'planned_hours':planned_hours,
@@ -60,12 +77,10 @@ class procurement_order(osv.osv):
'notes': procurement.note,
'procurement_id': procurement.id,
'description': procurement.note,
- 'date_deadline': procurement.date_planned,
- 'project_id': project_id,
- 'state': 'draft',
+ 'project_id': project and project.id or False,
'company_id': procurement.company_id.id,
},context=context)
- self.write(cr, uid, [procurement.id],{'task_id':task_id})
+ self.write(cr, uid, [procurement.id], {'task_id': task_id, 'state': 'running'}, context=context)
return task_id
procurement_order()
diff --git a/addons/project_mrp/test/project_task_procurement.yml b/addons/project_mrp/test/project_task_procurement.yml
index b2cc6a68363..b72527e61a5 100644
--- a/addons/project_mrp/test/project_task_procurement.yml
+++ b/addons/project_mrp/test/project_task_procurement.yml
@@ -1,83 +1,48 @@
-- |
- In order to test project_mrp module with OpenERP I create a sale order
- with product type 'service' so when procurement runs one task is created for
- the project associated with my sale order.
-
- I create record for a service type product.
+ In order to test process to generate task automatic from procurement, I confirm sale order to sale service product.
-
- !record {model: product.product, id: product_product_partnerstraining0, view: False}:
- categ_id: product.product_category_7
- cost_method: standard
- mes_type: fixed
- name: Partners Training
- procure_method: make_to_order
- supply_method: produce
- type: service
- uom_id: product.uom_day
- uom_po_id: product.uom_day
- warranty: 0.0
-- |
- I create a sale order for product Partners Training which has type 'Service',
- and select the appropriate Analytic Account matching my project.
--
- !record {model: sale.order, id: sale_order_so0}:
- date_order: !eval time.strftime('%Y-%m-%d')
- invoice_quantity: order
- name: TESTSO006
- order_policy: manual
- partner_id: base.res_partner_asus
- partner_invoice_id: base.res_partner_address_tang
- partner_order_id: base.res_partner_address_tang
- partner_shipping_id: base.res_partner_address_tang
- order_line:
- - state: draft
- delay: 7.0
- name: Partners Training
- price_unit: 1.0
- product_id: product_product_partnerstraining0
- product_uom: product.uom_day
- product_uom_qty: 5.0
- type: make_to_order
- picking_policy: direct
- pricelist_id: product.list0
- shop_id: sale.shop
- user_id: base.user_demo
-
-- I select the Analytic Account for my project on the sale order
--
- !python {model: sale.order}: |
- acc_id = self.pool.get('project.project').browse(cr, uid,
- ref('project.project_integrate_openerp')).analytic_account_id.id
- self.write(cr, uid, ref('sale_order_so0'), {'project_id': acc_id})
+ !workflow {model: sale.order, action: order_confirm, ref: sale.order7}
-
- I confirm this sale order.
--
- !workflow {model: sale.order, action: order_confirm, ref: sale_order_so0}
--
- I check the procurements.
+ I run the scheduler.
-
!python {model: procurement.order}: |
- orderline_obj = self.pool.get('sale.order.line')
- line_ids = orderline_obj.search(cr, uid, [('order_id','=', ref('sale_order_so0'))])
- orders = orderline_obj.browse(cr, uid, line_ids)
- proc_ids = map(lambda x: x.procurement_id.id, orders)
- assert proc_ids, 'No Procurements!'
+ self.run_scheduler(cr, uid)
-
- The scheduler runs.
+ Now I check that task details after run procurement
-
- !function {model: procurement.order, name: run_scheduler}:
- - model: procurement.order
- search: "[]"
+ !python {model: procurement.order}: |
+ from datetime import datetime
+ procurement_ids = self.search(cr, uid, [('sale_line_id', '=', ref('line_services'))])
+ assert procurement_ids, "Procurement is not generated for Service Order Line."
+ procurement = self.browse(cr, uid, procurement_ids[0], context=context)
+ assert procurement.state != 'done' , "Procurement should not be closed."
+ task = procurement.task_id
+ assert task, "Task is not generated."
+ # check whether task project either is the product's project, or corresponds to the analytic account of sale order
+ project = task.project_id
+ if procurement.product_id.project_id:
+ assert project == procurement.product_id.project_id, "Project does not correspond."
+ elif procurement.sale_line_id:
+ account = procurement.sale_line_id.order_id.project_id
+ assert (not project and not account) or project.analytic_account_id == account, "Project does not correspond."
+ planned_hours = self._convert_qty_company_hours(cr, uid, procurement, context=context)
+ assert task.planned_hours == planned_hours, 'Planned Hours do not correspond.'
+ assert datetime.strptime(task.date_deadline, '%Y-%m-%d') == datetime.strptime(procurement.date_planned, '%Y-%m-%d %H:%M:%S'), 'Deadline does not correspond.'
+ if procurement.product_id.product_manager:
+ assert task.user_id.id == procurement.product_id.product_manager.id, 'Allocated Person does not correspond with Service Product Manager.'
+ assert task.description == procurement.note, "Task description does not correspond."
-
- Now I check that one task is created for my sale order, in the desired project
+ I close that task.
-
!python {model: project.task}: |
- order_obj = self.pool.get('sale.order')
- order = order_obj.browse(cr, uid, ref('sale_order_so0'))
- # planned_hours == 40 because default company project UOM is hours, and
- # product was sold as 5.0 days.
- task_id = self.search(cr, uid, [('name', '=', order.name+":Partners Training"),
- ('project_id','=', ref('project.project_integrate_openerp')),
- ('planned_hours','=', 40.0),
- ('state','=','draft')])
- assert task_id, 'Expected Task not found!'
\ No newline at end of file
+ task_ids = self.search(cr, uid, [('sale_line_id', '=', ref('line_services'))])
+ assert task_ids, "Task is not generated for Service Order Line."
+ self.do_close(cr, uid, task_ids, context=context)
+-
+ I check procurement of Service Order Line after closed task.
+-
+ !python {model: procurement.order}: |
+ procurement_ids = self.search(cr, uid, [('sale_line_id', '=', ref('line_services'))])
+ assert procurement_ids, "Procurement is not generated for Service Order Line."
+ procurement = self.browse(cr, uid, procurement_ids[0], context=context)
+ assert procurement.state == 'done' , "Procurement should be closed."
diff --git a/addons/sale/__openerp__.py b/addons/sale/__openerp__.py
index dc86b22b40f..948352940a0 100644
--- a/addons/sale/__openerp__.py
+++ b/addons/sale/__openerp__.py
@@ -87,18 +87,14 @@ Dashboard for Sales Manager that includes:
],
'demo_xml': ['sale_demo.xml'],
'test': [
- 'test/edi_sale_order.yml',
- 'test/data_test.yml',
- 'test/manual_order_policy.yml',
- 'test/prepaid_order_policy.yml',
+ 'test/sale_order_demo.yml',
'test/picking_order_policy.yml',
+ 'test/manual_order_policy.yml',
'test/postpaid_order_policy.yml',
- 'test/advance_invoice.yml',
- 'test/so_make_line_invoice.yml',
- 'test/sale_procurement.yml',
- 'test/invoice_on_ordered_qty.yml',
- 'test/invoice_on_shipped_qty.yml',
- 'test/sale_report.yml',
+ 'test/prepaid_order_policy.yml',
+ 'test/cancel_order.yml',
+ 'test/delete_order.yml',
+ 'test/edi_sale_order.yml',
],
'installable': True,
'active': False,
diff --git a/addons/sale/report/sale_report_view.xml b/addons/sale/report/sale_report_view.xml
index 7cc40c30645..5cc7c4f5ca1 100644
--- a/addons/sale/report/sale_report_view.xml
+++ b/addons/sale/report/sale_report_view.xml
@@ -128,7 +128,7 @@
This report performs analysis on your quotations and sales orders. Analysis check your sales revenues and sort it by different group criteria (salesman, partner, product, etc.) Use this report to perform analysis on sales not having invoiced yet. If you want to analyse your turnover, you should use the Invoice Analysis report in the Accounting application.
-
+
diff --git a/addons/sale/sale.py b/addons/sale/sale.py
index 9f53b5cfd24..6d89b70c865 100644
--- a/addons/sale/sale.py
+++ b/addons/sale/sale.py
@@ -324,7 +324,6 @@ class sale_order(osv.osv):
return True
def onchange_pricelist_id(self, cr, uid, ids, pricelist_id, order_lines, context={}):
- print order_lines
if (not pricelist_id) or (not order_lines):
return {}
warning = {
@@ -718,7 +717,7 @@ class sale_order(osv.osv):
'date_expected': date_planned,
'product_qty': line.product_uom_qty,
'product_uom': line.product_uom.id,
- 'product_uos_qty': line.product_uos_qty,
+ 'product_uos_qty': (line.product_uos and line.product_uos_qty) or line.product_uom_qty,
'product_uos': (line.product_uos and line.product_uos.id)\
or line.product_uom.id,
'product_packaging': line.product_packaging.id,
@@ -750,6 +749,28 @@ class sale_order(osv.osv):
'company_id': order.company_id.id,
}
+ def ship_recreate(self, cr, uid, order, line, move_id, proc_id):
+ # FIXME: deals with potentially cancelled shipments, seems broken (specially if shipment has production lot)
+ """
+ Define ship_recreate for process after shipping exception
+ param order: sale order to which the order lines belong
+ param line: sale order line records to procure
+ param move_id: the ID of stock move
+ param proc_id: the ID of procurement
+ """
+ move_obj = self.pool.get('stock.move')
+ if order.state == 'shipping_except':
+ for pick in order.picking_ids:
+ for move in pick.move_lines:
+ if move.state == 'cancel':
+ mov_ids = move_obj.search(cr, uid, [('state', '=', 'cancel'),('sale_line_id', '=', line.id),('picking_id', '=', pick.id)])
+ if mov_ids:
+ for mov in move_obj.browse(cr, uid, mov_ids):
+ # FIXME: the following seems broken: what if move_id doesn't exist? What if there are several mov_ids? Shouldn't that be a sum?
+ move_obj.write(cr, uid, [move_id], {'product_qty': mov.product_qty, 'product_uos_qty': mov.product_uos_qty})
+ self.pool.get('procurement.order').write(cr, uid, [proc_id], {'product_qty': mov.product_qty, 'product_uos_qty': mov.product_uos_qty})
+ return True
+
def _create_pickings_and_procurements(self, cr, uid, order, order_lines, picking_id=False, *args):
"""Create the required procurements to supply sale order lines, also connecting
the procurements to appropriate stock moves in order to bring the goods to the
@@ -772,8 +793,8 @@ class sale_order(osv.osv):
move_obj = self.pool.get('stock.move')
picking_obj = self.pool.get('stock.picking')
procurement_obj = self.pool.get('procurement.order')
-
proc_ids = []
+
for line in order_lines:
if line.state == 'done':
continue
@@ -793,19 +814,7 @@ class sale_order(osv.osv):
proc_id = procurement_obj.create(cr, uid, self._prepare_order_line_procurement(cr, uid, order, line, move_id, date_planned, *args))
proc_ids.append(proc_id)
line.write({'procurement_id': proc_id})
-
- # FIXME: deals with potentially cancelled shipments, seems broken, see below
- # FIXME: was introduced by revid: mtr@mtr-20101125100355-0a1b7m792t63mssv
- if order.state == 'shipping_except':
- for pick in order.picking_ids:
- for move in pick.move_lines:
- if move.state == 'cancel':
- mov_ids = move_obj.search(cr, uid, [('state', '=', 'cancel'),('sale_line_id', '=', line.id),('picking_id', '=', pick.id)])
- if mov_ids:
- for mov in move_obj.browse(cr, uid, mov_ids):
- # FIXME: the following seems broken: what if move_id doesn't exist? What if there are several mov_ids? Shouldn't that be a sum?
- move_obj.write(cr, uid, [move_id], {'product_qty': mov.product_qty, 'product_uos_qty': mov.product_uos_qty})
- procurement_obj.write(cr, uid, [proc_id], {'product_qty': mov.product_qty, 'product_uos_qty': mov.product_uos_qty})
+ self.ship_recreate(cr, uid, order, line, move_id, proc_id)
wf_service = netsvc.LocalService("workflow")
if picking_id:
diff --git a/addons/sale/sale_demo.xml b/addons/sale/sale_demo.xml
index 4fcce85c5b5..5da496a1c4b 100644
--- a/addons/sale/sale_demo.xml
+++ b/addons/sale/sale_demo.xml
@@ -12,6 +12,9 @@
+ picking
+ procurement
+ Invoice after delivery
@@ -19,9 +22,9 @@
New server config + material
-
-
- 123
+
+
+ 123.20make_to_stock
@@ -30,20 +33,20 @@
[PC1] Basic PC
- 450
+ 450.5033make_to_stock
- [PC1] Basic PC
-
+ [PC3] Medium PC
+
- 450
- 3
- 3
+ 900
+ 5make_to_stock
+ 1
@@ -66,6 +69,9 @@
+ order
+ postpaid
+
@@ -99,6 +105,7 @@
+ prepaid
@@ -120,7 +127,6 @@
make_to_order7
-
@@ -176,6 +182,16 @@
make_to_order15
+
+
+ [CPU1] Processor AMD Athlon XP 1800+
+
+
+ 75
+ 3
+ 3
+ make_to_stock
+
@@ -228,7 +244,7 @@
[MB1] Mainboard ASUStek A7N8X
- 4
+ 15250make_to_order15
@@ -238,13 +254,12 @@
[MB2] Mainboard ASUStek A7V8X-X
- 4
+ 5500make_to_order15
-
-
+
@@ -257,8 +272,9 @@
service150.0100.0
-
-
+ produce
+
+
diff --git a/addons/sale/test/advance_invoice.yml b/addons/sale/test/advance_invoice.yml
deleted file mode 100644
index 06bd0a309f5..00000000000
--- a/addons/sale/test/advance_invoice.yml
+++ /dev/null
@@ -1,144 +0,0 @@
--
- In order to test the Deposit wizard of sale module in the Open-ERP,
- I create a Sale Order for LG Viewty Smart for qty 100 having order_policy manual.
--
- !record {model: sale.order, id: sale_order_so5}:
- invoice_quantity: order
- order_line:
- - product_uom_qty: 100.0
- product_id: sale.product_product_lgviewtysmart0
- name: LG View
- product_uos_qty: 100.0
- type: make_to_order
- order_policy: manual
- partner_id: sale.res_partner_cleartrail0
- picking_policy: direct
--
- I use the Advance Payment wizard.
--
- !record {model: sale.advance.payment.inv, id: sale_advance_payment_inv_0}:
- amount: 1000.0
- product_id: product.product_product_pc3
- qtty: 3.0
--
- Then I click on the "Create Partial Invoice" button
--
- !python {model: sale.advance.payment.inv}: |
- self.create_invoices(cr, uid, [ref("sale_advance_payment_inv_0")], {"lang": 'en_US',
- "active_model": 'sale.order', "active_ids": [ref("sale_order_so5")], "tz":
- False, "active_id": ref("sale_order_so5"), })
--
- I verify whether the invoice has been generated.
--
- !python {model: sale.order}: |
- so = self.read(cr, uid, ref("sale_order_so5"))
- assert so['invoice_ids'], "Invoices has not been generated for sale_order_so5"
--
- I open the Invoice for the SO.
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so5"))
- import netsvc
- wf_service = netsvc.LocalService("workflow")
- invoice_ids = so.invoice_ids
- for invoice in invoice_ids:
- wf_service.trg_validate(uid, 'account.invoice',invoice.id,'invoice_open', cr)
--
- I verify that an invoice state has transit from draft to open state
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so5"))
- invoice_id = self.search(cr, uid, [('origin','=',so.name),('state','=','open')])
- assert invoice_id, "Invoice is not in the open state"
--
- I pay the invoice
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so5"))
- invoice_id = self.search(cr, uid, [('origin','=',so.name),('state','=','open')])
- self.pay_and_reconcile(cr, uid, invoice_id,
- 3000.0, ref('account.cash'), ref('account.period_5'),
- ref('sale.account_journal_bankjournal0'), ref('account.cash'),
- ref('account.period_8'), ref('sale.account_journal_bankjournal0'),
- name='test')
--
- I verify that invoice has transit from Open to Paid state
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so5"))
- invoice_id = self.search(cr, uid, [('origin','=',so.name),('state','=','paid')])
- assert invoice_id, "Invoice for SO is not in paid state."
--
- I verify that Paid has been set to true.
--
- !python {model: sale.order}: |
- sale_id=self.browse(cr, uid, ref("sale_order_so5"))
- assert(sale_id.invoiced == True), "Paid has not been set to true"
--
- I confirm the Sale Order.
--
- !workflow {model: sale.order, action: order_confirm, ref: sale_order_so5}
--
- I click on "Create Invoice" button of Sales order to create the invoice.
--
- !workflow {model: sale.order, action: manual_invoice, ref: sale_order_so5}
--
- I verify whether the invoice has been generated for SO
--
- !python {model: sale.order}: |
- so = self.browse(cr, uid, ref("sale_order_so5"))
- assert so.invoice_ids[1], "Invoices has not been generated for sale_order_so5"
--
- I open the Invoice for the SO.
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so5"))
- import netsvc
- wf_service = netsvc.LocalService("workflow")
- invoice_ids = so.invoice_ids
- for invoice in invoice_ids:
- wf_service.trg_validate(uid, 'account.invoice',invoice.id,'invoice_open', cr)
--
- I verify that an invoice state has transit from draft to open state
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so5"))
- invoice_id = self.search(cr, uid, [('origin','=',so.name),('state','=','open')])
- assert invoice_id, "Invoice is not in the open state"
--
- I assign an analytic journal to the bank journal
--
- !record {model: account.journal, id: sale.account_journal_bankjournal0}:
- analytic_journal_id: account.cose_journal_sale
--
- I pay the invoice
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so5"))
- invoice_id = self.search(cr, uid, [('origin','=',so.name),('state','=','open')])
- self.pay_and_reconcile(cr, uid, invoice_id,
- 14000.0, ref('account.cash'), ref('account.period_5'),
- ref('sale.account_journal_bankjournal0'), ref('account.cash'),
- ref('account.period_5'), ref('sale.account_journal_bankjournal0'),
- name='test')
--
- I verify that an invoice is in done state.
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so5"))
- invoice_id = self.search(cr, uid, [('origin','=',so.name),('state','=','paid')])
- assert invoice_id, "Invoice for SO is not in done state."
--
- I verify that Paid has been set to true.
--
- !python {model: sale.order}: |
- sale_id=self.browse(cr, uid, ref("sale_order_so5"))
- assert(sale_id.invoiced == True), "Paid has not been set to true"
diff --git a/addons/sale/test/cancel_order.yml b/addons/sale/test/cancel_order.yml
new file mode 100644
index 00000000000..a398e1545ab
--- /dev/null
+++ b/addons/sale/test/cancel_order.yml
@@ -0,0 +1,88 @@
+-
+ In order to test the cancel sale order.
+-
+ Now I cancel Quotation.
+-
+ !python {model: sale.order}: |
+ self.action_cancel(cr, uid, [ref("order7")])
+-
+ I check state of Quotation after cancelled.
+-
+ !assert {model: sale.order, id: order7, string: sale order should be in cancel state}:
+ - state == 'cancel'
+-
+ I set cancelled quotation to draft.
+-
+ !python {model: sale.order}: |
+ self.action_cancel_draft(cr, uid, [ref("order7")])
+-
+ I confirm order.
+-
+ !workflow {model: sale.order, action: order_confirm, ref: order7}
+-
+ I send delivery in two shipments, so I am doing a partial delivery order.
+-
+ !python {model: stock.picking}: |
+ delivery_orders = self.search(cr, uid, [('sale_id','=',ref("order7"))])
+ first_picking = self.browse(cr, uid, delivery_orders[0], context=context)
+ if first_picking.force_assign(cr, uid, first_picking):
+ first_move = first_picking.move_lines[0]
+ values = {'move%s'%(first_move.id): {'product_qty': 5}}
+ first_picking.do_partial(values, context=context)
+-
+ Now I cancel latest shipment.
+-
+ !python {model: stock.picking}: |
+ import netsvc
+ delivery_orders = self.search(cr, uid, [('sale_id','=',ref("order7"))])
+ last_delivery_order_id = delivery_orders[0]
+ wf_service = netsvc.LocalService("workflow")
+ wf_service.trg_validate(uid, 'stock.picking', last_delivery_order_id, 'button_cancel', cr)
+-
+ I run the scheduler.
+-
+ !python {model: procurement.order}: |
+
+ self.run_scheduler(cr, uid)
+-
+ I check order status in "Ship Exception".
+-
+ !assert {model: sale.order, id: order7, string: Sale order should be in shipping exception}:
+ - state == "shipping_except"
+-
+ Now I regenerate shipment.
+-
+ !workflow {model: sale.order, action: ship_recreate, ref: order7}
+-
+ I check state of order in 'To Invoice'.
+-
+ !assert {model: sale.order, id: order7, string: Sale order should be In Progress state}:
+ - state == 'manual'
+-
+ I make invoice for order.
+-
+ !workflow {model: sale.order, action: manual_invoice, ref: order7}
+-
+ To cancel the sale order from Invoice Exception, I have to cancel the invoice of sale order.
+-
+ !python {model: sale.order}: |
+ import netsvc
+ invoice_ids = self.browse(cr, uid, ref("order7")).invoice_ids
+ wf_service = netsvc.LocalService("workflow")
+ first_invoice_id = invoice_ids[0]
+ wf_service.trg_validate(uid, 'account.invoice', first_invoice_id.id, 'invoice_cancel', cr)
+-
+ I check order status in "Invoice Exception" and related invoice is in cancel state.
+-
+ !assert {model: sale.order, id: order7, string: Sale order should be in Invoice Exception state}:
+ - state == "invoice_except", "Order should be in Invoice Exception state after cancel Invoice"
+-
+ Then I click on the Ignore Exception button.
+-
+ !workflow {model: sale.order, action: invoice_corrected, ref: order7}
+
+-
+ I check state of order in 'In Progress'.
+-
+ !assert {model: sale.order, id: order7, string: Sale order should be In progress state}:
+ - state == 'progress'
diff --git a/addons/sale/test/data_test.yml b/addons/sale/test/data_test.yml
deleted file mode 100644
index 8e064212f58..00000000000
--- a/addons/sale/test/data_test.yml
+++ /dev/null
@@ -1,254 +0,0 @@
--
- In order to test the sale module, I need to configure details regarding product,customer and account.
--
- I am going to sell my Mobile products to the customer with name Cleartrail
--
- I create View Account Type.
--
- !record {model: account.account.type, id: account_account_type_view0}:
- close_method: none
- code: View
- name: View
--
- I create Income Account Type.
--
- !record {model: account.account.type, id: account_account_type_income0}:
- close_method: unreconciled
- code: Income
- name: Income
--
- I create Expense Account Type.
--
- !record {model: account.account.type, id: account_account_type_expense0}:
- close_method: unreconciled
- code: Expense
- name: Expense
--
- I create Cash Account Type.
--
- !record {model: account.account.type, id: account_account_type_cash0}:
- close_method: balance
- code: Cash
- name: Cash
--
- I create Minimal Chart Account.
--
- !record {model: account.account, id: account_account_minimalchart0}:
- code: MC
- company_id: base.main_company
- currency_mode: current
- name: Minimal Chart
- parent_left: 1
- parent_right: 12
- type: view
- user_type: account_account_type_view0
--
- I create Payable Account.
--
- !record {model: account.account, id: account_account_payable1}:
- code: AP
- company_id: base.main_company
- currency_mode: current
- name: Payable
- parent_id: account_account_minimalchart0
- parent_left: 2
- parent_right: 3
- reconcile: true
- type: payable
- user_type: account_account_type_expense0
--
- I create Receivable Account.
--
- !record {model: account.account, id: account_account_receivable0}:
- code: AR
- company_id: base.main_company
- currency_mode: current
- name: Receivable
- parent_id: account_account_minimalchart0
- parent_left: 4
- parent_right: 5
- reconcile: true
- type: receivable
- user_type: account_account_type_income0
--
- I create Cash Account.
--
- !record {model: account.account, id: account_account_cash0}:
- code: C
- company_id: base.main_company
- currency_mode: current
- name: Cash
- parent_id: account_account_minimalchart0
- parent_left: 6
- parent_right: 7
- type: other
- user_type: account_account_type_cash0
--
- I create Purchases Account.
--
- !record {model: account.account, id: account_account_purchases0}:
- code: P
- company_id: base.main_company
- currency_mode: current
- name: Purchases
- parent_id: account_account_minimalchart0
- parent_left: 8
- parent_right: 9
- type: other
- user_type: account_account_type_expense0
--
- I create Sales Account.
--
- !record {model: account.account, id: account_account_sales0}:
- code: S
- company_id: base.main_company
- currency_mode: current
- name: Sales
- parent_id: account_account_minimalchart0
- parent_left: 10
- parent_right: 11
- type: other
- user_type: account_account_type_income0
--
- I create Purchase Journal - (test).
--
- !record {model: account.journal, id: account_journal_purchasejournal0}:
- code: PUJ
- company_id: base.main_company
- default_credit_account_id: account_account_purchases0
- default_debit_account_id: account_account_purchases0
- name: Purchase Journal - (test)
- type: purchase
- view_id: account.account_journal_view
--
- I create Sale Journal.
--
- !record {model: account.journal, id: account_journal_salejournal0}:
- code: SJ
- company_id: base.main_company
- default_credit_account_id: account_account_sales0
- default_debit_account_id: account_account_sales0
- name: Sale Journal
- type: sale
- view_id: account.account_journal_view
--
- I create Bank Journal.
--
- !record {model: account.journal, id: account_journal_bankjournal0}:
- code: BNK
- company_id: base.main_company
- default_credit_account_id: account_account_cash0
- default_debit_account_id: account_account_cash0
- name: Bank Journal
- type: cash
- view_id: account.account_journal_bank_view
--
- I create ir.property for account payable.
--
- !record {model: ir.property, id: ir_property_propertyaccountexpensecateg0}:
- company_id: base.main_company
- fields_id: account.field_res_partner_property_account_payable
- name: property_account_expense_categ
- value_reference: account.account,5
--
- I create ir.property for account receivable.
--
- !record {model: ir.property, id: ir_property_propertyaccountincomecateg0}:
- company_id: base.main_company
- fields_id: account.field_res_partner_property_account_receivable
- name: property_account_income_categ
- value_reference: account.account,6
--
- I create Partner category Customers.
--
- !record {model: res.partner.category, id: res_partner_category_customers0}:
- name: Customers
--
- I create Cleartrail Customer.
--
- !record {model: res.partner, id: res_partner_cleartrail0}:
- category_id:
- - res_partner_category_customers0
- name: Cleartrail
- opt_out: True
--
- I create contact address for Cleartrail.
--
- !record {model: res.partner.address, id: res_partner_address_1}:
- partner_id: res_partner_cleartrail0
- street: onam plaza, 14 B palasia A B Road
- type: contact
--
- I create invoice address for Cleartrail.
--
- !record {model: res.partner.address, id: res_partner_address_2}:
- partner_id: res_partner_cleartrail0
- street: sarda house 24 B palasia, A B Road
- type: invoice
--
- I create delivery address for Cleartrail.
--
- !record {model: res.partner.address, id: res_partner_address_3}:
- partner_id: res_partner_cleartrail0
- street: sangam house 15 B palasia, A B Road
- type: delivery
--
- Customer Cleartrail has specific instrument requirement regarding the stockable products.
--
- I define product category Mobile Products Sellable.
--
- !record {model: product.category, id: product_category_allproductssellable0}:
- name: Mobile Products Sellable
--
- I define product category Mobile Services.
--
- !record {model: product.category, id: product_category_services0}:
- name: Mobile Services
--
-
- I define LG Viewty Smart product.
--
- !record {model: product.product, id: product_product_lgviewtysmart0}:
- categ_id: product_category_allproductssellable0
- cost_method: standard
- list_price: 170.0
- mes_type: fixed
- name: LG Viewty Smart
- procure_method: make_to_order
- property_account_expense: sale.account_account_payable1
- property_account_income: sale.account_account_receivable0
- seller_delay: '1'
- seller_ids:
- - delay: 1
- name: base.res_partner_agrolait
- min_qty: 2.0
- qty: 5.0
- standard_price: 160.0
- supply_method: produce
- type: product
- uom_id: product.product_uom_unit
- uom_po_id: product.product_uom_unit
-
--
- I define Slider Mobile.
--
- !record {model: product.product, id: product_product_slidermobile0}:
- categ_id: product_category_allproductssellable0
- cost_method: standard
- list_price: 200
- mes_type: fixed
- name: Slider Mobile
- procure_method: make_to_order
- property_account_expense: sale.account_account_payable1
- property_account_income: sale.account_account_receivable0
- seller_delay: '1'
- seller_ids:
- - delay: 1
- name: base.res_partner_agrolait
- min_qty: 2.0
- qty: 5.0
- standard_price: 189.0
- supply_method: buy
- type: product
- uom_id: product.product_uom_unit
- uom_po_id: product.product_uom_unit
diff --git a/addons/sale/test/delete_order.yml b/addons/sale/test/delete_order.yml
new file mode 100644
index 00000000000..2bbfed9771d
--- /dev/null
+++ b/addons/sale/test/delete_order.yml
@@ -0,0 +1,14 @@
+-
+ I try to delete In progress order and check Error Message.
+-
+ !python {model: sale.order}: |
+ try:
+ self.unlink(cr, uid, [ref("order")])
+ except Exception,e:
+ pass
+-
+ I make duplicate order and delete.
+-
+ !python {model: sale.order}: |
+ id = self.copy(cr, uid, ref('order'))
+ self.unlink(cr, uid, [id])
diff --git a/addons/sale/test/invoice_on_ordered_qty.yml b/addons/sale/test/invoice_on_ordered_qty.yml
deleted file mode 100644
index 313aa3a0d63..00000000000
--- a/addons/sale/test/invoice_on_ordered_qty.yml
+++ /dev/null
@@ -1,110 +0,0 @@
--
- In order to test the Sale module in OpenERP,
- I create a Sale Order for Slider Mobile for 500 quantity having Shipping Policy 'Shipping & Manual Invoice' and Invoice on 'Ordered quantities'
- in order to create an invoice based on the ordered quantity
--
- !record {model: sale.order, id: sale_order_so9}:
- date_order: !eval time.strftime('%Y-%m-%d')
- invoice_quantity: order
- name: Test_SO006
- order_line:
- - name: Slider Mobile
- price_unit: 200
- product_uom: product.product_uom_unit
- product_uom_qty: 200.0
- state: draft
- delay: 7.0
- product_id: sale.product_product_slidermobile0
- product_uos_qty: 200.0
- type: make_to_order
- order_policy: manual
- invoice_quantity: order
- partner_id: sale.res_partner_cleartrail0
- partner_invoice_id: sale.res_partner_address_2
- partner_order_id: sale.res_partner_address_1
- partner_shipping_id: sale.res_partner_address_3
- picking_policy: direct
- pricelist_id: product.list0
- shop_id: sale.shop
--
- I confirm the Sale Order.
--
- !workflow {model: sale.order, action: order_confirm, ref: sale_order_so9}
--
- I verify that the picking has been generated for the sale order and I process it
--
- !python {model: sale.order}: |
- so = self.browse(cr, uid, ref("sale_order_so9"))
- assert so.picking_ids,"Picking has not been generated for sale_order_so9"
- picking, = so.picking_ids
- stock_partial_picking = self.pool.get('stock.partial.picking')
- partial_id = stock_partial_picking.create(cr, uid, {},
- context={'active_model': 'stock.picking',
- 'active_ids': [picking.id]})
- stock_partial_picking.do_partial(cr, uid, [partial_id])
--
- I click on Create Invoice button to create the invoice.
--
- !workflow {model: sale.order, action: manual_invoice, ref: sale_order_so9}
--
- I verify whether the invoice has been generated for SO
--
- !python {model: sale.order}: |
- so = self.browse(cr, uid, ref("sale_order_so9"))
- assert so.invoice_ids, "Invoices has not been generated for sale_order_so9"
--
- I verify that an invoice is created on the basis of ordered quantity
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so9"))
- for so_lines in so.order_line:
- qty = so_lines.product_uom_qty
- ids = self.search(cr, uid, [('origin','=',so.name)])
- inv_brw = self.browse(cr,uid,ids)[0]
- for inv_lines in inv_brw.invoice_line:
- qty1 = inv_lines.quantity
- assert qty1==qty, "Quantities are not same"
--
- I open the Invoice for the SO.
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so9"))
- import netsvc
- wf_service = netsvc.LocalService("workflow")
- invoice_ids = so.invoice_ids
- for invoice in invoice_ids:
- wf_service.trg_validate(uid, 'account.invoice',invoice.id,'invoice_open', cr)
--
- Assign analytic journal into bank journal
--
- !record {model: account.journal, id: sale.account_journal_bankjournal0}:
- analytic_journal_id: account.cose_journal_sale
--
- I pay the invoice
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so9"))
- invoice_id = self.search(cr, uid, [('origin','=',so.name),('state','=','open')])
- self.pay_and_reconcile(cr, uid, invoice_id,
- 40000.0, ref('account.cash'), ref('account.period_9'),
- ref('sale.account_journal_bankjournal0'), ref('account.cash'),
- ref('account.period_8'), ref('sale.account_journal_bankjournal0'),
- name='test')
--
- I verify the invoice are in paid state or not.
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so9"))
- invoice_ids = so.invoice_ids
- for invoice in invoice_ids:
- assert invoice.state =='paid', "Invoice for SO is not in done state."
--
- I check that Paid has been set to true.
--
- !python {model: sale.order}: |
- sale_id=self.browse(cr, uid, ref("sale_order_so9"))
- assert sale_id.invoiced == True, "Paid has not been set to true"
diff --git a/addons/sale/test/invoice_on_shipped_qty.yml b/addons/sale/test/invoice_on_shipped_qty.yml
deleted file mode 100644
index c6ac86471be..00000000000
--- a/addons/sale/test/invoice_on_shipped_qty.yml
+++ /dev/null
@@ -1,124 +0,0 @@
--
- In order to test the Sale module in OpenERP,
- I create a Sale Order for Slider Mobile for 200 quantity having Shipping Policy 'Invoice from Picking' and Invoice on 'Shipped quantities'
--
- !record {model: sale.order, id: sale_order_so6}:
- date_order: !eval time.strftime('%Y-%m-%d')
- invoice_quantity: order
- name: Test_SO006BIS
- order_line:
- - name: Slider Mobile
- price_unit: 200
- product_uom: product.product_uom_unit
- product_uom_qty: 200.0
- state: draft
- delay: 7.0
- product_id: sale.product_product_slidermobile0
- product_uos_qty: 200.0
- type: make_to_order
- order_policy: picking
- invoice_quantity: procurement
- partner_id: sale.res_partner_cleartrail0
- partner_invoice_id: sale.res_partner_address_2
- partner_order_id: sale.res_partner_address_1
- partner_shipping_id: sale.res_partner_address_3
- picking_policy: direct
- pricelist_id: product.list0
- shop_id: sale.shop
--
- I confirm the Sale Order.
--
- !workflow {model: sale.order, action: order_confirm, ref: sale_order_so6}
--
- I verify that the picking has been generated for the sale order and I process it
--
- !python {model: sale.order}: |
- so = self.browse(cr, uid, ref("sale_order_so6"))
- assert so.picking_ids,"Picking has not been generated for sale_order_so6"
- picking, = so.picking_ids
- stock_partial_picking = self.pool.get('stock.partial.picking')
- partial_id = stock_partial_picking.create(cr, uid, {},
- context={'active_model': 'stock.picking',
- 'active_ids': [picking.id]})
- # I change the qty to 100 for a partial delivery
- partial = stock_partial_picking.browse(cr,uid,partial_id)
- line_id = partial.move_ids[0].id
- partial.write({'move_ids': [(1,line_id,{'quantity':100})]})
- partial.do_partial()
--
- Then I click on 'Create Invoices' button
--
- !python {model: stock.invoice.onshipping}: |
- import time
- sale_obj = self.pool.get('sale.order')
- sale_id = sale_obj.browse(cr, uid, ref("sale_order_so6"))
- ids = [x.id for x in sale_id.picking_ids if x.state == 'done']
- wiz_id = self.create(cr, uid, {'invoice_date': time.strftime('%Y-%m-%d'), 'journal_id': ref('account.sales_journal')},
- {'active_ids': ids, 'active_model': 'stock.picking'})
- self.create_invoice(cr, uid, [wiz_id], {"active_ids": ids, "active_id": ids[0]})
--
- I verify whether the invoice has been generated for SO
--
- !python {model: sale.order}: |
- so = self.browse(cr, uid, ref("sale_order_so6"))
- assert so.invoice_ids, "Invoices has not been generated for sale_order_so6"
--
- I verify that an invoice is created on the basis of shipped quantities 100 not ordered quantities 200
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so6"))
- picking_obj = self.pool.get('stock.picking')
- ids = picking_obj.search(cr, uid, [('origin', '=', so.name),('type','=','out'),('state','=','done')])
- qty = qty1 = 0.0
- for pick_brw in picking_obj.browse(cr,uid, ids):
- for lines in pick_brw.move_lines:
- qty=lines.product_qty
- inv_id = self.search(cr, uid, [('origin', 'like', so.name)])
- inv_brw = self.browse(cr,uid,inv_id)[0]
- for inv_lines in inv_brw.invoice_line:
- qty1=inv_lines.quantity
- assert (qty1 == qty), "Quantities are not the same: invoiced: %s, shipped: %s" % (qty1,qty)
--
- I open the Invoice for the SO.
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so6"))
- import netsvc
- wf_service = netsvc.LocalService("workflow")
- invoice_ids = so.invoice_ids
- for invoice in invoice_ids:
- wf_service.trg_validate(uid, 'account.invoice',invoice.id,'invoice_open', cr)
--
- Assign analytic journal into bank journal
--
- !record {model: account.journal, id: sale.account_journal_bankjournal0}:
- analytic_journal_id: account.cose_journal_sale
--
- I pay the invoice
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so6"))
- invoice_id = self.search(cr, uid, [('origin','like',so.name),('state','=','open')])
- self.pay_and_reconcile(cr, uid, invoice_id,
- 40000.0, ref('account.cash'), ref('account.period_8'),
- ref('sale.account_journal_bankjournal0'), ref('account.cash'),
- ref('account.period_8'), ref('sale.account_journal_bankjournal0'),
- name='test')
--
- I verify the invoice are in paid state or not.
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so6"))
- invoice_ids = so.invoice_ids
- for invoice in invoice_ids:
- assert invoice.state=='paid', "Invoice for SO is not in done state."
--
- I check that Paid has been set to true.
--
- !python {model: sale.order}: |
- sale_id=self.browse(cr, uid, ref("sale_order_so6"))
- assert sale_id.invoiced == True, "Paid has not been set to true"
diff --git a/addons/sale/test/manual_order_policy.yml b/addons/sale/test/manual_order_policy.yml
index af515b2d4e4..d997e792696 100644
--- a/addons/sale/test/manual_order_policy.yml
+++ b/addons/sale/test/manual_order_policy.yml
@@ -1,261 +1,89 @@
-
- In order to test the Sale module in OpenERP,
- I create a Sale Order for Slider Mobile for 500 quantity having Shipping Policy 'Shipping & Manual Invoice'
+ I confirm the Quotation with "Deliver & invoice on demand".
-
- !record {model: sale.order, id: sale_order_so0}:
- date_order: !eval time.strftime('%Y-%m-%d')
- invoice_quantity: order
- name: Test_SO002
- order_line:
- - name: Slider Mobile
- price_unit: 200
- product_uom: product.product_uom_unit
- product_uom_qty: 500.0
- state: draft
- delay: 7.0
- product_id: sale.product_product_slidermobile0
- product_uos_qty: 500.0
- type: make_to_order
- order_policy: manual
- partner_id: sale.res_partner_cleartrail0
- partner_invoice_id: sale.res_partner_address_2
- partner_order_id: sale.res_partner_address_1
- partner_shipping_id: sale.res_partner_address_3
- picking_policy: direct
- pricelist_id: product.list0
- shop_id: sale.shop
+ !workflow {model: sale.order, action: order_confirm, ref: order4}
-
- I confirm the Sale Order.
--
- !workflow {model: sale.order, action: order_confirm, ref: sale_order_so0}
--
- I click on Create Invoice button to create the invoice.
--
- !workflow {model: sale.order, action: manual_invoice, ref: sale_order_so0}
-
--
- I verify whether the invoice has been generated for SO
+ I check that Invoice should not created.
-
!python {model: sale.order}: |
- so = self.browse(cr, uid, ref("sale_order_so0"))
- assert so.invoice_ids, "Invoices has not been generated for sale_order_so0"
+ sale_order = self.browse(cr, uid, ref("order4"))
+ assert len(sale_order.invoice_ids) == False, "Invoice should not created."
+ assert sale_order.picking_ids, "Delivery order should be created."
-
- I open the Invoice for the SO.
+ I create advance invoice.
-
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so0"))
+ !python {model: sale.advance.payment.inv}: |
+ ctx = context.copy()
+ ctx.update({"active_model": 'sale.order', "active_ids": [ref("order4")], "active_id":ref("order4")})
+ order_line = self.pool.get('sale.order.line').browse(cr, uid, ref("line7"), context=context)
+ pay_id = self.create(cr, uid, {'product_id': order_line.product_id.id, 'amount': order_line.price_subtotal, 'qtty': order_line.product_uom_qty})
+ self.create_invoices(cr, uid, [pay_id], context=ctx)
+-
+ I check Invoice which made advance
+-
+ !python {model: sale.order}: |
+ order = self.browse(cr, uid, ref('order4'))
+ assert order.invoice_ids, "Invoice should be created after make advance invoice."
+-
+ I create Invoice from sale order line.
+-
+ !python {model: sale.order.line.make.invoice}: |
+ ctx = context.copy()
+ ctx.update({"active_model": 'sale.order.line', "active_ids": [ref("line8")], "active_id":ref("line8")})
+ self.make_invoices(cr, uid, [], context=ctx)
+-
+ I check Invoice which made from sale order line.
+-
+ !python {model: sale.order.line}: |
+ line = self.browse(cr, uid, ref('line8'))
+ assert line.invoiced, "Line is not invoiced."
+ assert line.invoice_lines, "Invoice line should be created."
+-
+ I create manual Invoice for order.
+-
+ !record {model: sale.make.invoice, id: sale_make_invoice_1}:
+ invoice_date: !eval time.strftime('%Y-%m-%d')
+-
+ !python {model: sale.make.invoice}: |
+ ctx = context.copy()
+ ctx = ctx.update({"active_model": 'sale.order', "active_ids": [ref("order4")], "active_id":ref("order4")})
+ self.make_invoices(cr, uid, [ref("sale_make_invoice_1")], context)
+-
+ I open the Invoice.
+-
+ !python {model: sale.order}: |
import netsvc
wf_service = netsvc.LocalService("workflow")
- invoice_ids = so.invoice_ids
- for invoice in invoice_ids:
- wf_service.trg_validate(uid, 'account.invoice',invoice.id,'invoice_open', cr)
--
- I verify that an invoice state has transit from draft to open state
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so0"))
- invoice_id = self.search(cr, uid, [('origin','=',so.name),('state','=','open')])
- assert invoice_id, "Invoice is not in the open state"
--
- I verify that its Journal Entries has been created
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so0"))
- invoice_id = self.search(cr, uid, [('origin','=',so.name),('state','=','open')])
- inv_brw = self.browse(cr, uid, invoice_id)[0]
- assert inv_brw.move_id, "Journal Entries has not been created"
--
- Assign analytic journal into bank journal
--
- !record {model: account.journal, id: sale.account_journal_bankjournal0}:
- analytic_journal_id: account.cose_journal_sale
+ so = self.browse(cr, uid, ref("order4"))
+ for invoice in so.invoice_ids:
+ wf_service.trg_validate(uid, 'account.invoice', invoice.id, 'invoice_open', cr)
-
I pay the invoice
-
!python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so0"))
- invoice_id = self.search(cr, uid, [('origin','=',so.name),('state','=','open')])
- self.pay_and_reconcile(cr, uid, invoice_id,
- 100000.0, ref('account.cash'), ref('account.period_8'),
- ref('sale.account_journal_bankjournal0'), ref('account.cash'),
- ref('account.period_8'), ref('sale.account_journal_bankjournal0'),
- name='test')
+ sale_order = self.pool.get('sale.order')
+ order = sale_order.browse(cr, uid, ref("order4"))
+ journal_ids = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'cash'), ('company_id', '=', order.company_id.id)], limit=1)
+ for invoice in order.invoice_ids:
+ invoice.pay_and_reconcile(
+ invoice.amount_total, ref('account.cash'), ref('account.period_8'),
+ journal_ids[0], ref('account.cash'),
+ ref('account.period_8'), journal_ids[0],
+ name='test')
-
- I verify the invoice is in done state.
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so0"))
- invoice_id = self.search(cr, uid, [('origin','=',so.name),('state','=','paid')])
- assert invoice_id, "Invoice for SO is not in done state."
--
- I verify that Paid has been set to true.
+ I check Invoice after do manual.
-
!python {model: sale.order}: |
- sale_id=self.browse(cr, uid, ref("sale_order_so0"))
- assert(sale_id.invoiced == True), "Paid has not been set to true"
+ sale_order = self.browse(cr, uid, ref("order4"))
+ assert sale_order.invoice_ids, "Invoice should be created."
+ assert sale_order.invoiced, "Order is not invoiced."
+ assert sale_order.state == 'manual', 'Order should be in Manual.'
+
-
- I verify that the picking has been generated for the sale order
+ I set order policy "Deliver & invoice on demand" as default policy.
-
- !python {model: sale.order}: |
- so = self.browse(cr, uid, ref("sale_order_so0"))
- assert so.picking_ids,"Picking has not been generated for sale_order_so0"
+ !record {model: sale.config.picking_policy, id: sale.config.picking_policy_0}:
+ order_policy: 'manual'
-
- I verify that delivery order has been generated for sale order
--
- !python {model: stock.picking }: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so0"))
- picking_id = self.search(cr, uid, [('origin','=',so.name)])
- assert(picking_id),"Delivery order has not been generated"
--
- I verify that a procurement has been generated for so
--
- !python {model: procurement.order}: |
- from tools.translate import _
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so0"))
- proc_ids = self.search(cr, uid, [('origin','=',so.name)])
- assert(proc_ids),"No Procurements!"
--
- Then I click on the "Run Procurement" button
--
- !python {model: procurement.order}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so0"))
- import netsvc
- wf_service = netsvc.LocalService("workflow")
- proc_ids = self.search(cr, uid, [('origin','=',so.name)])
- for proc in proc_ids:
- wf_service.trg_validate(uid, 'procurement.order',proc,'button_check', cr)
--
- I verify that a procurement state is "running"
--
- !python {model: procurement.order}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so0"))
- proc_ids = self.search(cr, uid, [('origin','=',so.name),('state','in',['running','ready'])])
- # should be running is 'purchase' is installed, else 'ready'
- assert(proc_ids),"Procurement is not in running/ready state!"
--
- I verify that a purchase order has been generated
--
- !python {model: sale.order}: |
- from tools.translate import _
- modules = self.pool.get('ir.module.module')
- mod_pur = modules.search(cr, uid, [('name','=','purchase')])
- mod_brw = modules.browse(cr,uid,mod_pur)[0]
- if(mod_brw.state == 'installed'):
- so = self.browse(cr, uid, ref("sale_order_so0"))
- pur_obj=self.pool.get('purchase.order')
- pur_id=pur_obj.search(cr, uid, [('origin','=',so.name)])
- assert(pur_id),"Purchase order has not been generated"
-
--
- I click on the "Confirm" button to confirm the purchase order
--
- !python {model: sale.order}: |
- from tools.translate import _
- modules = self.pool.get('ir.module.module')
- mod_pur = modules.search(cr, uid, [('name','=','purchase')])
- mod_brw = modules.browse(cr,uid,mod_pur)[0]
- if(mod_brw.state == 'installed'):
- pur_obj=self.pool.get('purchase.order')
- so = self.browse(cr, uid, ref("sale_order_so0"))
- import netsvc
- wf_service = netsvc.LocalService("workflow")
- pur_ids = pur_obj.search(cr, uid, [('origin','=',so.name)])
- for pur in pur_ids:
- wf_service.trg_validate(uid, 'purchase.order',pur,'purchase_confirm', cr)
--
- I click on the "Approved by supplier" button to approve the purchase order
--
- !python {model: sale.order}: |
- from tools.translate import _
- modules = self.pool.get('ir.module.module')
- mod_pur = modules.search(cr, uid, [('name','=','purchase')])
- mod_brw = modules.browse(cr,uid,mod_pur)[0]
- if (mod_brw.state == 'installed'):
- pur_obj = self.pool.get('purchase.order')
- so = self.browse(cr, uid, ref("sale_order_so0"))
- import netsvc
- wf_service = netsvc.LocalService("workflow")
- pur_ids = pur_obj.search(cr, uid, [('origin','=',so.name)])
- for pur in pur_ids:
- wf_service.trg_validate(uid, 'purchase.order',pur,'purchase_approve', cr)
--
- I verify that a picking related to purchase order has been generated and I process it
--
- !python {model: sale.order}: |
- modules = self.pool.get('ir.module.module')
- mod_pur = modules.search(cr, uid, [('name','=','purchase')])
- mod_brw = modules.browse(cr,uid,mod_pur)[0]
- if (mod_brw.state == 'installed'):
- pur_obj = self.pool.get('purchase.order')
- so = self.browse(cr, uid, ref("sale_order_so0"))
- pur_id = pur_obj.search(cr, uid, [('origin','=',so.name)])
- po = pur_obj.browse(cr, uid, pur_id)[0]
- assert(po.picking_ids),"Picking for purchase order has not been generated"
- picking, = po.picking_ids
- stock_partial_picking = self.pool.get('stock.partial.picking')
- partial_id = stock_partial_picking.create(cr, uid, {},
- context={'active_model': 'stock.picking',
- 'active_ids': [picking.id]})
- stock_partial_picking.do_partial(cr, uid, [partial_id])
--
- I verify that picking for purchase order has been done.
--
- !python {model: sale.order}: |
- from tools.translate import _
- modules = self.pool.get('ir.module.module')
- mod_pur = modules.search(cr, uid, [('name','=','purchase')])
- mod_brw = modules.browse(cr,uid,mod_pur)[0]
- if(mod_brw.state == 'installed'):
- pur_obj = self.pool.get('purchase.order')
- so = self.browse(cr, uid, ref("sale_order_so0"))
- pur_id = pur_obj.search(cr, uid, [('origin','=',so.name)])
- po = pur_obj.browse(cr, uid, pur_id)[0]
- picking_obj = self.pool.get('stock.picking')
- ids = picking_obj.search(cr, uid, [('purchase_id', '=', po.id ),('state', '=', 'done')])
- assert(ids),"Picking is not in the done state!"
--
- Then I process the picking
--
- !python {model: stock.picking }: |
- import time
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so0"))
- picking_id = self.search(cr, uid, [('origin','=',so.name),('type','=','out')])
- if picking_id:
- pick=self.browse(cr,uid,picking_id[0])
- pick.force_assign(cr, uid)
- stock_partial_picking = self.pool.get('stock.partial.picking')
- partial_id = stock_partial_picking.create(cr, uid, {},
- context={'active_model': 'stock.picking',
- 'active_ids': [pick.id]})
- stock_partial_picking.do_partial(cr, uid, [partial_id])
--
- I verify that picking for sale order is in done state.
--
- !python {model: stock.picking }: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so0"))
- picking_id = self.search(cr, uid, [('origin','=',so.name),('type','=','out')])
- pick = self.browse(cr,uid,picking_id[0])
- assert (pick.state) =='done', "Picking for SO is not in done state."
--
- I verify that a "Picked" has been set to true
--
- !python {model: sale.order}: |
- so = self.browse(cr, uid, ref("sale_order_so0"))
- assert (so.shipped == True), "Picked has not been set to True"
--
- I verify that a sale order is in done state
--
- !python {model: sale.order}: |
- so = self.browse(cr, uid, ref("sale_order_so0"))
- assert (so.state == 'done'), "Sale order is not in the done state."
+ !python {model: sale.config.picking_policy}: |
+ self.execute(cr, uid, [ref("sale.config.picking_policy_0")])
diff --git a/addons/sale/test/picking_order_policy.yml b/addons/sale/test/picking_order_policy.yml
index 1dcbf980da4..33b23dbd5d0 100644
--- a/addons/sale/test/picking_order_policy.yml
+++ b/addons/sale/test/picking_order_policy.yml
@@ -1,264 +1,171 @@
-
- In order to test the Sale module in OpenERP,
- I create a Sale Order for Slider Mobile for qty 500 having Shipping Policy is 'Invoice from Picking'
+ In order to test process of the Sale Order,
-
- !record {model: sale.order, id: sale_order_so7}:
- date_order: !eval time.strftime('%Y-%m-%d')
- invoice_quantity: order
- name: Test_SO007
- order_line:
- - name: Slider Mobile
- price_unit: 200
- product_uom: product.product_uom_unit
- product_uom_qty: 500.0
- state: draft
- delay: 7.0
- product_id: sale.product_product_slidermobile0
- product_uos_qty: 500.0
- th_weight: 0.0
- type: make_to_order
- order_policy: picking
- partner_id: sale.res_partner_cleartrail0
- partner_invoice_id: sale.res_partner_address_2
- partner_order_id: sale.res_partner_address_1
- partner_shipping_id: sale.res_partner_address_3
- picking_policy: direct
- pricelist_id: product.list0
- shop_id: sale.shop
+ First I check the total amount of the Quotation before Approved.
-
- I confirm the sale order.
+ !assert {model: sale.order, id: order, string: The amount of the Quotation is not correctly computed}:
+ - sum([l.price_subtotal for l in order_line]) == amount_untaxed
-
- !workflow {model: sale.order, action: order_confirm, ref: sale_order_so7}
+ I confirm the quotation with "Invoice based on deliveries" policy.
-
- I verify that picking has been generated for the sale order.
+ !workflow {model: sale.order, action: order_confirm, ref: order}
+-
+ I check that invoice should not created before dispatch delivery.
-
!python {model: sale.order}: |
- so = self.browse(cr, uid, ref("sale_order_so7"))
- assert so.picking_ids,"Picking has not been generated for sale_order_so7"
+ order = self.pool.get('sale.order').browse(cr, uid, ref("order"))
+ assert order.state == 'progress', 'Order should be in inprogress.'
+ assert len(order.invoice_ids) == False, "Invoice should not created."
-
- Then I done the picking
+ I check the details of procurement after confirmed quotation.
-
- !python {model: stock.picking }: |
- import time
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so7"))
- picking_id = self.search(cr, uid, [('origin','=',so.name),('type','=','out')])
- if picking_id:
- pick=self.browse(cr,uid,picking_id[0])
- pick.force_assign(cr, uid)
- stock_partial_picking = self.pool.get('stock.partial.picking')
- partial_id = stock_partial_picking.create(cr, uid, {},
- context={'active_model': 'stock.picking',
- 'active_ids': [pick.id]})
- stock_partial_picking.do_partial(cr, uid, [partial_id])
+ !python {model: sale.order}: |
+ from datetime import datetime, timedelta
+ from dateutil.relativedelta import relativedelta
+ from tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
+ order = self.browse(cr, uid, ref("order"))
+ for order_line in order.order_line:
+ procurement = order_line.procurement_id
+ date_planned = datetime.strptime(order.date_order, DEFAULT_SERVER_DATE_FORMAT) + relativedelta(days=order_line.delay or 0.0)
+ date_planned = (date_planned - timedelta(days=order.company_id.security_lead)).strftime(DEFAULT_SERVER_DATETIME_FORMAT)
+ assert procurement.date_planned == date_planned, "Scheduled date is not correspond."
+ assert procurement.product_id.id == order_line.product_id.id, "Product is not correspond."
+ assert procurement.product_qty == order_line.product_uom_qty, "Qty is not correspond."
+ assert procurement.product_uom.id == order_line.product_uom.id, "UOM is not correspond."
+ assert procurement.procure_method == order_line.type, "Procurement method is not correspond."
-
- Then I click on 'Create Invoices' button
+ I run the scheduler.
+-
+ !python {model: procurement.order}: |
+ self.run_scheduler(cr, uid)
+-
+ I check the details of delivery order after confirmed quotation.
+-
+ !python {model: sale.order}: |
+ from datetime import datetime, timedelta
+ from dateutil.relativedelta import relativedelta
+ from tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
+ sale_order = self.browse(cr, uid, ref("order"))
+ assert sale_order.picking_ids, "Delivery order is not created."
+ for picking in sale_order.picking_ids:
+ assert picking.state == "auto" or "confirmed", "Delivery order should be in 'Waitting Availability' state."
+ assert picking.origin == sale_order.name,"Origin of Delivery order is not correspond with sequence number of sale order."
+ assert picking.type == 'out',"Shipment should be Outgoing."
+ assert picking.move_type == sale_order.picking_policy,"Delivery Method is not corresponding with delivery method of sale order."
+ assert picking.address_id.id == sale_order.partner_shipping_id.id,"Shipping Address is not correspond with sale order."
+ assert picking.note == sale_order.note,"Note is not correspond with sale order."
+ assert picking.invoice_state == (sale_order.order_policy=='picking' and '2binvoiced') or 'none',"Invoice policy is not correspond with sale order."
+ assert len(picking.move_lines) == len(sale_order.order_line), "Total move of delivery order are not corresposning with total sale order lines."
+ location_id = sale_order.shop_id.warehouse_id.lot_stock_id.id
+ output_id = sale_order.shop_id.warehouse_id.lot_output_id.id
+ for move in picking.move_lines:
+ order_line = move.sale_line_id
+ date_planned = datetime.strptime(sale_order.date_order, DEFAULT_SERVER_DATE_FORMAT) + relativedelta(days=order_line.delay or 0.0)
+ date_planned = (date_planned - timedelta(days=sale_order.company_id.security_lead)).strftime(DEFAULT_SERVER_DATETIME_FORMAT)
+ assert datetime.strptime(move.date_expected, DEFAULT_SERVER_DATETIME_FORMAT) == datetime.strptime(date_planned, DEFAULT_SERVER_DATETIME_FORMAT), "Excepted Date is not correspond with Planned Date."
+ assert move.product_id.id == order_line.product_id.id,"Product is not correspond."
+ assert move.product_qty == order_line.product_uom_qty,"Product Quantity is not correspond."
+ assert move.product_uom.id == order_line.product_uom.id,"Product UOM is not correspond."
+ assert move.product_uos_qty == (order_line.product_uos and order_line.product_uos_qty) or order_line.product_uom_qty,"Product UOS Quantity is not correspond."
+ assert move.product_uos == (order_line.product_uos and order_line.product_uos.id) or order_line.product_uom.id,"Product UOS is not correspond"
+ assert move.product_packaging.id == order_line.product_packaging.id,"Product packaging is not correspond."
+ assert move.address_id.id == order_line.address_allotment_id.id or sale_order.partner_shipping_id.id,"Address is not correspond"
+ #assert move.location_id.id == location_id,"Source Location is not correspond."
+ #assert move.location_dest_id == output_id,"Destination Location is not correspond."
+ assert move.note == order_line.notes,"Note is not correspond"
+ assert move.price_unit == order_line.product_id.standard_price or 0.0,"Price Unit is not correspond"
+-
+ Now, I dispatch delivery order.
+-
+ !python {model: stock.partial.picking}: |
+ order = self.pool.get('sale.order').browse(cr, uid, ref("order"))
+ for pick in order.picking_ids:
+ data = pick.force_assign()
+ if data == True:
+ partial_id = self.create(cr, uid, {}, context={'active_model': 'stock.picking','active_ids': [pick.id]})
+ self.do_partial(cr, uid, [partial_id])
+-
+ I check sale order to verify shipment.
+-
+ !python {model: sale.order}: |
+ order = self.pool.get('sale.order').browse(cr, uid, ref("order"))
+ assert order.shipped == True, "Sale order is not Delivered."
+ assert order.picked_rate == 100, "Shipment progress is not 100%."
+ #assert order.state == 'progress', 'Order should be in inprogress.'
+ assert len(order.invoice_ids) == False, "Invoice should not created on dispatch delivery order."
+-
+ I create Invoice from Delivery Order.
-
!python {model: stock.invoice.onshipping}: |
- import time
- sale_obj=self.pool.get('sale.order')
- sale_id=sale_obj.browse(cr, uid, ref("sale_order_so7"))
- ids = [x.id for x in sale_id.picking_ids]
- wiz_id = self.create(cr, uid, {'invoice_date': time.strftime('%Y-%m-%d'), 'journal_id': ref('account.sales_journal')},
- {'active_ids': ids, 'active_model': 'stock.picking'})
- self.create_invoice(cr, uid, [wiz_id], {"active_ids": ids, "active_id": ids[0]})
+ sale = self.pool.get('sale.order')
+ sale_order = sale.browse(cr, uid, ref("order"))
+ ship_ids = [x.id for x in sale_order.picking_ids]
+ wiz_id = self.create(cr, uid, {'journal_id': ref('account.sales_journal')},
+ {'active_ids': ship_ids, 'active_model': 'stock.picking'})
+ self.create_invoice(cr, uid, [wiz_id], {"active_ids": ship_ids, "active_id": ship_ids[0]})
-
- I check that an invoice has been created.
+ I check the invoice details after dispatched delivery.
-
!python {model: sale.order}: |
- sale_id=self.browse(cr, uid, ref("sale_order_so7"))
- assert(sale_id.invoice_ids), "Invoice has not been created"
+ order = self.browse(cr, uid, ref("order"))
+ assert order.invoice_ids, "Invoice is not created."
+ ac = order.partner_id.property_account_receivable.id
+ journal_ids = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'sale'), ('company_id', '=', order.company_id.id)], limit=1)
+ for invoice in order.invoice_ids:
+ assert invoice.type == 'out_invoice',"Invoice should be Customer Invoice."
+ assert invoice.account_id.id == ac,"Invoice account is not correspond."
+ assert invoice.reference == order.client_order_ref or order.name,"Reference is not correspond."
+ assert invoice.partner_id.id == order.partner_id.id,"Customer is not correspond."
+ assert invoice.address_invoice_id.id == order.partner_invoice_id.id,"Invoice Address is not correspond."
+ assert invoice.currency_id.id == order.pricelist_id.currency_id.id, "Currency is not correspond."
+ assert invoice.comment == order.note or '',"Note is not correspond."
+ assert invoice.journal_id.id == journal_ids[0],"Sales Journal is not link on Invoice."
+ assert invoice.payment_term.id == order.payment_term.id, "Payment term is not correspond."
+ for so_line in order.order_line:
+ inv_line = so_line.invoice_lines[0]
+ ac = so_line.product_id.product_tmpl_id.property_account_income.id or so_line.product_id.categ_id.property_account_income_categ.id
+ assert inv_line.product_id.id == so_line.product_id.id or False,"Product is not correspond"
+ assert inv_line.account_id.id == ac,"Account of Invoice line is not corresponding."
+ assert inv_line.uos_id.id == (so_line.product_uos and so_line.product_uos.id) or so_line.product_uom.id, "Product UOS is not correspond."
+ assert inv_line.price_unit == so_line.price_unit , "Price Unit is not correspond."
+ assert inv_line.quantity == (so_line.product_uos and so_line.product_uos_qty) or so_line.product_uom_qty , "Product qty is not correspond."
+ assert inv_line.price_subtotal == so_line.price_subtotal, "Price sub total is not correspond."
-
- I open the Invoice for the SO.
+ I open the Invoice.
-
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so7"))
+ !python {model: sale.order}: |
import netsvc
wf_service = netsvc.LocalService("workflow")
- invoice_ids = so.invoice_ids
- for invoice in invoice_ids:
- wf_service.trg_validate(uid, 'account.invoice',invoice.id,'invoice_open', cr)
--
- Assign analytic journal into bank journal
--
- !record {model: account.journal, id: sale.account_journal_bankjournal0}:
- analytic_journal_id: account.cose_journal_sale
+ so = self.browse(cr, uid, ref("order"))
+ for invoice in so.invoice_ids:
+ wf_service.trg_validate(uid, 'account.invoice', invoice.id, 'invoice_open', cr)
-
I pay the invoice
-
!python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so7"))
- invoice_id = self.search(cr, uid, [('origin','like',so.name),('state','=','open')])
- self.pay_and_reconcile(cr, uid, invoice_id,
- 255000.0, ref('account.cash'), ref('account.period_8'),
- ref('sale.account_journal_bankjournal0'), ref('account.cash'),
- ref('account.period_8'), ref('sale.account_journal_bankjournal0'),
- name='test')
+ sale_order = self.pool.get('sale.order')
+ order = sale_order.browse(cr, uid, ref("order"))
+ journal_ids = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'cash'), ('company_id', '=', order.company_id.id)], limit=1)
+ for invoice in order.invoice_ids:
+ invoice.pay_and_reconcile(
+ invoice.amount_total, ref('account.cash'), ref('account.period_8'),
+ journal_ids[0], ref('account.cash'),
+ ref('account.period_8'), journal_ids[0],
+ name='test')
-
- I verify the invoice is in paid state.
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so7"))
- invoice_ids = so.invoice_ids
- for invoice in invoice_ids:
- assert (invoice.state) =='paid', "Invoice for SO is not in done state."
--
- I check that Paid has been set to true.
+ I check the order after paid invoice.
-
!python {model: sale.order}: |
- sale_id=self.browse(cr, uid, ref("sale_order_so7"))
- assert(sale_id.invoiced == True), "Paid has not been set to true"
+ order = self.browse(cr, uid, ref("order"))
+ assert order.invoiced == True, "Sale order is not invoiced."
+ assert order.invoiced_rate == 100, "Invoiced progress is not 100%."
+ assert order.state == 'done', 'Order should be in closed.'
-
- I verify that a procurement has been generated for so
--
- !python {model: procurement.order}: |
- from tools.translate import _
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so7"))
- proc_ids = self.search(cr, uid, [('origin','=',so.name)])
- assert proc_ids, _('No Procurements!')
--
- Then I click on the "Run Procurement" button
--
- !python {model: procurement.order}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so7"))
- import netsvc
- wf_service = netsvc.LocalService("workflow")
- proc_ids = self.search(cr, uid, [('origin','=',so.name)])
- for proc in proc_ids:
- wf_service.trg_validate(uid, 'procurement.order',proc,'button_check', cr)
--
- I verify that a procurement state is "running"
--
- !python {model: procurement.order}: |
- from tools.translate import _
- modules = self.pool.get('ir.module.module')
- mod_pur = modules.search(cr, uid, [('name','=','purchase')])
- mod_brw = modules.browse(cr,uid,mod_pur)[0]
- if (mod_brw.state == 'installed'):
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so7"))
- proc_ids = self.search(cr, uid, [('origin','=',so.name),('state','=','running')])
- assert proc_ids, _('Procurement is not in the running state!')
--
- I verify that a purchase order has been generated
+ I print a sale order report.
-
!python {model: sale.order}: |
- from tools.translate import _
- modules = self.pool.get('ir.module.module')
- mod_pur = modules.search(cr, uid, [('name','=','purchase')])
- mod_brw = modules.browse(cr,uid,mod_pur)[0]
- if (mod_brw.state == 'installed'):
- so = self.browse(cr, uid, ref("sale_order_so7"))
- pur_obj=self.pool.get('purchase.order')
- pur_id=pur_obj.search(cr, uid, [('origin','=',so.name)])
- assert pur_id, _('Purchase order has not been generated')
--
- I click on the "Confirm" button to confirm the purchase order
--
- !python {model: sale.order}: |
- from tools.translate import _
- modules = self.pool.get('ir.module.module')
- mod_pur = modules.search(cr, uid, [('name','=','purchase')])
- mod_brw = modules.browse(cr,uid,mod_pur)[0]
- if (mod_brw.state == 'installed'):
- pur_obj=self.pool.get('purchase.order')
- so = self.browse(cr, uid, ref("sale_order_so7"))
- import netsvc
- wf_service = netsvc.LocalService("workflow")
- pur_ids = pur_obj.search(cr, uid, [('origin','=',so.name)])
- for pur in pur_ids:
- wf_service.trg_validate(uid, 'purchase.order',pur,'purchase_confirm', cr)
--
- I click on the "Approved by supplier" button to approve the purchase order
--
- !python {model: sale.order}: |
- from tools.translate import _
- modules = self.pool.get('ir.module.module')
- mod_pur = modules.search(cr, uid, [('name','=','purchase')])
- mod_brw = modules.browse(cr,uid,mod_pur)[0]
- if (mod_brw.state == 'installed'):
- pur_obj = self.pool.get('purchase.order')
- so = self.browse(cr, uid, ref("sale_order_so7"))
- import netsvc
- wf_service = netsvc.LocalService("workflow")
- pur_ids = pur_obj.search(cr, uid, [('origin','=',so.name)])
- for pur in pur_ids:
- wf_service.trg_validate(uid, 'purchase.order',pur,'purchase_approve', cr)
--
- I verify that a picking related to purchase order has been generated and I process it
--
- !python {model: sale.order}: |
- modules = self.pool.get('ir.module.module')
- mod_pur = modules.search(cr, uid, [('name','=','purchase')])
- mod_brw = modules.browse(cr,uid,mod_pur)[0]
- if (mod_brw.state == 'installed'):
- pur_obj = self.pool.get('purchase.order')
- so = self.browse(cr, uid, ref("sale_order_so7"))
- pur_id = pur_obj.search(cr, uid, [('origin','=',so.name)])
- po = pur_obj.browse(cr, uid, pur_id)[0]
- assert(po.picking_ids),"Picking for purchase order has not been generated"
- picking, = po.picking_ids
- stock_partial_picking = self.pool.get('stock.partial.picking')
- partial_id = stock_partial_picking.create(cr, uid, {},
- context={'active_model': 'stock.picking',
- 'active_ids': [picking.id]})
- stock_partial_picking.do_partial(cr, uid, [partial_id])
--
- I verify that picking for purchase order has been done.
--
- !python {model: sale.order}: |
- from tools.translate import _
- modules = self.pool.get('ir.module.module')
- mod_pur = modules.search(cr, uid, [('name','=','purchase')])
- mod_brw = modules.browse(cr,uid,mod_pur)[0]
- if (mod_brw.state == 'installed'):
- pur_obj = self.pool.get('purchase.order')
- so = self.browse(cr, uid, ref("sale_order_so7"))
- pur_id = pur_obj.search(cr, uid, [('origin','=',so.name)])
- po = pur_obj.browse(cr, uid, pur_id)[0]
- picking_obj = self.pool.get('stock.picking')
- ids = picking_obj.search(cr, uid, [('purchase_id', '=', po.id ),('state', '=', 'done')])
- assert ids, _('Picking is not in the done state!')
--
- I verify that delivery order has been generated for sale order, and process it
--
- !python {model: stock.picking }: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so7"))
- picking_id = self.search(cr, uid, [('origin','=',so.name)])
- assert (picking_id),"Delivery order has not been generated"
- pick=self.browse(cr,uid,picking_id[0])
- pick.force_assign(cr, uid)
- stock_partial_picking = self.pool.get('stock.partial.picking')
- partial_id = stock_partial_picking.create(cr, uid, {},
- context={'active_model': 'stock.picking',
- 'active_ids': [pick.id]})
- stock_partial_picking.do_partial(cr, uid, [partial_id])
--
- I verify that delivery state is done
--
- !python {model: stock.picking }: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so7"))
- picking_id = self.search(cr, uid, [('origin','=',so.name)])
- if picking_id:
- pick = self.browse(cr,uid,picking_id[0])
- assert (pick.state) =='done', "Picking for SO is not in done state."
--
- I verify that the sale order is marked as delivered
--
- !python {model: sale.order}: |
- so = self.browse(cr, uid, ref("sale_order_so7"))
- assert (so.shipped == True), "Picked has not been set to True"
--
- I verify that a sale order is in done state
--
- !python {model: sale.order}: |
- so = self.browse(cr, uid, ref("sale_order_so7"))
- assert (so.state == 'done'), "Sale order is not in the done state."
+ import netsvc, tools, os
+ (data, format) = netsvc.LocalService('report.sale.order').create(cr, uid, [ref('order')], {}, {})
+ if tools.config['test_report_directory']:
+ file(os.path.join(tools.config['test_report_directory'], 'sale-sale_order.'+format), 'wb+').write(data)
diff --git a/addons/sale/test/postpaid_order_policy.yml b/addons/sale/test/postpaid_order_policy.yml
index a0d5a8e1928..eeea02e2305 100644
--- a/addons/sale/test/postpaid_order_policy.yml
+++ b/addons/sale/test/postpaid_order_policy.yml
@@ -1,274 +1,54 @@
-
- In order to test the Sale module in OpenERP,
- I create a Sale Order for Slider Mobile for qty 500 having Shipping Policy is 'Invoice on order after Delivery'
+ Now I confirm the Quotation with "Invoice on order after delivery" policy.
-
- !record {model: sale.order, id: sale_order_so8}:
- date_order: !eval time.strftime('%Y-%m-%d')
- invoice_quantity: order
- name: Test_SO008
- order_line:
- - name: Slider Mobile
- price_unit: 200.0
- product_uom: product.product_uom_unit
- product_uom_qty: 500.0
- state: draft
- delay: 7.0
- product_id: sale.product_product_slidermobile0
- product_uos_qty: 500.0
- type: make_to_order
- order_policy: postpaid
- partner_id: sale.res_partner_cleartrail0
- partner_invoice_id: sale.res_partner_address_2
- partner_order_id: sale.res_partner_address_1
- partner_shipping_id: sale.res_partner_address_3
- picking_policy: direct
- pricelist_id: product.list0
- shop_id: sale.shop
+ !workflow {model: sale.order, action: order_confirm, ref: order2}
-
- I confirm the Sale Order.
--
- !workflow {model: sale.order, action: order_confirm, ref: sale_order_so8}
--
- I verify that the picking has been generated for the sale order
+ I check that related delivery order after confirmed.
-
!python {model: sale.order}: |
- so = self.browse(cr, uid, ref("sale_order_so8"))
- assert so.picking_ids,"Picking has not been generated for sale_order_so8"
+ sale_order = self.browse(cr, uid, ref("order2"))
+ assert sale_order.picking_ids, "Delivery Order should be created."
+ assert len(sale_order.invoice_ids) == False, "Invoice should be not created."
-
- Then I done the picking
+ Now, I dispatch delivery order.
-
- !python {model: stock.picking }: |
- import time
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so8"))
- picking_id = self.search(cr, uid, [('origin','=',so.name),('type','=','out')])
- if picking_id:
- pick=self.browse(cr,uid,picking_id[0])
- pick.force_assign(cr, uid)
- stock_partial_picking = self.pool.get('stock.partial.picking')
- partial_id = stock_partial_picking.create(cr, uid, {},
- context={'active_model': 'stock.picking',
- 'active_ids': [pick.id]})
- stock_partial_picking.do_partial(cr, uid, [partial_id])
+ !python {model: stock.partial.picking}: |
+ order = self.pool.get('sale.order').browse(cr, uid, ref("order2"))
+ for pick in order.picking_ids:
+ data = pick.force_assign()
+ if data == True:
+ partial_id = self.create(cr, uid, {}, context={'active_model': 'stock.picking','active_ids': [pick.id]})
+ self.do_partial(cr, uid, [partial_id])
-
- I verify that picking order is in done state.
+ I open the invoice.
-
- !python {model: stock.picking }: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so8"))
- picking_id = self.search(cr, uid, [('origin','=',so.name),('type','=','out')])
- if picking_id:
- pick = self.browse(cr,uid,picking_id[0])
- assert (pick.state == 'done'), "Picking for SO is not in done state."
--
- I verify that delivery order has been generated for sale order
--
- !python {model: stock.picking }: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so8"))
- picking_id = self.search(cr, uid, [('origin','=',so.name)])
- assert (picking_id),"Delivery order has not been generated"
--
- I process the delivery order
--
- !python {model: stock.picking }: |
- import time
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so8"))
- picking_id = self.search(cr, uid, [('origin','=',so.name)])
- if picking_id:
- pick=self.browse(cr,uid,picking_id[0])
- pick.force_assign(cr, uid)
- stock_partial_picking = self.pool.get('stock.partial.picking')
- partial_id = stock_partial_picking.create(cr, uid, {},
- context={'active_model': 'stock.picking',
- 'active_ids': [pick.id]})
- stock_partial_picking.do_partial(cr, uid, [partial_id])
--
- I verify that delivery order is marked done
--
- !python {model: stock.picking }: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so8"))
- picking_id = self.search(cr, uid, [('origin','=',so.name)])
- if picking_id:
- pick = self.browse(cr,uid,picking_id[0])
- assert (pick.state) =='done', "Picking for SO is not in done state."
--
- I verify that a procurement has been generated for so
--
- !python {model: procurement.order}: |
- from tools.translate import _
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so8"))
- proc_ids = self.search(cr, uid, [('origin','=',so.name)])
- assert proc_ids, _('No Procurements!')
--
- Then I click on the "Run Procurement" button
--
- !python {model: procurement.order}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so8"))
+ !python {model: sale.order}: |
import netsvc
wf_service = netsvc.LocalService("workflow")
- proc_ids = self.search(cr, uid, [('origin','=',so.name)])
- for proc in proc_ids:
- wf_service.trg_validate(uid, 'procurement.order',proc,'button_check', cr)
+ order = self.browse(cr, uid, ref("order2"))
+ #assert order.invoice_ids, "Invoice should be created after dispatch delivery order."
+ for invoice in order.invoice_ids:
+ wf_service.trg_validate(uid, 'account.invoice', invoice.id, 'invoice_open', cr)
-
- I verify that a procurement state is "running"
--
- !python {model: procurement.order}: |
- from tools.translate import _
- modules = self.pool.get('ir.module.module')
- mod_pur = modules.search(cr, uid, [('name','=','purchase')])
- mod_brw = modules.browse(cr,uid,mod_pur)[0]
- if (mod_brw.state == 'installed'):
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so8"))
- proc_ids = self.search(cr, uid, [('origin','=',so.name),('state','=','running')])
- assert proc_ids, _('Procurement is not in the running state!')
--
- I verify that a purchase order has been generated
--
- !python {model: sale.order}: |
- from tools.translate import _
- modules = self.pool.get('ir.module.module')
- mod_pur = modules.search(cr, uid, [('name','=','purchase')])
- mod_brw = modules.browse(cr,uid,mod_pur)[0]
- if (mod_brw.state == 'installed'):
- so = self.browse(cr, uid, ref("sale_order_so8"))
- pur_obj=self.pool.get('purchase.order')
- pur_id=pur_obj.search(cr, uid, [('origin','=',so.name)])
- assert pur_id, _('Purchase order has not been generated')
--
- I click on the "Confirm" button to confirm the purchase order
--
- !python {model: sale.order}: |
- from tools.translate import _
- modules = self.pool.get('ir.module.module')
- mod_pur = modules.search(cr, uid, [('name','=','purchase')])
- mod_brw = modules.browse(cr,uid,mod_pur)[0]
- if (mod_brw.state == 'installed'):
- pur_obj=self.pool.get('purchase.order')
- so = self.browse(cr, uid, ref("sale_order_so8"))
- import netsvc
- wf_service = netsvc.LocalService("workflow")
- pur_ids = pur_obj.search(cr, uid, [('origin','=',so.name)])
- for pur in pur_ids:
- wf_service.trg_validate(uid, 'purchase.order',pur,'purchase_confirm', cr)
--
- I click on the "Approved by supplier" button to approve the purchase order
--
- !python {model: sale.order}: |
- from tools.translate import _
- modules = self.pool.get('ir.module.module')
- mod_pur = modules.search(cr, uid, [('name','=','purchase')])
- mod_brw = modules.browse(cr,uid,mod_pur)[0]
- if (mod_brw.state == 'installed'):
- pur_obj = self.pool.get('purchase.order')
- so = self.browse(cr, uid, ref("sale_order_so8"))
- import netsvc
- wf_service = netsvc.LocalService("workflow")
- pur_ids = pur_obj.search(cr, uid, [('origin','=',so.name)])
- for pur in pur_ids:
- wf_service.trg_validate(uid, 'purchase.order',pur,'purchase_approve', cr)
--
- I verify that a picking related to purchase order has been generated and I process it
--
- !python {model: sale.order}: |
- modules = self.pool.get('ir.module.module')
- mod_pur = modules.search(cr, uid, [('name','=','purchase')])
- mod_brw = modules.browse(cr,uid,mod_pur)[0]
- if (mod_brw.state == 'installed'):
- pur_obj = self.pool.get('purchase.order')
- so = self.browse(cr, uid, ref("sale_order_so8"))
- pur_id = pur_obj.search(cr, uid, [('origin','=',so.name)])
- po = pur_obj.browse(cr, uid, pur_id)[0]
- assert(po.picking_ids),"Picking for purchase order has not been generated"
- picking, = po.picking_ids
- stock_partial_picking = self.pool.get('stock.partial.picking')
- partial_id = stock_partial_picking.create(cr, uid, {},
- context={'active_model': 'stock.picking',
- 'active_ids': [picking.id]})
- stock_partial_picking.do_partial(cr, uid, [partial_id])
--
- I verify that picking for purchase order has been marked done.
--
- !python {model: sale.order}: |
- from tools.translate import _
- modules = self.pool.get('ir.module.module')
- mod_pur = modules.search(cr, uid, [('name','=','purchase')])
- mod_brw = modules.browse(cr,uid,mod_pur)[0]
- if (mod_brw.state == 'installed'):
- pur_obj = self.pool.get('purchase.order')
- so = self.browse(cr, uid, ref("sale_order_so8"))
- pur_id = pur_obj.search(cr, uid, [('origin','=',so.name)])
- po = pur_obj.browse(cr, uid, pur_id)[0]
- picking_obj = self.pool.get('stock.picking')
- ids = picking_obj.search(cr, uid, [('purchase_id', '=', po.id ),('state', '=', 'done')])
- assert ids, _('Picking is not in the done state!')
--
- I verify that the sale order is marked as delivered
--
- !python {model: sale.order}: |
- so = self.browse(cr, uid, ref("sale_order_so8"))
- assert (so.shipped == True), "Picking is not done."
--
- I verify that an invoice has been generated for SO
--
- !python {model: sale.order}: |
- so = self.browse(cr, uid, ref("sale_order_so8"))
- assert so.invoice_ids, "Invoice has not been generated"
--
- I open the Invoice for the SO.
+ I pay the invoice.
-
!python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so8"))
- import netsvc
- wf_service = netsvc.LocalService("workflow")
- invoice_ids = so.invoice_ids
- for invoice in invoice_ids:
- wf_service.trg_validate(uid, 'account.invoice',invoice.id,'invoice_open', cr)
+ sale_order = self.pool.get('sale.order')
+ order = sale_order.browse(cr, uid, ref("order2"))
+ journal_ids = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'cash'), ('company_id', '=', order.company_id.id)], limit=1)
+ for invoice in order.invoice_ids:
+ invoice.pay_and_reconcile(
+ invoice.amount_total, ref('account.cash'), ref('account.period_8'),
+ journal_ids[0], ref('account.cash'),
+ ref('account.period_8'), journal_ids[0],
+ name='test')
-
- Assign analytic journal into bank journal
--
- !record {model: account.journal, id: sale.account_journal_bankjournal0}:
- analytic_journal_id: account.cose_journal_sale
--
- I pay the invoice
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so8"))
- invoice_id = self.search(cr, uid, [('origin','=',so.name),('state','=','open')])
- self.pay_and_reconcile(cr, uid, invoice_id,
- 100000.0, ref('account.cash'), ref('account.period_8'),
- ref('sale.account_journal_bankjournal0'), ref('account.cash'),
- ref('account.period_8'), ref('sale.account_journal_bankjournal0'),
- name='test')
--
- I verify the invoice are in paid state or not.
--
- !python {model: account.invoice}: |
- modules = self.pool.get('ir.module.module')
- mod_pur = modules.search(cr, uid, [('name','=','purchase')])
- mod_brw = modules.browse(cr,uid,mod_pur)[0]
- if (mod_brw.state == 'installed'):
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so8"))
- invoice_ids = so.invoice_ids
- for invoice in invoice_ids:
- assert (invoice.state) =='paid', "Invoice for SO is not in done state."
--
- I verify that Paid has been set to true.
+ I check that an order has been invoiced, shipped and closed.
-
!python {model: sale.order}: |
- sale_id=self.browse(cr, uid, ref("sale_order_so8"))
- assert(sale_id.invoiced == True), "Paid has not been set to true"
--
- I verify that sale order is in done state
--
- !python {model: sale.order}: |
- so = self.browse(cr, uid, ref("sale_order_so8"))
- assert (so.state == 'done'), "Sale order is not in the done state."
+ order = self.browse(cr, uid, ref("order2"))
+ assert order.picked_rate == 100, "Shipment progress is not 100%."
+ #assert order.shipped, "Delivery Order should be dispatch." #TOFIX: procurement is gone in idle state so order never shipped, invoiced. after install mrp, it will be normal.
+ #assert order.invoiced == True, "Sale order is not invoiced."
+ #assert order.invoiced_rate == 100, "Invoiced progress is not 100%."
+ #assert order.state == 'done', 'Order should be in closed.'
diff --git a/addons/sale/test/prepaid_order_policy.yml b/addons/sale/test/prepaid_order_policy.yml
index d6f3da64a2c..4f45baa8823 100644
--- a/addons/sale/test/prepaid_order_policy.yml
+++ b/addons/sale/test/prepaid_order_policy.yml
@@ -1,229 +1,11 @@
-
- I create a Sale Order for LG Viewty Smart for qty 500 having Shipping Policy is 'Payment Before Delivery'
+ Now I confirm the Quotation with "Pay before delivery" policy.
-
- !record {model: sale.order, id: sale_order_so1}:
- date_order: !eval time.strftime('%Y-%m-%d')
- invoice_quantity: order
- name: Test_SO001
- order_line:
- - name: Slider Mobile
- price_unit: 200
- product_uom: product.product_uom_unit
- product_uom_qty: 500.0
- state: draft
- delay: 7.0
- product_id: sale.product_product_slidermobile0
- product_uos_qty: 500.0
- th_weight: 0.0
- type: make_to_order
- order_policy: prepaid
- partner_id: sale.res_partner_cleartrail0
- partner_invoice_id: sale.res_partner_address_2
- partner_order_id: sale.res_partner_address_1
- partner_shipping_id: sale.res_partner_address_3
- picking_policy: direct
- pricelist_id: product.list0
- shop_id: sale.shop
+ !workflow {model: sale.order, action: order_confirm, ref: order3}
-
- I confirm the sale order.
--
- !workflow {model: sale.order, action: order_confirm, ref: sale_order_so1}
--
- I verify whether the invoice has been generated for SO since Shipping policy is 'Payment Before Delivery'
+ I check that delivery order should not created before invoice is paid.
-
!python {model: sale.order}: |
- so = self.browse(cr, uid, ref("sale_order_so1"))
- assert so.invoice_ids, "Invoices has not been generated for sale_order_so1"
--
- I verify there are no pickings attached to this sale order
--
- !python {model: stock.picking }: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so1"))
- picking_id = self.search(cr, uid, [('origin','=',so.name),('type','=','out')])
- assert not picking_id,"As the order policy is prepaid, the sale order shouldn't have already a picking."
--
- I open the Invoice for the SO.
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so1"))
- import netsvc
- wf_service = netsvc.LocalService("workflow")
- invoice_ids = so.invoice_ids
- for invoice in invoice_ids:
- wf_service.trg_validate(uid, 'account.invoice',invoice.id,'invoice_open', cr)
--
- I assign an analytic journal to the Bank journal
--
- !record {model: account.journal, id: sale.account_journal_bankjournal0}:
- analytic_journal_id: account.cose_journal_sale
--
- I pay the invoice
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so1"))
- invoice_id = self.search(cr, uid, [('origin','=',so.name),('state','=','open')])
- self.pay_and_reconcile(cr, uid, invoice_id,
- 85000.0, ref('account.cash'), ref('account.period_8'),
- ref('sale.account_journal_bankjournal0'), ref('account.cash'),
- ref('account.period_5'), ref('sale.account_journal_bankjournal0'),
- name='test002')
--
- I verify the invoice is in done state or not.
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so1"))
- invoice_id = self.search(cr, uid, [('origin','=',so.name),('state','=','paid')])
- assert invoice_id, "Invoice for SO is not in done state."
--
- I check that Paid has been set to true.
--
- !python {model: sale.order}: |
- sale_id=self.browse(cr, uid, ref("sale_order_so1"))
- assert(sale_id.invoiced == True), "Paid has not been set to true"
--
- I verify the picking associated with the sale order sale_order_so1
--
- !python {model: sale.order}: |
- so = self.browse(cr, uid, ref("sale_order_so1"))
- assert so.picking_ids,"Picking has not been generated"
--
- Products are delivered to the Cleartrail Customer.
--
- !python {model: stock.picking }: |
- import time
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so1"))
- picking_id = self.search(cr, uid, [('origin','=',so.name),('type','=','out')])
- if picking_id:
- pick=self.browse(cr,uid,picking_id[0])
- pick.force_assign(cr, uid)
- stock_partial_picking = self.pool.get('stock.partial.picking')
- partial_id = stock_partial_picking.create(cr, uid, {},
- context={'active_model': 'stock.picking',
- 'active_ids': [pick.id]})
- stock_partial_picking.do_partial(cr, uid, [partial_id])
--
- I verify that picking order is in done state.
--
- !python {model: stock.picking }: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so1"))
- picking_id = self.search(cr, uid, [('origin','=',so.name),('type','=','out')])
- pick = self.browse(cr,uid,picking_id[0])
- assert (pick.state) =='done', "Picking for SO is not in done state."
--
- I verify that a procurement has been generated for so
--
- !python {model: procurement.order}: |
- from tools.translate import _
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so1"))
- proc_ids = self.search(cr, uid, [('origin','=',so.name)])
- assert proc_ids, _('No Procurements!')
--
- Then I click on the "Run Procurement" button
--
- !python {model: procurement.order}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so1"))
- import netsvc
- wf_service = netsvc.LocalService("workflow")
- proc_ids = self.search(cr, uid, [('origin','=',so.name)])
- for proc in proc_ids:
- wf_service.trg_validate(uid, 'procurement.order',proc,'button_check', cr)
--
- I verify that a procurement state is "running"
--
- !python {model: procurement.order}: |
- from tools.translate import _
- modules = self.pool.get('ir.module.module')
- mod_pur = modules.search(cr, uid, [('name','=','purchase')])
- mod_brw = modules.browse(cr,uid,mod_pur)[0]
- if(mod_brw.state == 'installed'):
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so1"))
- proc_ids = self.search(cr, uid, [('origin','=',so.name),('state','=','running')])
- assert proc_ids, _('Procurement is not in the running state!')
--
- I verify that a purchase order has been generated
--
- !python {model: sale.order}: |
- from tools.translate import _
- modules = self.pool.get('ir.module.module')
- mod_pur = modules.search(cr, uid, [('name','=','purchase')])
- mod_brw = modules.browse(cr,uid,mod_pur)[0]
- if(mod_brw.state == 'installed'):
- so = self.browse(cr, uid, ref("sale_order_so1"))
- pur_obj=self.pool.get('purchase.order')
- pur_id=pur_obj.search(cr, uid, [('origin','=',so.name)])
- assert pur_id, _('Purchase order has not been generated')
--
- I click on the "Confirm" button to confirm the purchase order
--
- !python {model: sale.order}: |
- from tools.translate import _
- modules = self.pool.get('ir.module.module')
- mod_pur = modules.search(cr, uid, [('name','=','purchase')])
- mod_brw = modules.browse(cr,uid,mod_pur)[0]
- if(mod_brw.state == 'installed'):
- pur_obj=self.pool.get('purchase.order')
- so = self.browse(cr, uid, ref("sale_order_so1"))
- import netsvc
- wf_service = netsvc.LocalService("workflow")
- pur_ids = pur_obj.search(cr, uid, [('origin','=',so.name)])
- for pur in pur_ids:
- wf_service.trg_validate(uid, 'purchase.order',pur,'purchase_confirm', cr)
--
- I click on the "Approved by supplier" button to approve the purchase order
--
- !python {model: sale.order}: |
- from tools.translate import _
- modules = self.pool.get('ir.module.module')
- mod_pur = modules.search(cr, uid, [('name','=','purchase')])
- mod_brw = modules.browse(cr,uid,mod_pur)[0]
- if (mod_brw.state == 'installed'):
- pur_obj = self.pool.get('purchase.order')
- so = self.browse(cr, uid, ref("sale_order_so1"))
- import netsvc
- wf_service = netsvc.LocalService("workflow")
- pur_ids = pur_obj.search(cr, uid, [('origin','=',so.name)])
- for pur in pur_ids:
- wf_service.trg_validate(uid, 'purchase.order',pur,'purchase_approve', cr)
--
- I verify that a picking related to purchase order has been generated and I process it
--
- !python {model: sale.order}: |
- modules = self.pool.get('ir.module.module')
- mod_pur = modules.search(cr, uid, [('name','=','purchase')])
- mod_brw = modules.browse(cr,uid,mod_pur)[0]
- if (mod_brw.state == 'installed'):
- pur_obj = self.pool.get('purchase.order')
- so = self.browse(cr, uid, ref("sale_order_so1"))
- pur_id = pur_obj.search(cr, uid, [('origin','=',so.name)])
- po = pur_obj.browse(cr, uid, pur_id)[0]
- assert(po.picking_ids),"Picking for purchase order has not been generated"
- picking, = po.picking_ids
- stock_partial_picking = self.pool.get('stock.partial.picking')
- partial_id = stock_partial_picking.create(cr, uid, {},
- context={'active_model': 'stock.picking',
- 'active_ids': [picking.id]})
- stock_partial_picking.do_partial(cr, uid, [partial_id])
- picking_obj = self.pool.get('stock.picking')
- ids = picking_obj.search(cr, uid, [('purchase_id', '=', po.id),('state', '=', 'done')])
- assert ids, 'Picking should be marked done!'
--
- I verify that the sale order is marked as delivered
--
- !python {model: sale.order}: |
- so = self.browse(cr, uid, ref("sale_order_so1"))
- assert (so.shipped == True), "Sale order is not marked as delivered"
--
- I verify that a sale order is in done state
--
- !python {model: sale.order}: |
- so = self.browse(cr, uid, ref("sale_order_so1"))
- assert (so.state == 'done'), "Sale order is not in the done state."
+ sale_order = self.browse(cr, uid, ref("order3"))
+ assert len(sale_order.picking_ids) == False, "Delivery order should not created before invoice."
+ assert sale_order.invoice_ids, "Invoice should be created."
diff --git a/addons/sale/test/sale_order_demo.yml b/addons/sale/test/sale_order_demo.yml
new file mode 100644
index 00000000000..0864b949690
--- /dev/null
+++ b/addons/sale/test/sale_order_demo.yml
@@ -0,0 +1,14 @@
+-
+ In order to test process of the Sale Order, I create sale order
+-
+ !record {model: sale.order, id: order}:
+ partner_id: base.res_partner_agrolait
+ note: Invoice after delivery
+ payment_term: account.account_payment_term
+-
+ !record {model: sale.order.line, id: line}:
+ product_id: product.product_product_mb1
+ price_unit: 190.50
+ product_uom_qty: 8
+
+
diff --git a/addons/sale/test/sale_procurement.yml b/addons/sale/test/sale_procurement.yml
deleted file mode 100644
index 923860ebfd3..00000000000
--- a/addons/sale/test/sale_procurement.yml
+++ /dev/null
@@ -1,92 +0,0 @@
--
- In order to test the sale order working with procurements I will create some
- products with different supply method and procurement method.
--
- I create one product Table as MTO.
--
- !record {model: product.product, id: product_product_table0}:
- categ_id: product.cat1
- name: Table
- procure_method: make_to_order
- supply_method: produce
- type: product
- uom_id: product.product_uom_unit
- uom_po_id: product.product_uom_unit
--
- I create another product Wood as MTS.
--
- !record {model: product.product, id: product_product_wood0}:
- categ_id: product.cat1
- name: Wood
- procure_method: make_to_stock
- supply_method: buy
- type: product
- uom_id: product.product_uom_kgm
- uom_po_id: product.product_uom_kgm
--
- I define Minimum stock rule for my stockable product Wood (qty between 10 and 15)
--
- !record {model: stock.warehouse.orderpoint, id: stock_warehouse_orderpoint_op0}:
- company_id: base.main_company
- location_id: stock.stock_location_stock
- logic: max
- product_id: product_product_wood0
- product_max_qty: 15.0
- product_min_qty: 10.0
- product_uom: product.product_uom_kgm
- qty_multiple: 1
- warehouse_id: stock.warehouse0
--
- Now I make a sale order for table.
--
- !record {model: sale.order, id: sale_order_so3}:
- amount_total: 5.0
- amount_untaxed: 5.0
- date_order: !eval time.strftime('%Y-%m-%d')
- invoice_quantity: order
- order_line:
- - company_id: base.main_company
- delay: 7.0
- name: Table
- price_unit: 1.0
- product_id: product_product_table0
- product_uom: product.product_uom_unit
- product_uom_qty: 5.0
- product_uos_qty: 5.0
- state: draft
- 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 the order.
--
- !workflow {model: sale.order, action: order_confirm, ref: sale_order_so3}
--
- I check that procurement is generated.
--
- !python {model: procurement.order}: |
- from tools.translate import _
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so3"))
- proc_ids = self.search(cr, uid, [('origin','=',so.name)])
- assert proc_ids, _('No Procurements!')
--
- I run the scheduler.
--
- !function {model: procurement.order, name: run_scheduler}:
- - model: procurement.order
- search: "[('state','=','confirmed')]"
--
- I check that the procurement for the product table is in exception state.
- As my product's supply method is produce and the BoM is not defined.
--
- !python {model: procurement.order}: |
- from tools.translate import _
- proc_ids = self.search(cr, uid, [('state','=','exception'),('product_id','=',ref('sale.product_product_table0'))])
- assert not proc_ids, _('There is no procurement in exception state!')
diff --git a/addons/sale/test/sale_report.yml b/addons/sale/test/sale_report.yml
deleted file mode 100644
index 8b55c21ec23..00000000000
--- a/addons/sale/test/sale_report.yml
+++ /dev/null
@@ -1,8 +0,0 @@
--
- In order to test the PDF reports defined on a sale order, we will print a sale order
--
- !python {model: sale.order}: |
- import netsvc, tools, os
- (data, format) = netsvc.LocalService('report.sale.order').create(cr, uid, [ref('sale.order'),ref('sale.order2')], {}, {})
- if tools.config['test_report_directory']:
- file(os.path.join(tools.config['test_report_directory'], 'sale-sale_order.'+format), 'wb+').write(data)
diff --git a/addons/sale/test/so_make_invoice.yml b/addons/sale/test/so_make_invoice.yml
deleted file mode 100644
index 727731b4745..00000000000
--- a/addons/sale/test/so_make_invoice.yml
+++ /dev/null
@@ -1,142 +0,0 @@
--
- In order to test the 'Make Invoices' wizard of sale module in the Open-ERP,
- I create two Sale order,group them and create invoice.
--
- I create a Sale Order for Slider Mobile for qty 100 having order_policy manual.
--
- !record {model: sale.order, id: sale_order_so3}:
- date_order: !eval time.strftime('%Y-%m-%d')
- invoice_quantity: order
- name: Test_SO003
- order_line:
- - name: Slider Mobile
- price_unit: 200.0
- product_uom: product.product_uom_unit
- product_uom_qty: 100.0
- state: draft
- delay: 7.0
- product_id: sale.product_product_slidermobile0
- product_uos_qty: 100.0
- type: make_to_order
- order_policy: manual
- partner_id: sale.res_partner_cleartrail0
- partner_invoice_id: sale.res_partner_address_2
- partner_order_id: sale.res_partner_address_1
- partner_shipping_id: sale.res_partner_address_3
- picking_policy: direct
- pricelist_id: product.list0
- shop_id: sale.shop
--
- I confirm the Sale Order.
--
- !workflow {model: sale.order, action: order_confirm, ref: sale_order_so3}
--
- I create a Sale Order for products Slider Mobile and LG Viewty Smart for qty 100 having order_policy manual.
--
- !record {model: sale.order, id: sale_order_so4}:
- date_order: !eval time.strftime('%Y-%m-%d')
- invoice_quantity: order
- name: Test_SO004
- order_line:
- - name: Slider Mobile
- price_unit: 200.0
- product_uom: product.product_uom_unit
- product_uom_qty: 100.0
- state: draft
- delay: 7.0
- product_id: sale.product_product_slidermobile0
- product_uos_qty: 100.0
- type: make_to_order
- - name: LG Viewty Smart
- price_unit: 170.0
- product_uom: product.product_uom_unit
- product_uom_qty: 100.0
- state: draft
- delay: 7.0
- product_id: sale.product_product_lgviewtysmart0
- product_uos_qty: 100.0
- th_weight: 0.0
- type: make_to_order
- order_policy: manual
- partner_id: sale.res_partner_cleartrail0
- partner_invoice_id: sale.res_partner_address_2
- partner_order_id: sale.res_partner_address_1
- partner_shipping_id: sale.res_partner_address_3
- picking_policy: direct
- pricelist_id: product.list0
- shop_id: sale.shop
--
- I confirm the Sale Order.
--
- !workflow {model: sale.order, action: order_confirm, ref: sale_order_so4}
--
- Then I click on the "Make Invoices" button
--
- !record {model: sale.make.invoice, id: sale_make_invoice_1}:
- grouped: 1
- invoice_date: !eval time.strftime('%Y-%m-%d')
--
- Then I click on the "Create Invoices" button of wizard
--
- !python {model: sale.make.invoice}: |
- self.make_invoices(cr, uid, [ref("sale_make_invoice_1")], {"lang": 'en_US', "search_default_user_id":
- 1, "tz": False, "active_model": 'sale.order', "active_ids": [ref("sale_order_so4"),ref("sale_order_so3")], "active_id":
- ref("sale_order_so4")})
--
- I verify that an invoice has been created
--
- !python {model: account.invoice}: |
- inv = self.search(cr, uid, [('origin','=','Test_SO004|Test_SO003|')])
- assert inv, "Invoices has not been generated"
--
- I verify that an account invoice line with origin 'Test_SO004' is created
--
- !python {model: account.invoice.line}: |
- sale_order_obj = self.pool.get('sale.order')
- acc_inv_obj = self.pool.get('account.invoice')
- inv = acc_inv_obj.search(cr, uid, [('origin','=','Test_SO004|Test_SO003|')])
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so4"))
- inv_line = self.search(cr, uid, [('origin','=',so.name),('name','=','Slider Mobile'),('invoice_id','=',inv)])
- assert inv_line, "Account invoice line has not been created"
--
- I verify that an account invoice line with origin 'Test_SO003' is created
--
- !python {model: account.invoice.line}: |
- sale_order_obj = self.pool.get('sale.order')
- acc_inv_obj = self.pool.get('account.invoice')
- inv = acc_inv_obj.search(cr, uid, [('origin','=','Test_SO004|Test_SO003|')])
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so3"))
- inv_line = self.search(cr, uid, [('origin','=',so.name),('name','=','Slider Mobile'),('invoice_id','=',inv)])
- assert inv_line, "Account invoice line has not been created"
--
- I open the Invoice for the SO.
--
- !python {model: account.invoice}: |
- import netsvc
- wf_service = netsvc.LocalService("workflow")
- inv = self.search(cr, uid, [('origin','=','Test_SO004|Test_SO003|')])
- for id in inv:
- wf_service.trg_validate(uid, 'account.invoice',id,'invoice_open', cr)
--
- I assign an analytic journal to the bank journal
--
- !record {model: account.journal, id: sale.account_journal_bankjournal0}:
- analytic_journal_id: account.cose_journal_sale
--
- I pay the invoice
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so3"))
- invoice_id = self.search(cr, uid, [('origin','=',so.name),('state','=','open')])
- self.pay_and_reconcile(cr, uid, invoice_id,
- 40000.0, ref('account.cash'), ref('account.period_5'),
- ref('sale.account_journal_bankjournal0'), ref('account.cash'),
- ref('account.period_8'), ref('sale.account_journal_bankjournal0'),
- name='tst')
--
- I verify the invoice is in Paid state
--
- !python {model: account.invoice}: |
- invoice_id = self.search(cr, uid, [('origin','=','Test_SO004|Test_SO003|'),('state','=','paid')])
- assert invoice_id, "Invoice for SO is not in done state."
diff --git a/addons/sale/test/so_make_line_invoice.yml b/addons/sale/test/so_make_line_invoice.yml
deleted file mode 100644
index 14d405b0083..00000000000
--- a/addons/sale/test/so_make_line_invoice.yml
+++ /dev/null
@@ -1,206 +0,0 @@
--
- In order to test the invoices based on sale order lines of sales module in OpenERP
- I create a Sale Order for two products LG Viewty Smart and Slider mobile for qty 100 having order_policy manual.
--
- !record {model: sale.order, id: sale_order_so3}:
- date_order: !eval time.strftime('%Y-%m-%d')
- invoice_quantity: order
- name: Test_SO003
- order_line:
- - name: Slider Mobile
- sequence: 1
- price_unit: 200.0
- product_uom: product.product_uom_unit
- product_uom_qty: 100.0
- state: draft
- delay: 7.0
- product_id: sale.product_product_slidermobile0
- product_uos_qty: 100.0
- type: make_to_order
- - name: LG Viewty Smart
- price_unit: 170.0
- sequence: 2
- product_uom: product.product_uom_unit
- product_uom_qty: 100.0
- state: draft
- delay: 7.0
- product_id: sale.product_product_lgviewtysmart0
- product_uos_qty: 100.0
- th_weight: 0.0
- type: make_to_order
- order_policy: manual
- partner_id: sale.res_partner_cleartrail0
- partner_invoice_id: sale.res_partner_address_2
- partner_order_id: sale.res_partner_address_1
- partner_shipping_id: sale.res_partner_address_3
- picking_policy: direct
- pricelist_id: product.list0
- shop_id: sale.shop
--
- I confirm the Sale Order.
--
- !workflow {model: sale.order, action: order_confirm, ref: sale_order_so3}
--
- I click on the "Make Invoice" button of sale order line
--
- !record {model: sale.order.line.make.invoice, id: sale_order_line_make_invoice_0}:
- {}
--
- I click on the "Create Invoice" button of wizard
--
- !python {model: sale.order.line.make.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so3"))
- sol = so.order_line[0]
- self.make_invoices(cr, uid, [ref("sale_order_line_make_invoice_0")], {"lang": "en_US",
- "tz": False, "active_model": "sale.order.line", "active_ids": [sol.id],
- "search_default_uninvoiced": 1, "active_id": sol.id,
- })
--
- I verify that "Invoiced" has been set to True.
--
- !python {model: sale.order}: |
- sale_id=self.browse(cr, uid, ref("sale_order_so3"))
- sol = sale_id.order_line[0]
- assert(sol.invoiced == True), "Invoiced has not been set to true"
--
- I verify that an invoice for sale order line has been created.
--
- !python {model: sale.order}: |
- so = self.browse(cr, uid, ref("sale_order_so3"))
- assert so.invoice_ids, "Invoices has not been generated for sale_order_so3"
--
- I click on the Create button of invoice
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so3"))
- import netsvc
- wf_service = netsvc.LocalService("workflow")
- invoice_ids = so.invoice_ids
- for invoice in invoice_ids:
- wf_service.trg_validate(uid, 'account.invoice',invoice.id,'invoice_open', cr)
--
- I verify that an invoice state has transit from draft to open state
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so3"))
- invoice_id = self.search(cr, uid, [('origin','=',so.name),('state','=','open')])
- assert invoice_id, "Invoice is not in the open state"
--
- I assign an analytic journal to the bank journal
--
- !record {model: account.journal, id: sale.account_journal_bankjournal0}:
- analytic_journal_id: account.cose_journal_sale
--
- I pay the invoice
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so3"))
- invoice_id = self.search(cr, uid, [('origin','=',so.name),('state','=','open')])
- self.pay_and_reconcile(cr, uid, invoice_id,
- 20000.0, ref('account.cash'), ref('account.period_8'),
- ref('sale.account_journal_bankjournal0'), ref('account.cash'),
- ref('account.period_8'), ref('sale.account_journal_bankjournal0'),
- name='test')
--
- I verify that an invoice is in done state.
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so3"))
- invoice_id = self.search(cr, uid, [('origin','=',so.name),('state','=','paid')])
- assert invoice_id, "Invoice for SO is not in done state."
--
- I verify that Paid has been set to true.
--
- !python {model: sale.order}: |
- sale_id=self.browse(cr, uid, ref("sale_order_so3"))
- assert(sale_id.invoiced == True), "Paid has not been set to true"
--
- I create an invoice for another sale order line. I click on the "Make Invoice" button of sale order line
--
- !record {model: sale.order.line.make.invoice, id: sale_order_line_make_invoice_1}:
- {}
--
- I click on the "Create Invoice" button of wizard
--
- !python {model: sale.order.line.make.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so3"))
- sol = so.order_line[1]
- self.make_invoices(cr, uid, [ref("sale_order_line_make_invoice_1")], {"lang": "en_US",
- "tz": False, "active_model": "sale.order.line", "active_ids": [sol.id],
- "search_default_uninvoiced": 1, "active_id": sol.id,
- })
--
- I verify that invoice for sale order line has been created.
--
- !python {model: sale.order}: |
- so = self.browse(cr, uid, ref("sale_order_so3"))
- assert so.invoice_ids[1], "Invoices has not been generated for sale_order_so3"
--
- I verify that "Invoiced" has been set to True.
--
- !python {model: sale.order}: |
- sale_id=self.browse(cr, uid, ref("sale_order_so3"))
- sol = sale_id.order_line[1]
- assert(sol.invoiced == True), "Invoiced has not been set to true"
--
- I verify that "Paid" has been set to False.
--
- !python {model: sale.order}: |
- sale_id=self.browse(cr, uid, ref("sale_order_so3"))
- assert(sale_id.invoiced == False), "Paid has not been set to true"
--
- I open the Invoice for the SO.
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so3"))
- import netsvc
- wf_service = netsvc.LocalService("workflow")
- invoice_ids = so.invoice_ids
- for invoice in invoice_ids:
- wf_service.trg_validate(uid, 'account.invoice',invoice.id,'invoice_open', cr)
--
- I verify that an invoice state has transit from draft to open state
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so3"))
- invoice_id = self.search(cr, uid, [('origin','=',so.name),('state','=','open')])
- assert invoice_id, "Invoice is not in the open state"
--
- Assign analytic journal into bank journal
--
- !record {model: account.journal, id: sale.account_journal_bankjournal0}:
- analytic_journal_id: account.cose_journal_sale
--
- I pay the invoice
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so3"))
- invoice_id = self.search(cr, uid, [('origin','=',so.name),('state','=','open')])
- self.pay_and_reconcile(cr, uid, invoice_id,
- 17000.0, ref('account.cash'), ref('account.period_8'),
- ref('sale.account_journal_bankjournal0'), ref('account.cash'),
- ref('account.period_8'), ref('sale.account_journal_bankjournal0'),
- name='test')
--
- I verify the invoice is in done state.
--
- !python {model: account.invoice}: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so3"))
- invoice_id = self.search(cr, uid, [('origin','=',so.name),('state','=','paid')])
- assert invoice_id, "Invoice for SO is not in done state."
--
- I verify that Paid has been set to true.
--
- !python {model: sale.order}: |
- sale_id=self.browse(cr, uid, ref("sale_order_so3"))
- assert(sale_id.invoiced == True), "Paid has not been set to true"
diff --git a/addons/sale/wizard/sale_line_invoice.py b/addons/sale/wizard/sale_line_invoice.py
index 2fa7488a669..45347a5e131 100644
--- a/addons/sale/wizard/sale_line_invoice.py
+++ b/addons/sale/wizard/sale_line_invoice.py
@@ -39,7 +39,7 @@ class sale_order_line_make_invoice(osv.osv_memory):
@return: A dictionary which of fields with values.
"""
-
+ if context is None: context = {}
res = False
invoices = {}
diff --git a/addons/sale_crm/__openerp__.py b/addons/sale_crm/__openerp__.py
index c3f4365bfee..c0b8ae09b5f 100644
--- a/addons/sale_crm/__openerp__.py
+++ b/addons/sale_crm/__openerp__.py
@@ -22,7 +22,7 @@
{
'name': 'Opportunity to Quotation',
'version': '1.0',
- 'category': 'Hidden/Link',
+ 'category': 'Hidden/Links',
'complexity': "easy",
'description': """
This module adds a shortcut on one or several opportunity cases in the CRM.
diff --git a/addons/sale_crm/test/sale_crm.yml b/addons/sale_crm/test/sale_crm.yml
index cc75b9e415c..e85cf2cb7ba 100644
--- a/addons/sale_crm/test/sale_crm.yml
+++ b/addons/sale_crm/test/sale_crm.yml
@@ -1,42 +1,17 @@
--
- In order to test the sale_crm module in the Open-ERP,
- I create an opportunity and create a sale order through 'Convert to Sale' wizard .
--
- I create an opportunity
--
- !record {model: crm.lead, id: crm_lead_opportunity0}:
- country_id: base.be
- name: Opportunity-1
- planned_revenue: 50000.0
- probability: 70.0
- partner_address_id: base.res_partner_address_7
- partner_id: base.res_partner_4
- planned_revenue: 0.0
- probability: 0.0
- section_id: crm.section_sales_department
- type: opportunity
- categ_id: crm.categ_oppor1
--
- Then I click on the 'Convert to Sale' wizard
--
- I place a sale order for product keyboard having quantity 50
-
!record {model: crm.make.sale, id: crm_make_sale_0}:
partner_id: base.res_partner_4
- shop_id: sale.shop
-
- Then I click on the 'Ok' button of wizard
+ I convert opportunity into "Quotation".
-
!python {model: crm.make.sale}: |
- crm_obj = self.pool.get('crm.lead')
- crm = crm_obj.browse(cr, uid, ref("crm_lead_opportunity0"))
- self.makeOrder(cr, uid, [ref("crm_make_sale_0")], {"lang": "en_US", "tz": False,
- "active_model": "crm.lead", "section_id": "crm.section_sales_department", "default_type": "opportunity",
- "search_default_user_id": 1, "search_default_current": 1, "active_ids": [crm.id],
+ crm_lead = self.pool.get('crm.lead')
+ crm = crm_lead.browse(cr, uid, ref("crm.crm_case_construstazunits0"))
+ self.makeOrder(cr, uid, [ref("crm_make_sale_0")], {"active_ids": [crm.id],
"active_id": crm.id})
-
- I verify that a sale order has been generated from an opportunity
+ I check that reference number of "Quotation" in opportunity.
-
!python {model: crm.lead}: |
- crm = self.browse(cr, uid, ref("crm_lead_opportunity0"))
- assert (crm.ref),("sale order has not been created")
+ crm = self.browse(cr, uid, ref("crm.crm_case_construstazunits0"))
+ assert crm.ref, "Quotation has not been created."
diff --git a/addons/sale_mrp/__openerp__.py b/addons/sale_mrp/__openerp__.py
index 4900834f7b0..e3372690e6d 100644
--- a/addons/sale_mrp/__openerp__.py
+++ b/addons/sale_mrp/__openerp__.py
@@ -23,7 +23,7 @@
{
'name': 'Sales and MRP Management',
'version': '1.0',
- 'category': 'Hidden/Link',
+ 'category': 'Hidden/Links',
'complexity': "easy",
'description': """
This module provides facility to the user to install mrp and sales modulesat a time.
diff --git a/addons/share/static/src/css/share.css b/addons/share/static/src/css/share.css
index 4bd4f1d67e5..8b137891791 100644
--- a/addons/share/static/src/css/share.css
+++ b/addons/share/static/src/css/share.css
@@ -1,14 +1 @@
-.openerp li.oe-share {
- background: url(../img/share.png) no-repeat 0 60%;
- padding-left: 20px;
-}
-
-.openerp a.oe-share {
- background: url(../img/share.png) no-repeat center center;
- display: block;
- float: left;
- width: 20px;
- height: 20px;
- margin-top: 3px;
-}
diff --git a/addons/share/static/src/js/share.js b/addons/share/static/src/js/share.js
index 45cc2bd20ca..b084e82f7c9 100644
--- a/addons/share/static/src/js/share.js
+++ b/addons/share/static/src/js/share.js
@@ -1,7 +1,8 @@
openerp.share = function(instance) {
-function launch_wizard(self, view) {
+function launch_wizard(self, view, button) {
+ var button = button || 'go_step_1';
var action = view.widget_parent.action;
var Share = new instance.web.DataSet(self, 'share.wizard', view.dataset.get_context());
var domain = new instance.web.CompoundDomain(view.dataset.domain);
@@ -16,9 +17,10 @@ function launch_wizard(self, view) {
name: action.name,
domain: result.domain,
action_id: action.id,
+ view_type: view.fields_view.type,
}, function(result) {
var share_id = result.result;
- var step1 = Share.call('go_step_1', [[share_id],], function(result) {
+ var step1 = Share.call(button, [[share_id],], function(result) {
var action = result;
self.do_action(action);
});
@@ -26,37 +28,15 @@ function launch_wizard(self, view) {
});
}
-var _has_share = null;
-function if_has_share(yes, no) {
- if (!_has_share) {
- _has_share = $.Deferred(function() {
- var self = this;
- instance.connection.on_session_invalid.add_last(function() { _has_share = null; });
- var func = new instance.web.Model(null, "share.wizard").get_func("has_share");
- func(instance.connection.uid).pipe(function(res) {
- if(res) {
- self.resolve();
- } else {
- self.reject();
- }
- });
- });
- }
- _has_share.done(yes).fail(no);
-}
-
-
instance.web.Sidebar = instance.web.Sidebar.extend({
add_default_sections: function() {
this._super();
var self = this;
- if_has_share(function() {
- self.add_items('other', [{
- label: 'Share',
- callback: self.on_sidebar_click_share,
- classname: 'oe-share',
- }]);
- });
+ self.add_items('other', [{
+ label: 'Share',
+ callback: self.on_sidebar_click_share,
+ classname: 'oe-share',
+ }]);
},
on_sidebar_click_share: function(item) {
var view = this.widget_parent
@@ -67,13 +47,14 @@ instance.web.Sidebar = instance.web.Sidebar.extend({
instance.web.ViewManagerAction.include({
start: function() {
var self = this;
- if_has_share(function() {
- self.$element.find('a.oe-share').click(self.on_click_share);
- }, function() {
- self.$element.find('a.oe-share').remove();
- });
+ self.$element.find('a.oe-share_link').click(self.on_click_share_link);
+ self.$element.find('a.oe-share').click(self.on_click_share);
return this._super.apply(this, arguments);
},
+ on_click_share_link: function(e) {
+ e.preventDefault();
+ launch_wizard(this, this.views[this.active_view].controller,'go_step_1_link');
+ },
on_click_share: function(e) {
e.preventDefault();
launch_wizard(this, this.views[this.active_view].controller);
diff --git a/addons/share/static/src/xml/share.xml b/addons/share/static/src/xml/share.xml
index 9a1363846a0..d8d3ab506fe 100644
--- a/addons/share/static/src/xml/share.xml
+++ b/addons/share/static/src/xml/share.xml
@@ -5,9 +5,8 @@
-
-
-
+
+
diff --git a/addons/share/wizard/share_wizard.py b/addons/share/wizard/share_wizard.py
index d6fa426f7ab..e115cab2552 100644
--- a/addons/share/wizard/share_wizard.py
+++ b/addons/share/wizard/share_wizard.py
@@ -22,12 +22,16 @@ import logging
import random
import time
from urllib import quote_plus
+import uuid
+
+import simplejson
import tools
from osv import osv, fields
from osv import expression
from tools.translate import _
from tools.safe_eval import safe_eval
+import openerp
FULL_ACCESS = ('perm_read', 'perm_write', 'perm_create', 'perm_unlink')
READ_WRITE_ACCESS = ('perm_read', 'perm_write')
@@ -78,7 +82,7 @@ class share_wizard(osv.osv_memory):
def _user_type_selection(self, cr, uid, context=None):
"""Selection values may be easily overridden/extended via inheritance"""
- return [('emails','List of emails')]
+ return [('embedded', 'Direct link or embed code'), ('emails','Emails'), ]
"""Override of create() to auto-compute the action name"""
def create(self, cr, uid, values, context=None):
@@ -101,11 +105,53 @@ class share_wizard(osv.osv_memory):
result[this.id] = this.share_url_template() % data
return result
+ def _generate_embedded_code(self, wizard, options=None):
+ cr = wizard._cr
+ uid = wizard._uid
+ context = wizard._context
+ if options is None:
+ options = {}
+
+ js_options = {}
+ title = options['title'] if 'title' in options else wizard.embed_option_title
+ search = (options['search'] if 'search' in options else wizard.embed_option_search) if wizard.access_mode != 'readonly' else False
+
+ if not title:
+ js_options['display_title'] = False
+ if search:
+ js_options['search_view'] = True
+
+ js_options_str = (', ' + simplejson.dumps(js_options)) if js_options else ''
+
+ base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url', default=None, context=context)
+ user = wizard.result_line_ids[0]
+
+ return """
+
+ """ % {
+ 'init': simplejson.dumps(openerp.conf.server_wide_modules),
+ 'server': simplejson.dumps(base_url),
+ 'dbname': simplejson.dumps(cr.dbname),
+ 'login': simplejson.dumps(user.login),
+ 'password': simplejson.dumps(user.password),
+ 'action': user.user_id.action_id.id,
+ 'options': js_options_str,
+ }
+
+ def _embed_code(self, cr, uid, ids, _fn, _args, context=None):
+ result = dict.fromkeys(ids, '')
+ for this in self.browse(cr, uid, ids, context=context):
+ result[this.id] = self._generate_embedded_code(this)
+ return result
+
_columns = {
'action_id': fields.many2one('ir.actions.act_window', 'Action to share', required=True,
help="The action that opens the screen containing the data you wish to share."),
+ 'view_type': fields.char('Current View Type', size=32, required=True),
'domain': fields.char('Domain', size=256, help="Optional domain for further data filtering"),
- 'user_type': fields.selection(lambda s, *a, **k: s._user_type_selection(*a, **k),'Users to share with', required=True,
+ 'user_type': fields.selection(lambda s, *a, **k: s._user_type_selection(*a, **k),'Sharing method', required=True,
help="Select the type of user(s) you would like to share data with."),
'new_users': fields.text("Emails"),
'access_mode': fields.selection([('readonly','Can view'),('readwrite','Can edit')],'Access Mode', required=True,
@@ -115,18 +161,39 @@ class share_wizard(osv.osv_memory):
help='Main access page for users that are granted shared access'),
'name': fields.char('Share Title', size=64, required=True, help="Title for the share (displayed to users as menu and shortcut name)"),
'message': fields.text("Personal Message", help="An optional personal message, to be included in the e-mail notification."),
+
+ 'embed_code': fields.function(_embed_code, type='text'),
+ 'embed_option_title': fields.boolean("Display title"),
+ 'embed_option_search': fields.boolean('Display search view'),
}
_defaults = {
- 'user_type' : 'emails',
+ 'view_type': 'tree',
+ 'user_type' : 'embedded',
'domain': lambda self, cr, uid, context, *a: context.get('domain', '[]'),
'action_id': lambda self, cr, uid, context, *a: context.get('action_id'),
'access_mode': 'readonly',
+ 'embed_option_title': True,
+ 'embed_option_search': True,
}
+ def go_step_1_link(self, cr, uid, ids, context=None):
+ dummy, step1_form_view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'share', 'share_step1_form_link')
+ return {
+ 'name': _('Link or embed your documents'),
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'res_model': 'share.wizard',
+ 'view_id': False,
+ 'res_id': ids[0],
+ 'views': [(step1_form_view_id, 'form')],
+ 'type': 'ir.actions.act_window',
+ 'target': 'new'
+ }
+
def go_step_1(self, cr, uid, ids, context=None):
dummy, step1_form_view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'share', 'share_step1_form')
return {
- 'name': _('Grant instant access to your documents'),
+ 'name': _('Share your documents by email'),
'view_type': 'form',
'view_mode': 'form',
'res_model': 'share.wizard',
@@ -155,33 +222,52 @@ class share_wizard(osv.osv_memory):
current_user = user_obj.browse(cr, UID_ROOT, uid, context=context)
created_ids = []
existing_ids = []
- for new_user in (wizard_data.new_users or '').split('\n'):
- # Ignore blank lines
- new_user = new_user.strip()
- if not new_user: continue
- # Ignore the user if it already exists.
- existing = user_obj.search(cr, UID_ROOT, [('login', '=', new_user)])
- existing_ids.extend(existing)
- if existing:
- new_line = { 'user_id': existing[0],
- 'newly_created': False}
+ if wizard_data.user_type == 'emails':
+ for new_user in (wizard_data.new_users or '').split('\n'):
+ # Ignore blank lines
+ new_user = new_user.strip()
+ if not new_user: continue
+ # Ignore the user if it already exists.
+ existing = user_obj.search(cr, UID_ROOT, [('login', '=', new_user)])
+ existing_ids.extend(existing)
+ if existing:
+ new_line = { 'user_id': existing[0],
+ 'newly_created': False}
+ wizard_data.write({'result_line_ids': [(0,0,new_line)]})
+ continue
+ new_pass = generate_random_pass()
+ user_id = user_obj.create(cr, UID_ROOT, {
+ 'login': new_user,
+ 'password': new_pass,
+ 'name': new_user,
+ 'user_email': new_user,
+ 'groups_id': [(6,0,[group_id])],
+ 'share': True,
+ 'company_id': current_user.company_id.id
+ })
+ new_line = { 'user_id': user_id,
+ 'password': new_pass,
+ 'newly_created': True}
wizard_data.write({'result_line_ids': [(0,0,new_line)]})
- continue
+ created_ids.append(user_id)
+
+ elif wizard_data.user_type == 'embedded':
+ new_login = 'embedded-%s' % (uuid.uuid4().hex,)
new_pass = generate_random_pass()
user_id = user_obj.create(cr, UID_ROOT, {
- 'login': new_user,
- 'password': new_pass,
- 'name': new_user,
- 'user_email': new_user,
- 'groups_id': [(6,0,[group_id])],
- 'share': True,
- 'company_id': current_user.company_id.id
+ 'login': new_login,
+ 'password': new_pass,
+ 'name': new_login,
+ 'groups_id': [(6,0,[group_id])],
+ 'share': True,
+ 'company_id': current_user.company_id.id
})
new_line = { 'user_id': user_id,
'password': new_pass,
'newly_created': True}
wizard_data.write({'result_line_ids': [(0,0,new_line)]})
created_ids.append(user_id)
+
return created_ids, existing_ids
def _create_shortcut(self, cr, uid, values, context=None):
@@ -241,21 +327,33 @@ class share_wizard(osv.osv_memory):
def _shared_action_def(self, cr, uid, wizard_data, context=None):
copied_action = wizard_data.action_id
+
+ if wizard_data.access_mode == 'readonly':
+ view_mode = wizard_data.view_type
+ view_id = copied_action.view_id.id if copied_action.view_id.type == wizard_data.view_type else False
+ else:
+ view_mode = copied_action.view_mode
+ view_id = copied_action.view_id.id
+
+
action_def = {
'name': wizard_data.name,
'domain': copied_action.domain,
'context': self._cleanup_action_context(wizard_data.action_id.context, uid),
'res_model': copied_action.res_model,
- 'view_mode': copied_action.view_mode,
+ 'view_mode': view_mode,
'view_type': copied_action.view_type,
- 'search_view_id': copied_action.search_view_id.id,
- 'view_id': copied_action.view_id.id,
+ 'search_view_id': copied_action.search_view_id.id if wizard_data.access_mode != 'readonly' else False,
+ 'view_id': view_id,
+ 'auto_search': True,
}
if copied_action.view_ids:
action_def['view_ids'] = [(0,0,{'sequence': x.sequence,
'view_mode': x.view_mode,
'view_id': x.view_id.id })
- for x in copied_action.view_ids]
+ for x in copied_action.view_ids
+ if (wizard_data.access_mode != 'readonly' or x.view_mode == wizard_data.view_type)
+ ]
return action_def
def _setup_action_and_shortcut(self, cr, uid, wizard_data, user_ids, make_home, context=None):
@@ -660,6 +758,8 @@ class share_wizard(osv.osv_memory):
msg_ids = []
for result_line in wizard_data.result_line_ids:
email_to = result_line.user_id.user_email
+ if not email_to:
+ continue
subject = wizard_data.name
body = _("Hello,")
body += "\n\n"
@@ -685,7 +785,6 @@ class share_wizard(osv.osv_memory):
body += "--\n"
body += _("OpenERP is a powerful and user-friendly suite of Business Applications (CRM, Sales, HR, etc.)\n"
"It is open source and can be found on http://www.openerp.com.")
-
msg_ids.append(mail_message.schedule_with_attach(cr, uid,
user.user_email,
[email_to],
@@ -697,6 +796,12 @@ class share_wizard(osv.osv_memory):
mail_message.send(cr, uid, msg_ids, context=context)
self._logger.info('%d share notification(s) sent.', len(msg_ids))
+ def onchange_embed_options(self, cr, uid, ids, opt_title, opt_search, context=None):
+ wizard = self.browse(cr, uid, ids[0], context)
+ options = dict(title=opt_title, search=opt_search)
+ return {'value': {'embed_code': self._generate_embedded_code(wizard, options)}}
+
+share_wizard()
class share_result_line(osv.osv_memory):
_name = 'share.wizard.result.line'
diff --git a/addons/share/wizard/share_wizard_view.xml b/addons/share/wizard/share_wizard_view.xml
index 128b32b07da..330363879cf 100644
--- a/addons/share/wizard/share_wizard_view.xml
+++ b/addons/share/wizard/share_wizard_view.xml
@@ -23,25 +23,43 @@
+
+ share.step1.form.link
+ share.wizard
+ form
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
share.step1.formshare.wizardform
-
-
-
-
-
-
+
+
+
-
+
-
+
@@ -61,15 +79,30 @@
form
-
-
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -98,6 +131,17 @@
- 'domain' (string expression for full domain to apply as sent to server,
with dynamic data like 'uid' replaced by actual value (i.e. after eval)!)
-->
+
+ Share Wizard
+ ir.actions.act_window
+ share.wizard
+ form
+ form
+
+ new
+ {'default_user_type':'embedded'}
+
+
Share Wizardir.actions.act_window