diff --git a/addons/board_manufacturing/board_manufacturing_view.xml b/addons/board_manufacturing/board_manufacturing_view.xml
index 17b4bc486bc..191f1818612 100644
--- a/addons/board_manufacturing/board_manufacturing_view.xml
+++ b/addons/board_manufacturing/board_manufacturing_view.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/addons/board_warehouse/board_warehouse_view.xml b/addons/board_warehouse/board_warehouse_view.xml
index cdc93d9a274..af797401935 100644
--- a/addons/board_warehouse/board_warehouse_view.xml
+++ b/addons/board_warehouse/board_warehouse_view.xml
@@ -23,7 +23,7 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+ Production Management
+ -->
mrp.production.tree
@@ -765,259 +783,22 @@
-
-
-
-
- mrp.procurement.tree
- mrp.procurement
- tree
-
-
-
-
-
-
-
-
-
-
-
+
+
+ mrp.procurement.form.inherit
+ mrp.procurement
+
+ form
+
+
+
+
+
-
- mrp.procurement.form
- mrp.procurement
- form
-
-
-
-
-
- mrp.procurement.select
- mrp.procurement
- search
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Procurement Orders
- ir.actions.act_window
- mrp.procurement
- form
-
-
-
-
-
-
- Procurements
- ir.actions.act_window
- mrp.procurement
- form
- tree,form
-
- []
- {}
-
-
-
- Procurement Exceptions
- ir.actions.act_window
- mrp.procurement
- form
- tree,form
- [('state','=','exception')]
-
-
-
-
- Procurement Exceptions to Fix
- ir.actions.act_window
- mrp.procurement
- form
- tree,form
- [('state','=','exception'), ('message', '<>', '')]
-
-
-
-
- Temporary Procurement Exceptions
- ir.actions.act_window
- mrp.procurement
- form
- tree,form
- [('state','=','exception'), ('message', '=', '')]
-
-
-
-
- stock.warehouse.orderpoint.tree
- stock.warehouse.orderpoint
- tree
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- stock.warehouse.orderpoint.search
- stock.warehouse.orderpoint
- search
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- stock.warehouse.orderpoint.form
- stock.warehouse.orderpoint
- form
-
-
-
-
-
-
- Minimum Stock Rules
- stock.warehouse.orderpoint
- ir.actions.act_window
- form
-
-
-
-
-
-
-
-
-
button_cancel
-
+
-
-
- mrp.procurement.basic
- mrp.procurement
- True
-
-
-
-
- True
- draft
-
-
-
- cancel
- function
- action_cancel()
- True
-
-
-
- confirm
- function
- action_confirm()
-
-
-
- confirm_wait
- function
- write({'state':'exception'})
-
-
-
- confirm_mts
-
-
-
- confirm_mto
-
-
-
- make_to_stock
- function
- action_move_assigned()
-
-
+
produce
subflow
action_produce_assign_product()
-
+
produce_check
-
+
produce_service
function
action_produce_assign_service()
-
-
- buy
- subflow
-
- action_po_assign()
-
-
-
- ready
- function
- action_ready()
-
-
-
- wait_done
- function
- write({'state':'waiting'})
-
-
-
-
- True
- done
- function
- action_done()
-
-
-
-
-
- button_confirm
-
-
-
-
- button_wait_done
- True
-
-
-
-
- check_move_done()
- stock.move
- [move_id.id]
-
-
-
-
-
- button_check
- test_cancel()
-
-
-
-
- button_check
- not test_cancel()
-
-
-
-
- procure_method=='make_to_order'
-
-
-
-
- procure_method=='make_to_stock'
-
-
-
-
- button_cancel
-
-
-
-
- button_cancel
-
-
-
-
- button_restart
-
-
-
-
- button_cancel
-
-
-
-
- button_restart
-
-
-
-
- button_cancel
-
-
-
-
- check_make_to_stock()
-
+
-
+
check_produce()
-
-
-
- check_product()
-
not check_product()
-
-
-
- check_buy()
-
-
-
-
- True
-
-
-
-
-
-
- subflow.cancel
-
+
-
+
subflow.cancel
-
-
-
- subflow.cancel
-
-
-
-
-
- subflow.done
-
-
+
-
+
-
-
-
- subflow.delivery_done
+
+
+
+
+ check_product()
-
-
-
- action_check_finnished()
+
+
+
+
+ subflow.cancel
-
-
-
- check_move_cancel()
+
+
+
+
+ subflow.done
+
+
diff --git a/addons/mrp/process/procurement_process.xml b/addons/mrp/process/procurement_process.xml
index 17d72a520f2..08d66570b1f 100644
--- a/addons/mrp/process/procurement_process.xml
+++ b/addons/mrp/process/procurement_process.xml
@@ -1,43 +1,16 @@
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -46,31 +19,31 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
@@ -79,10 +52,22 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -91,10 +76,22 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -102,14 +99,14 @@
-
+
-
+
diff --git a/addons/mrp/security/ir.model.access.csv b/addons/mrp/security/ir.model.access.csv
index 48f27679435..d5e00b9cbda 100644
--- a/addons/mrp/security/ir.model.access.csv
+++ b/addons/mrp/security/ir.model.access.csv
@@ -1,7 +1,5 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
"access_mrp_workcenter","mrp.workcenter","model_mrp_workcenter","mrp.group_mrp_user",1,0,0,0
-"access_mrp_property_group","mrp.property.group","model_mrp_property_group","mrp.group_mrp_user",1,0,0,0
-"access_mrp_property","mrp.property","model_mrp_property","mrp.group_mrp_user",1,0,0,0
"access_mrp_routing","mrp.routing","model_mrp_routing","mrp.group_mrp_user",1,0,0,0
"access_mrp_routing_workcenter","mrp.routing.workcenter","model_mrp_routing_workcenter","mrp.group_mrp_user",1,0,0,0
"access_mrp_bom","mrp.bom","model_mrp_bom","mrp.group_mrp_user",1,0,0,0
@@ -10,11 +8,7 @@
"access_mrp_production_workcenter_line","mrp.production.workcenter.line","model_mrp_production_workcenter_line","mrp.group_mrp_user",1,1,1,1
"access_mrp_production_product_line","mrp.production.product.line","model_mrp_production_product_line","mrp.group_mrp_user",1,1,1,1
"access_mrp_procurement","mrp.procurement","model_mrp_procurement","mrp.group_mrp_user",1,1,1,1
-"access_stock_warehouse_orderpoint","stock.warehouse.orderpoint","model_stock_warehouse_orderpoint","mrp.group_mrp_user",1,0,0,0
-"access_stock_warehouse_orderpoint_manager","stock.warehouse.orderpoint.manager","model_stock_warehouse_orderpoint","mrp.group_mrp_manager",1,1,1,1
"access_mrp_workcenter_manager","mrp.workcenter.manager","model_mrp_workcenter","mrp.group_mrp_user",1,1,1,1
-"access_mrp_property_group_manager","mrp.property.group.manager","model_mrp_property_group","mrp.group_mrp_user",1,1,1,1
-"access_mrp_property_manager","mrp.property.manager","model_mrp_property","mrp.group_mrp_user",1,1,1,1
"access_mrp_routing_manager","mrp.routing.manager","model_mrp_routing","mrp.group_mrp_manager",1,1,1,1
"access_mrp_routing_workcenter_manager","mrp.routing.workcenter.manager","model_mrp_routing_workcenter","mrp.group_mrp_manager",1,1,1,1
"access_mrp_bom_manager","mrp.bom.manager","model_mrp_bom","mrp.group_mrp_manager",1,1,1,1
@@ -32,10 +26,7 @@
"access_mrp_production_stock_worker","mrp.production stock_worker","model_mrp_production","stock.group_stock_user",1,0,0,0
"access_mrp_installer","mrp.installer","model_mrp_installer","mrp.group_mrp_user",1,0,0,0
"access_mrp_product_produce","mrp.product.produce","model_mrp_product_produce","mrp.group_mrp_user",1,0,0,0
-"access_mrp_make_procurement","make.procurement","model_make_procurement","mrp.group_mrp_user",1,0,0,0
"access_mrp_change_production_qty","change.production.qty","model_change_production_qty","mrp.group_mrp_user",1,0,0,0
-"access_mrp_procurement_compute_all","mrp.procurement.compute.all","model_mrp_procurement_compute_all","mrp.group_mrp_user",1,0,0,0
-"access_mrp_procurement_orderpoint_compute","mrp.procurement.orderpoint.compute","model_mrp_procurement_orderpoint_compute","mrp.group_mrp_user",1,0,0,0
"access_mrp_production_order","mrp.production.order","model_mrp_production_order","mrp.group_mrp_user",1,0,0,0
"access_report_workcenter_load","report.workcenter.load","model_report_workcenter_load","mrp.group_mrp_manager",1,0,0,0
"access_report_mrp_inout","report.mrp.inout","model_report_mrp_inout","mrp.group_mrp_manager",1,0,0,0
diff --git a/addons/mrp/security/mrp_security.xml b/addons/mrp/security/mrp_security.xml
index 955bdad2fdd..4d47e374e02 100644
--- a/addons/mrp/security/mrp_security.xml
+++ b/addons/mrp/security/mrp_security.xml
@@ -16,20 +16,6 @@
-
- mrp_procurement multi-company
-
-
- ['|',('company_id','child_of',[user.company_id.id]),('company_id','=',False)]
-
-
-
- stock_warehouse.orderpoint multi-company
-
-
- ['|',('company_id','child_of',[user.company_id.id]),('company_id','=',False)]
-
-
mrp_production multi-company
diff --git a/addons/mrp/stock.py b/addons/mrp/stock.py
index 4a35d6003cf..dcb7d4573c1 100644
--- a/addons/mrp/stock.py
+++ b/addons/mrp/stock.py
@@ -27,74 +27,6 @@ import ir
import netsvc
import time
-
-class stock_warehouse_orderpoint(osv.osv):
- """
- Defines Minimum stock rules.
- """
- _name = "stock.warehouse.orderpoint"
- _description = "Orderpoint minimum rule"
-
- _columns = {
- 'name': fields.char('Name', size=32, required=True),
- 'active': fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the orderpoint without removing it."),
- 'logic': fields.selection([('max','Order to Max'),('price','Best price (not yet active!)')], 'Reordering Mode', required=True),
- 'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse', required=True),
- 'location_id': fields.many2one('stock.location', 'Location', required=True),
- 'product_id': fields.many2one('product.product', 'Product', required=True, ondelete='cascade', domain=[('type','=','product')]),
- 'product_uom': fields.many2one('product.uom', 'Product UOM', required=True ),
- 'product_min_qty': fields.float('Min Quantity', required=True,
- help="When the virtual stock goes belong the Min Quantity, Open ERP generates "\
- "a procurement to bring the virtual stock to the Max Quantity."),
- 'product_max_qty': fields.float('Max Quantity', required=True,
- help="When the virtual stock goes belong the Min Quantity, Open ERP generates "\
- "a procurement to bring the virtual stock to the Max Quantity."),
- 'qty_multiple': fields.integer('Qty Multiple', required=True,
- help="The procurement quantity will by rounded up to this multiple."),
- 'procurement_id': fields.many2one('mrp.procurement', 'Latest procurement'),
- 'company_id': fields.many2one('res.company','Company',required=True),
- }
- _defaults = {
- 'active': lambda *a: 1,
- 'logic': lambda *a: 'max',
- 'qty_multiple': lambda *a: 1,
- 'name': lambda x,y,z,c: x.pool.get('ir.sequence').get(y,z,'mrp.warehouse.orderpoint') or '',
- 'product_uom': lambda sel, cr, uid, context: context.get('product_uom', False),
- 'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'stock.warehouse.orderpoint', context=c)
- }
-
- def onchange_warehouse_id(self, cr, uid, ids, warehouse_id, context={}):
- """ Finds location id for changed warehouse.
- @param warehouse_id: Changed id of warehouse.
- @return: Dictionary of values.
- """
- if warehouse_id:
- w = self.pool.get('stock.warehouse').browse(cr, uid, warehouse_id, context)
- v = {'location_id': w.lot_stock_id.id}
- return {'value': v}
- return {}
-
- def onchange_product_id(self, cr, uid, ids, product_id, context={}):
- """ Finds UoM for changed product.
- @param product_id: Changed id of product.
- @return: Dictionary of values.
- """
- if product_id:
- prod = self.pool.get('product.product').browse(cr,uid,product_id)
- v = {'product_uom': prod.uom_id.id}
- return {'value': v}
- return {}
-
- def copy(self, cr, uid, id, default=None,context={}):
- if not default:
- default = {}
- default.update({
- 'name': self.pool.get('ir.sequence').get(cr, uid, 'mrp.warehouse.orderpoint') or '',
- })
- return super(stock_warehouse_orderpoint, self).copy(cr, uid, id, default, context)
-
-stock_warehouse_orderpoint()
-
class StockMove(osv.osv):
_inherit = 'stock.move'
diff --git a/addons/mrp/test/mrp_phantom_bom.yml b/addons/mrp/test/mrp_phantom_bom.yml
new file mode 100644
index 00000000000..df4ade1cb6e
--- /dev/null
+++ b/addons/mrp/test/mrp_phantom_bom.yml
@@ -0,0 +1,234 @@
+-
+ 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 the products required to produce some orange juices: Oranges, Sugar and Water.
+-
+ !record {model: product.uom, id: product_uom_litre0}:
+ category_id: product.product_uom_categ_kgm
+ factor: 1.0
+ name: Litre
+ rounding: 0.01
+-
+ !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
+-
+ !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
+ qty: 1.0
+ supply_method: buy
+ type: product
+ uom_id: product.product_uom_kgm
+ uom_po_id: product.product_uom_kgm
+-
+ !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
+ qty: 2.0
+ supply_method: buy
+ type: product
+ uom_id: product.product_uom_kgm
+ uom_po_id: product.product_uom_kgm
+-
+ !record {model: product.product, id: product_product_water0}:
+ categ_id: product.cat1
+ name: Water
+ procure_method: make_to_stock
+ supply_method: buy
+ type: consu
+ uom_id: product_uom_litre0
+ uom_po_id: product_uom_litre0
+-
+ 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
+-
+ !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 products orange and sugar
+-
+ !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
+-
+ !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: '2010-04-16 15:53:36'
+ location_dest_id: stock.stock_location_output
+ location_src_id: stock.stock_location_stock
+ name: MO/00002
+ 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
+ company_id: base.main_company
+ date_planned: '2010-04-16 15:53:36'
+ location_dest_id: stock.stock_location_output
+ location_src_id: stock.stock_location_stock
+ name: MO/00002
+ 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: mrp.procurement}: |
+ from tools.translate import _
+ proc_ids = self.search(cr, uid, [('origin','=',':MO/00002')])
+ assert proc_ids, _('No Procurements!')
+-
+ The scheduler runs.
+-
+ !function {model: mrp.procurement, name: run_scheduler}:
+ - model: mrp.procurement
+ search: "[('origin','=',':MO/00002')]"
+-
+ 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}: |
+ from tools.translate import _
+ pick_ids = self.search(cr, uid, [('origin','=',':MO/00002'),('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}: |
+ from tools.translate import _
+ import netsvc
+ purch_ids = self.search(cr, uid, [('origin','in',['SCHEDULER','OP/00002','OP/00003'])])
+ 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 get the approval from both the suppliers. So I approve my purchase orders.
+-
+ !python {model: purchase.order}: |
+ from tools.translate import _
+ import netsvc
+ purch_ids = self.search(cr, uid, [('origin','in',['SCHEDULER','OP/00002','OP/00003']),('state','=','confirmed')])
+ assert purch_ids, _('No Confirmed Purchase Orders found!')
+ wf_service = netsvc.LocalService("workflow")
+ for p_id in purch_ids:
+ wf_service.trg_validate(uid, 'purchase.order', p_id, 'purchase_approve', cr)
+-
+ I see two incoming pickings for Orange and Sugar.
+-
+ !python {model: stock.picking}: |
+ from tools.translate import _
+ pick_ids = self.search(cr, uid, [('origin','in',['PO00001:SCHEDULER','PO00002:SCHEDULER','PO00003:OP/00002','PO00004:OP/00003']),('type','=','in')])
+ assert pick_ids, _('No Incoming Shipments found!')
+-
+ I receive both the products. My incoming pickings are done.
+-
+ !record {model: stock.partial.picking, id: stock_partial_picking0}:
+ date: '2010-04-30 16:53:36'
+ partner_id: base.res_partner_asus
+ address_id: base.res_partner_address_tang
+-
+ !python {model: stock.partial.picking}: |
+ pick_obj = self.pool.get('stock.picking')
+ picking_ids = pick_obj.search(cr, uid, [('origin','in',['PO00001:SCHEDULER','PO00002:SCHEDULER','PO00003:OP/00002','PO00004:OP/00003']),('type','=','in')])
+ self.do_partial(cr, uid, [1],context={'active_ids': picking_ids})
+
\ No newline at end of file
diff --git a/addons/mrp/test/mrp_production_order.yml b/addons/mrp/test/mrp_production_order.yml
new file mode 100644
index 00000000000..023a9f22f31
--- /dev/null
+++ b/addons/mrp/test/mrp_production_order.yml
@@ -0,0 +1,139 @@
+-
+ 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_mo0}:
+ bom_id: mrp.mrp_bom_9
+ routing_id: mrp.mrp_routing_0
+ company_id: base.main_company
+ date_planned: '2010-05-06 14:55:52'
+ location_dest_id: stock.stock_location_stock
+ location_src_id: stock.stock_location_stock
+ name: MO/00004
+ product_id: product.product_product_pc1
+ product_qty: 5.0
+ product_uom: product.product_uom_unit
+ product_uos_qty: 0.0
+-
+ Creating a mrp.production.workcenter.line record
+-
+ !record {model: mrp.production.workcenter.line, id: mrp_production_workcenter_line_assemblyline0}:
+ cycle: 5.0
+ hour: 10.0
+ name: Assembly Line 1
+ production_id: mrp_production_mo0
+ sequence: 0.0
+ workcenter_id: mrp.mrp_workcenter_0
+-
+ Creating a mrp.production.product.line record
+-
+ !record {model: mrp.production.product.line, id: mrp_production_product_line_regularprocessorconfig0}:
+ name: Regular processor config
+ product_id: product.product_product_cpu_gen
+ product_qty: 5.0
+ product_uom: product.product_uom_unit
+ product_uos_qty: 0.0
+ production_id: mrp_production_mo0
+-
+ Creating a mrp.production.product.line record
+-
+ !record {model: mrp.production.product.line, id: mrp_production_product_line_hddseagategb0}:
+ name: HDD Seagate 7200.8 80GB
+ product_id: product.product_product_hdd1
+ product_qty: 5.0
+ product_uom: product.product_uom_unit
+ product_uos_qty: 0.0
+ production_id: mrp_production_mo0
+-
+ Creating a mrp.production.product.line record
+-
+ !record {model: mrp.production.product.line, id: mrp_production_product_line_atxmidsizetower0}:
+ name: ATX Mid-size Tower
+ product_id: product.product_product_tow1
+ product_qty: 5.0
+ product_uom: product.product_uom_unit
+ product_uos_qty: 0.0
+ production_id: mrp_production_mo0
+-
+ Creating a mrp.production.product.line record
+-
+ !record {model: mrp.production.product.line, id: mrp_production_product_line_mouse0}:
+ name: Mouse
+ product_id: product.product_product_25
+ product_qty: 5.0
+ product_uom: product.product_uom_unit
+ product_uos_qty: 0.0
+ production_id: mrp_production_mo0
+-
+ Creating a mrp.production.product.line record
+-
+ !record {model: mrp.production.product.line, id: mrp_production_product_line_keyboard0}:
+ name: Keyboard
+ product_id: product.product_product_24
+ product_qty: 5.0
+ product_uom: product.product_uom_unit
+ product_uos_qty: 0.0
+ production_id: mrp_production_mo0
+-
+ I confirm the order.
+-
+ !workflow {model: mrp.production, action: button_confirm, ref: mrp_production_mo0}
+-
+ I am checking Procurement orders.
+-
+ !python {model: mrp.procurement}: |
+ from tools.translate import _
+ proc_ids = self.search(cr, uid, [('origin','=',':MO/00004')])
+ assert proc_ids, _('No Procurements!')
+-
+ The scheduler runs.
+-
+ !function {model: mrp.procurement, name: run_scheduler}:
+ - model: mrp.procurement
+ search: "[('origin','=',':MO/00004')]"
+-
+ I am checking Internal picking.
+-
+ !python {model: stock.picking}: |
+ from tools.translate import _
+ pick_ids = self.search(cr, uid, [('origin','=',':MO/00004'),('type','=','internal')])
+ assert pick_ids, _('No Internal Pickings!')
+-
+ I see that there is a manufacturing order for the subproduct of PC1 with ready state.
+-
+ !python {model: mrp.production}: |
+ from tools.translate import _
+ order_ids = self.search(cr, uid, [('origin','=',':MO/00004'),('state','=','ready')])
+ assert order_ids, _('No manufacturing order!')
+-
+ I start producing that product first. So I marked it as started.
+-
+ !record {model: mrp.product.produce, id: mrp_product_produce0}:
+ product_qty: 5.00
+ mode: 'consume_produce'
+-
+ !python {model: mrp.product.produce}: |
+ prod_obj = self.pool.get('mrp.production')
+ prod_ids = prod_obj.search(cr, uid, [('origin','=',':MO/00004')])
+ self.do_produce(cr, uid, [1], 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, [('origin','=',':MO/00004'),('state','=','done')])
+ assert prod_ids, _('Manufacturing order is yet not done!')
+-
+ I start producing the product PC1.
+-
+ !workflow {model: mrp.production, action: button_produce, ref: mrp_production_mo0}
+-
+ !python {model: mrp.product.produce}: |
+ from tools.translate import _
+ prod_obj = self.pool.get('mrp.production')
+ prod_ids = prod_obj.search(cr, uid, [('product_id.default_code','=','PC1')])
+ self.do_produce(cr, uid, [1], context={'active_ids': prod_ids})
diff --git a/addons/mrp/wizard/__init__.py b/addons/mrp/wizard/__init__.py
index 045d7f1bd71..aa4408e543e 100644
--- a/addons/mrp/wizard/__init__.py
+++ b/addons/mrp/wizard/__init__.py
@@ -20,14 +20,10 @@
##############################################################################
import mrp_product_produce
-import orderpoint_procurement
-import mrp_procurement
-import schedulers_all
import mrp_price
import mrp_workcenter_load
#import mrp_track_prod
import change_production_qty
-import make_procurement_product
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/mrp/wizard/mrp_track_prod.py b/addons/mrp/wizard/mrp_track_prod.py
index 11e1ec32ec6..43929b47dc7 100644
--- a/addons/mrp/wizard/mrp_track_prod.py
+++ b/addons/mrp/wizard/mrp_track_prod.py
@@ -56,33 +56,35 @@ class mrp_track_move(osv.osv_memory):
"""
res = super(mrp_track_move, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar,submenu=False)
record_id = context and context.get('active_id', False) or False
- if record_id:
- prod_obj = self.pool.get('mrp.production')
- prod = prod_obj.browse(cr, uid, record_id)
- try:
- if prod.state != 'done':
- res['arch'] = '''
- '''
- else:
- arch_lst = ['')
- res['arch'] = '\n'.join(arch_lst)
- except Exception,e:
- return res
+ active_model = context.get('active_model')
+
+ if not record_id or (active_model and active_model != 'mrp.production'):
+ return res
+
+ prod_obj = self.pool.get('mrp.production')
+ prod = prod_obj.browse(cr, uid, record_id)
+ if prod.state != 'done':
+ res['arch'] = '''
+ '''
+ else:
+ arch_lst = ['')
+ res['arch'] = '\n'.join(arch_lst)
+
return res
def track_lines(self, cr, uid, ids, context):
diff --git a/addons/mrp_procurement/__init__.py b/addons/mrp_procurement/__init__.py
new file mode 100644
index 00000000000..6cb8ad4027b
--- /dev/null
+++ b/addons/mrp_procurement/__init__.py
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL ().
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+import mrp_procurement
+import wizard
+import schedulers
+import company
\ No newline at end of file
diff --git a/addons/mrp_procurement/__openerp__.py b/addons/mrp_procurement/__openerp__.py
new file mode 100644
index 00000000000..82c611c6c78
--- /dev/null
+++ b/addons/mrp_procurement/__openerp__.py
@@ -0,0 +1,52 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL ().
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+
+{
+ "name" : "Procurements",
+ "version" : "1.0",
+ "author" : "Tiny",
+ "website" : "http://www.openerp.com",
+ "category" : "Generic Modules/Production",
+ "depends" : ["base","process", "product", "stock"],
+ "description": """
+ This is the module for computing Procurements.
+ """,
+ 'init_xml': [],
+ 'update_xml': [
+ 'security/ir.model.access.csv',
+ 'security/mrp_procurement_security.xml',
+ 'mrp_procurement_data.xml',
+ 'wizard/make_procurement_view.xml',
+ 'wizard/mrp_procurement_view.xml',
+ 'wizard/orderpoint_procurement_view.xml',
+ 'mrp_procurement_view.xml',
+ 'wizard/schedulers_all_view.xml',
+ 'mrp_procurement_workflow.xml',
+ 'process/procurement_process.xml',
+ "company_view.xml",
+ ],
+# 'demo_xml': [],
+ 'installable': True,
+ 'active': False,
+ 'certificate': '',
+}
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/mrp_procurement/company.py b/addons/mrp_procurement/company.py
new file mode 100644
index 00000000000..ce39ca9a684
--- /dev/null
+++ b/addons/mrp_procurement/company.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL ().
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+from osv import osv,fields
+
+class company(osv.osv):
+ _inherit = 'res.company'
+ _columns = {
+ 'schedule_range': fields.float('Scheduler Range', required=True,
+ help="This is the time frame analysed by the scheduler when "\
+ "computing procurements. All procurements that are not between "\
+ "today and today+range are skipped for futur computation."),
+ }
+ _defaults = {
+ 'schedule_range': lambda *a: 80.0,
+ }
+company()
+
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/mrp_procurement/company_view.xml b/addons/mrp_procurement/company_view.xml
new file mode 100644
index 00000000000..543e36fe02f
--- /dev/null
+++ b/addons/mrp_procurement/company_view.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+ res.company.mrp.config
+ res.company
+ form
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/addons/mrp_procurement/mrp_procurement.py b/addons/mrp_procurement/mrp_procurement.py
new file mode 100644
index 00000000000..bd5b223779f
--- /dev/null
+++ b/addons/mrp_procurement/mrp_procurement.py
@@ -0,0 +1,527 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL ().
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+from mx import DateTime
+from osv import osv, fields
+from tools.translate import _
+import netsvc
+import time
+
+
+class mrp_property_group(osv.osv):
+ """
+ Group of mrp properties.
+ """
+ _name = 'mrp.property.group'
+ _description = 'Property Group'
+ _columns = {
+ 'name': fields.char('Property Group', size=64, required=True),
+ 'description': fields.text('Description'),
+ }
+mrp_property_group()
+
+class mrp_property(osv.osv):
+ """
+ Properties of mrp.
+ """
+ _name = 'mrp.property'
+ _description = 'Property'
+ _columns = {
+ 'name': fields.char('Name', size=64, required=True),
+ 'composition': fields.selection([('min','min'),('max','max'),('plus','plus')], 'Properties composition', required=True, help="Not used in computations, for information purpose only."),
+ 'group_id': fields.many2one('mrp.property.group', 'Property Group', required=True),
+ 'description': fields.text('Description'),
+ }
+ _defaults = {
+ 'composition': lambda *a: 'min',
+ }
+mrp_property()
+
+# ------------------------------------------------------------------
+# Procurement
+# ------------------------------------------------------------------
+#
+# Produce, Buy or Find products and place a move
+# then wizard for picking lists & move
+#
+class mrp_procurement(osv.osv):
+ """
+ Procurement Orders
+ """
+ _name = "mrp.procurement"
+ _description = "Procurement"
+ _order = 'priority,date_planned'
+
+ _columns = {
+ 'name': fields.char('Reason', size=64, required=True, help='Procurement name.'),
+ 'origin': fields.char('Source Document', size=64,
+ help="Reference of the document that created this Procurement.\n"
+ "This is automatically completed by Open ERP."),
+ 'priority': fields.selection([('0','Not urgent'),('1','Normal'),('2','Urgent'),('3','Very Urgent')], 'Priority', required=True),
+ 'date_planned': fields.datetime('Scheduled date', required=True),
+ 'date_close': fields.datetime('Date Closed'),
+ 'product_id': fields.many2one('product.product', 'Product', required=True, states={'draft':[('readonly',False)]}, readonly=True),
+ 'product_qty': fields.float('Quantity', required=True, states={'draft':[('readonly',False)]}, readonly=True),
+ 'product_uom': fields.many2one('product.uom', 'Product UoM', required=True, states={'draft':[('readonly',False)]}, readonly=True),
+ 'product_uos_qty': fields.float('UoS Quantity', states={'draft':[('readonly',False)]}, readonly=True),
+ 'product_uos': fields.many2one('product.uom', 'Product UoS', states={'draft':[('readonly',False)]}, readonly=True),
+ 'move_id': fields.many2one('stock.move', 'Reservation', ondelete='set null'),
+ 'close_move': fields.boolean('Close Move at end', required=True),
+ 'location_id': fields.many2one('stock.location', 'Location', required=True, states={'draft':[('readonly',False)]}, readonly=True),
+ 'procure_method': fields.selection([('make_to_stock','from stock'),('make_to_order','on order')], 'Procurement Method', states={'draft':[('readonly',False)], 'confirmed':[('readonly',False)]},
+ readonly=True, required=True, help="If you encode manually a Procurement, you probably want to use" \
+ " a make to order method."),
+
+ 'note': fields.text('Note'),
+
+ 'property_ids': fields.many2many('mrp.property', 'mrp_procurement_property_rel', 'procurement_id','property_id', 'Properties'),
+
+ 'message': fields.char('Latest error', size=64, help="Exception occurred while computing procurement orders."),
+ 'state': fields.selection([
+ ('draft','Draft'),
+ ('confirmed','Confirmed'),
+ ('exception','Exception'),
+ ('running','Running'),
+ ('cancel','Cancel'),
+ ('ready','Ready'),
+ ('done','Done'),
+ ('waiting','Waiting')], 'State', required=True,
+ help='When a procurement is created the state is set to \'Draft\'.\n If the procurement is confirmed, the state is set to \'Confirmed\'.\
+ \nAfter confirming the state is set to \'Running\'.\n If any exception arises in the order then the state is set to \'Exception\'.\n Once the exception is removed the state becomes \'Ready\'.\n It is in \'Waiting\'. state when the procurement is waiting for another one to finish.'),
+ 'note': fields.text('Note'),
+ 'company_id': fields.many2one('res.company','Company',required=True),
+ }
+ _defaults = {
+ 'state': lambda *a: 'draft',
+ 'priority': lambda *a: '1',
+ 'date_planned': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
+ 'close_move': lambda *a: 0,
+ 'procure_method': lambda *a: 'make_to_order',
+ 'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'mrp.procurement', context=c)
+ }
+
+ def unlink(self, cr, uid, ids, context=None):
+ procurements = self.read(cr, uid, ids, ['state'])
+ unlink_ids = []
+ for s in procurements:
+ if s['state'] in ['draft','cancel']:
+ unlink_ids.append(s['id'])
+ else:
+ raise osv.except_osv(_('Invalid action !'), _('Cannot delete Procurement Order(s) which are in %s State!' % s['state']))
+ return osv.osv.unlink(self, cr, uid, unlink_ids, context=context)
+
+ def onchange_product_id(self, cr, uid, ids, product_id, context={}):
+ """ Finds UoM and UoS of changed product.
+ @param product_id: Changed id of product.
+ @return: Dictionary of values.
+ """
+ if product_id:
+ w = self.pool.get('product.product').browse(cr, uid, product_id, context)
+ v = {
+ 'product_uom': w.uom_id.id,
+ 'product_uos': w.uos_id and w.uos_id.id or w.uom_id.id
+ }
+ return {'value': v}
+ return {}
+
+ def check_product(self, cr, uid, ids):
+ """ Checks product type.
+ @return: True or False
+ """
+ for procurement in self.browse(cr, uid, ids):
+ if procurement.product_id.type in ('product', 'consu'):
+ return True
+ return False
+
+ def check_move_cancel(self, cr, uid, ids, context={}):
+ """ Checks if move is cancelled or not.
+ @return: True or False.
+ """
+ res = True
+ ok = False
+ for procurement in self.browse(cr, uid, ids, context):
+ if procurement.move_id:
+ ok = True
+ if not procurement.move_id.state == 'cancel':
+ res = False
+ return res and ok
+
+ def check_move_done(self, cr, uid, ids, context={}):
+ """ Checks if move is done or not.
+ @return: True or False.
+ """
+ res = True
+ for proc in self.browse(cr, uid, ids, context):
+ if proc.move_id:
+ if not proc.move_id.state == 'done':
+ res = False
+ return res
+
+ #
+ # This method may be overrided by objects that override mrp.procurment
+ # for computing their own purpose
+ #
+ def _quantity_compute_get(self, cr, uid, proc, context={}):
+ """ Finds sold quantity of product.
+ @param proc: Current procurement.
+ @return: Quantity or False.
+ """
+ if proc.product_id.type == 'product':
+ if proc.move_id.product_uos:
+ return proc.move_id.product_uos_qty
+ return False
+
+ def _uom_compute_get(self, cr, uid, proc, context={}):
+ """ Finds UoS if product is Stockable Product.
+ @param proc: Current procurement.
+ @return: UoS or False.
+ """
+ if proc.product_id.type == 'product':
+ if proc.move_id.product_uos:
+ return proc.move_id.product_uos.id
+ return False
+
+ #
+ # Return the quantity of product shipped/produced/served, wich may be
+ # different from the planned quantity
+ #
+ def quantity_get(self, cr, uid, id, context={}):
+ """ Finds quantity of product used in procurement.
+ @return: Quantity of product.
+ """
+ proc = self.browse(cr, uid, id, context)
+ result = self._quantity_compute_get(cr, uid, proc, context)
+ if not result:
+ result = proc.product_qty
+ return result
+
+ def uom_get(self, cr, uid, id, context=None):
+ """ Finds UoM of product used in procurement.
+ @return: UoM of product.
+ """
+ proc = self.browse(cr, uid, id, context)
+ result = self._uom_compute_get(cr, uid, proc, context)
+ if not result:
+ result = proc.product_uom.id
+ return result
+
+ def check_waiting(self, cr, uid, ids, context=[]):
+ """ Checks state of move.
+ @return: True or False
+ """
+ for procurement in self.browse(cr, uid, ids, context=context):
+ if procurement.move_id and procurement.move_id.state == 'auto':
+ return True
+ return False
+
+ def check_produce_service(self, cr, uid, procurement, context=[]):
+ return True
+
+ def check_produce_product(self, cr, uid, procurement, context=[]):
+ """ Finds BoM of a product if not found writes exception message.
+ @param procurement: Current procurement.
+ @return: True or False.
+ """
+ return True
+
+ def check_make_to_stock(self, cr, uid, ids, context={}):
+ """ Checks product type.
+ @return: True or False
+ """
+ ok = True
+ for procurement in self.browse(cr, uid, ids, context=context):
+ if procurement.product_id.type == 'service':
+ ok = ok and self._check_make_to_stock_service(cr, uid, procurement, context)
+ else:
+ ok = ok and self._check_make_to_stock_product(cr, uid, procurement, context)
+ return ok
+
+ def check_produce(self, cr, uid, ids, context={}):
+ """ Checks product type.
+ @return: True or Product Id.
+ """
+ res = True
+ user = self.pool.get('res.users').browse(cr, uid, uid)
+ for procurement in self.browse(cr, uid, ids):
+ if procurement.product_id.product_tmpl_id.supply_method <> 'produce':
+ if procurement.product_id.seller_ids:
+ partner = procurement.product_id.seller_ids[0].name
+ if user.company_id and user.company_id.partner_id:
+ if partner.id == user.company_id.partner_id.id:
+ return True
+ return False
+ if procurement.product_id.product_tmpl_id.type=='service':
+ res = res and self.check_produce_service(cr, uid, procurement, context)
+ else:
+ res = res and self.check_produce_product(cr, uid, procurement, context)
+ if not res:
+ return False
+ return res
+
+ def check_buy(self, cr, uid, ids):
+ """ Checks product type.
+ @return: True or Product Id.
+ """
+ user = self.pool.get('res.users').browse(cr, uid, uid)
+ partner_obj = self.pool.get('res.partner')
+ for procurement in self.browse(cr, uid, ids):
+ if procurement.product_id.product_tmpl_id.supply_method <> 'buy':
+ return False
+ if not procurement.product_id.seller_ids:
+ cr.execute('update mrp_procurement set message=%s where id=%s', (_('No supplier defined for this product !'), procurement.id))
+ return False
+ partner = procurement.product_id.seller_ids[0].name
+ if user.company_id and user.company_id.partner_id:
+ if partner.id == user.company_id.partner_id.id:
+ return False
+ address_id = partner_obj.address_get(cr, uid, [partner.id], ['delivery'])['delivery']
+ if not address_id:
+ cr.execute('update mrp_procurement set message=%s where id=%s', (_('No address defined for the supplier'), procurement.id))
+ return False
+ return True
+
+ def test_cancel(self, cr, uid, ids):
+ """ Tests whether state of move is cancelled or not.
+ @return: True or False
+ """
+ for record in self.browse(cr, uid, ids):
+ if record.move_id and record.move_id.state == 'cancel':
+ return True
+ return False
+
+ def action_confirm(self, cr, uid, ids, context={}):
+ """ Confirms procurement and writes exception message if any.
+ @return: True
+ """
+ move_obj = self.pool.get('stock.move')
+ for procurement in self.browse(cr, uid, ids):
+ if procurement.product_qty <= 0.00:
+ raise osv.except_osv(_('Data Insufficient !'), _('Please check the Quantity of Procurement Order(s), it should not be less than 1!'))
+ if procurement.product_id.type in ('product', 'consu'):
+ if not procurement.move_id:
+ source = procurement.location_id.id
+ if procurement.procure_method == 'make_to_order':
+ source = procurement.product_id.product_tmpl_id.property_stock_procurement.id
+ id = move_obj.create(cr, uid, {
+ 'name': 'PROC:' + procurement.name,
+ 'location_id': source,
+ 'location_dest_id': procurement.location_id.id,
+ 'product_id': procurement.product_id.id,
+ 'product_qty': procurement.product_qty,
+ 'product_uom': procurement.product_uom.id,
+ 'date_planned': procurement.date_planned,
+ 'state': 'confirmed',
+ 'company_id': procurement.company_id.id,
+ })
+ self.write(cr, uid, [procurement.id], {'move_id': id, 'close_move': 1})
+ else:
+ # TODO: check this
+ if procurement.procure_method == 'make_to_stock' and procurement.move_id.state in ('waiting',):
+ id = move_obj.write(cr, uid, [procurement.move_id.id], {'state':'confirmed'})
+ self.write(cr, uid, ids, {'state': 'confirmed', 'message': ''})
+ return True
+
+ def action_move_assigned(self, cr, uid, ids, context={}):
+ """ Changes procurement state to Running and writes message.
+ @return: True
+ """
+ self.write(cr, uid, ids, {'state': 'running', 'message': _('from stock: products assigned.')})
+ return True
+
+ def _check_make_to_stock_service(self, cr, uid, procurement, context={}):
+ return True
+
+ def _check_make_to_stock_product(self, cr, uid, procurement, context={}):
+ """ Checks procurement move state.
+ @param procurement: Current procurement.
+ @return: True or move id.
+ """
+ ok = True
+ if procurement.move_id:
+ id = procurement.move_id.id
+ if not (procurement.move_id.state in ('done','assigned','cancel')):
+ ok = ok and self.pool.get('stock.move').action_assign(cr, uid, [id])
+ cr.execute('select count(id) from stock_warehouse_orderpoint where product_id=%s', (procurement.product_id.id,))
+ if not cr.fetchone()[0]:
+ cr.execute('update mrp_procurement set message=%s where id=%s', (_('from stock and no minimum orderpoint rule defined'), procurement.id))
+ return ok
+
+ def action_produce_assign_service(self, cr, uid, ids, context={}):
+ """ Changes procurement state to Running.
+ @return: True
+ """
+ for procurement in self.browse(cr, uid, ids):
+ self.write(cr, uid, [procurement.id], {'state': 'running'})
+ return True
+
+ def action_produce_assign_product(self, cr, uid, ids, context={}):
+ """ This is action which call from workflow to assign production order to procurements
+ @return: True
+ """
+ return 0
+
+
+ def action_po_assign(self, cr, uid, ids, context={}):
+ """ This is action which call from workflow to assign purchase order to procurements
+ @return: True
+ """
+ return 0
+
+ def action_cancel(self, cr, uid, ids):
+ """ Cancels procurement and writes move state to Assigned.
+ @return: True
+ """
+ todo = []
+ todo2 = []
+ move_obj = self.pool.get('stock.move')
+ for proc in self.browse(cr, uid, ids):
+ if proc.close_move:
+ if proc.move_id.state not in ('done', 'cancel'):
+ todo2.append(proc.move_id.id)
+ else:
+ if proc.move_id and proc.move_id.state == 'waiting':
+ todo.append(proc.move_id.id)
+ if len(todo2):
+ move_obj.action_cancel(cr, uid, todo2)
+ if len(todo):
+ move_obj.write(cr, uid, todo, {'state': 'assigned'})
+ self.write(cr, uid, ids, {'state': 'cancel'})
+ wf_service = netsvc.LocalService("workflow")
+ for id in ids:
+ wf_service.trg_trigger(uid, 'mrp.procurement', id, cr)
+ return True
+
+ def action_check_finnished(self, cr, uid, ids):
+ return self.check_move_done(cr, uid, ids)
+
+ def action_check(self, cr, uid, ids):
+ """ Checks procurement move state whether assigned or done.
+ @return: True
+ """
+ ok = False
+ for procurement in self.browse(cr, uid, ids):
+ if procurement.move_id.state == 'assigned' or procurement.move_id.state == 'done':
+ self.action_done(cr, uid, [procurement.id])
+ ok = True
+ return ok
+
+ def action_ready(self, cr, uid, ids):
+ """ Changes procurement state to Ready.
+ @return: True
+ """
+ res = self.write(cr, uid, ids, {'state': 'ready'})
+ return res
+
+ def action_done(self, cr, uid, ids):
+ """ Changes procurement state to Done and writes Closed date.
+ @return: True
+ """
+ move_obj = self.pool.get('stock.move')
+ for procurement in self.browse(cr, uid, ids):
+ if procurement.move_id:
+ if procurement.close_move and (procurement.move_id.state <> 'done'):
+ move_obj.action_done(cr, uid, [procurement.move_id.id])
+ res = self.write(cr, uid, ids, {'state': 'done', 'date_close': time.strftime('%Y-%m-%d')})
+ wf_service = netsvc.LocalService("workflow")
+ for id in ids:
+ wf_service.trg_trigger(uid, 'mrp.procurement', id, cr)
+ return res
+
+ def run_scheduler(self, cr, uid, automatic=False, use_new_cursor=False, context=None):
+ ''' Runs through scheduler.
+ @param use_new_cursor: False or the dbname
+ '''
+ if not context:
+ context={}
+ self._procure_confirm(cr, uid, use_new_cursor=use_new_cursor, context=context)
+ self._procure_orderpoint_confirm(cr, uid, automatic=automatic,\
+ use_new_cursor=use_new_cursor, context=context)
+
+mrp_procurement()
+
+
+class stock_warehouse_orderpoint(osv.osv):
+ """
+ Defines Minimum stock rules.
+ """
+ _name = "stock.warehouse.orderpoint"
+ _description = "Orderpoint minimum rule"
+
+ _columns = {
+ 'name': fields.char('Name', size=32, required=True),
+ 'active': fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the orderpoint without removing it."),
+ 'logic': fields.selection([('max','Order to Max'),('price','Best price (not yet active!)')], 'Reordering Mode', required=True),
+ 'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse', required=True),
+ 'location_id': fields.many2one('stock.location', 'Location', required=True),
+ 'product_id': fields.many2one('product.product', 'Product', required=True, ondelete='cascade', domain=[('type','=','product')]),
+ 'product_uom': fields.many2one('product.uom', 'Product UOM', required=True ),
+ 'product_min_qty': fields.float('Min Quantity', required=True,
+ help="When the virtual stock goes belong the Min Quantity, Open ERP generates "\
+ "a procurement to bring the virtual stock to the Max Quantity."),
+ 'product_max_qty': fields.float('Max Quantity', required=True,
+ help="When the virtual stock goes belong the Min Quantity, Open ERP generates "\
+ "a procurement to bring the virtual stock to the Max Quantity."),
+ 'qty_multiple': fields.integer('Qty Multiple', required=True,
+ help="The procurement quantity will by rounded up to this multiple."),
+ 'procurement_id': fields.many2one('mrp.procurement', 'Latest procurement'),
+ 'company_id': fields.many2one('res.company','Company',required=True),
+ }
+ _defaults = {
+ 'active': lambda *a: 1,
+ 'logic': lambda *a: 'max',
+ 'qty_multiple': lambda *a: 1,
+ 'name': lambda x,y,z,c: x.pool.get('ir.sequence').get(y,z,'mrp.warehouse.orderpoint') or '',
+ 'product_uom': lambda sel, cr, uid, context: context.get('product_uom', False),
+ 'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'stock.warehouse.orderpoint', context=c)
+ }
+
+ def onchange_warehouse_id(self, cr, uid, ids, warehouse_id, context={}):
+ """ Finds location id for changed warehouse.
+ @param warehouse_id: Changed id of warehouse.
+ @return: Dictionary of values.
+ """
+ if warehouse_id:
+ w = self.pool.get('stock.warehouse').browse(cr, uid, warehouse_id, context)
+ v = {'location_id': w.lot_stock_id.id}
+ return {'value': v}
+ return {}
+
+ def onchange_product_id(self, cr, uid, ids, product_id, context={}):
+ """ Finds UoM for changed product.
+ @param product_id: Changed id of product.
+ @return: Dictionary of values.
+ """
+ if product_id:
+ prod = self.pool.get('product.product').browse(cr,uid,product_id)
+ v = {'product_uom': prod.uom_id.id}
+ return {'value': v}
+ return {}
+
+ def copy(self, cr, uid, id, default=None,context={}):
+ if not default:
+ default = {}
+ default.update({
+ 'name': self.pool.get('ir.sequence').get(cr, uid, 'mrp.warehouse.orderpoint') or '',
+ })
+ return super(stock_warehouse_orderpoint, self).copy(cr, uid, id, default, context)
+
+stock_warehouse_orderpoint()
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/mrp_procurement/mrp_procurement_data.xml b/addons/mrp_procurement/mrp_procurement_data.xml
new file mode 100644
index 00000000000..256472bd2fd
--- /dev/null
+++ b/addons/mrp_procurement/mrp_procurement_data.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+ Run mrp scheduler
+
+
+ 1
+ days
+ -1
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/addons/mrp_procurement/mrp_procurement_view.xml b/addons/mrp_procurement/mrp_procurement_view.xml
new file mode 100644
index 00000000000..84b47ee516d
--- /dev/null
+++ b/addons/mrp_procurement/mrp_procurement_view.xml
@@ -0,0 +1,251 @@
+
+
+
+
+
+
+ mrp.procurement.tree
+ mrp.procurement
+ tree
+
+
+
+
+
+
+
+
+
+
+
+
+
+ mrp.procurement.form
+ mrp.procurement
+ form
+
+
+
+
+
+ mrp.procurement.select
+ mrp.procurement
+ search
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Procurement Orders
+ ir.actions.act_window
+ mrp.procurement
+ form
+
+
+
+
+
+ Procurements
+ ir.actions.act_window
+ mrp.procurement
+ form
+ tree,form
+
+ []
+ {}
+
+
+
+ Procurement Exceptions
+ ir.actions.act_window
+ mrp.procurement
+ form
+ tree,form
+ [('state','=','exception')]
+
+
+
+ Procurement Exceptions to Fix
+ ir.actions.act_window
+ mrp.procurement
+ form
+ tree,form
+ [('state','=','exception'), ('message', '<>', '')]
+
+
+
+
+ Temporary Procurement Exceptions
+ ir.actions.act_window
+ mrp.procurement
+ form
+ tree,form
+ [('state','=','exception'), ('message', '=', '')]
+
+
+
+
+ stock.warehouse.orderpoint.tree
+ stock.warehouse.orderpoint
+ tree
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ stock.warehouse.orderpoint.search
+ stock.warehouse.orderpoint
+ search
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ stock.warehouse.orderpoint.form
+ stock.warehouse.orderpoint
+ form
+
+
+
+
+
+
+ Minimum Stock Rules
+ stock.warehouse.orderpoint
+ ir.actions.act_window
+ form
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/addons/mrp_procurement/mrp_procurement_workflow.xml b/addons/mrp_procurement/mrp_procurement_workflow.xml
new file mode 100644
index 00000000000..46c4a10fffc
--- /dev/null
+++ b/addons/mrp_procurement/mrp_procurement_workflow.xml
@@ -0,0 +1,196 @@
+
+
+
+
+
+
+
+ mrp.procurement.basic
+ mrp.procurement
+ True
+
+
+
+
+ True
+ draft
+
+
+
+ cancel
+ function
+ action_cancel()
+ True
+
+
+
+ confirm
+ function
+ action_confirm()
+
+
+
+ confirm_wait
+ function
+ write({'state':'exception'})
+
+
+
+ confirm_mts
+
+
+
+ confirm_mto
+
+
+
+ make_to_stock
+ function
+ action_move_assigned()
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ready
+ function
+ action_ready()
+
+
+
+ wait_done
+ function
+ write({'state':'waiting'})
+
+
+
+
+ True
+ done
+ function
+ action_done()
+
+
+
+
+
+ button_confirm
+
+
+
+
+ button_wait_done
+ True
+
+
+
+
+ check_move_done()
+ stock.move
+ [move_id.id]
+
+
+
+
+
+ button_check
+ test_cancel()
+
+
+
+
+ button_check
+ not test_cancel()
+
+
+
+
+ procure_method=='make_to_order'
+
+
+
+
+ procure_method=='make_to_stock'
+
+
+
+
+ button_cancel
+
+
+
+
+ button_cancel
+
+
+
+
+ button_restart
+
+
+
+
+ button_cancel
+
+
+
+
+ button_restart
+
+
+
+
+ button_cancel
+
+
+
+
+ check_make_to_stock()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ action_check_finnished()
+
+
+
+
+ check_move_cancel()
+
+
+
+
diff --git a/addons/mrp_procurement/process/procurement_process.xml b/addons/mrp_procurement/process/procurement_process.xml
new file mode 100644
index 00000000000..21f953c6a6f
--- /dev/null
+++ b/addons/mrp_procurement/process/procurement_process.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/mrp/schedulers.py b/addons/mrp_procurement/schedulers.py
similarity index 99%
rename from addons/mrp/schedulers.py
rename to addons/mrp_procurement/schedulers.py
index cc482d95c52..7a89723e5ca 100644
--- a/addons/mrp/schedulers.py
+++ b/addons/mrp_procurement/schedulers.py
@@ -238,4 +238,5 @@ class mrp_procurement(osv.osv):
cr.close()
return {}
mrp_procurement()
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/mrp/scripts/scheduler.py b/addons/mrp_procurement/scripts/scheduler.py
similarity index 100%
rename from addons/mrp/scripts/scheduler.py
rename to addons/mrp_procurement/scripts/scheduler.py
diff --git a/addons/mrp_procurement/security/ir.model.access.csv b/addons/mrp_procurement/security/ir.model.access.csv
new file mode 100644
index 00000000000..ce022a730b0
--- /dev/null
+++ b/addons/mrp_procurement/security/ir.model.access.csv
@@ -0,0 +1,9 @@
+"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
+"access_mrp_property_group","mrp.property.group","model_mrp_property_group",,1,0,0,0
+"access_mrp_property","mrp.property","model_mrp_property",,1,0,0,0
+"access_mrp_procurement","mrp.procurement","model_mrp_procurement",,1,0,0,0
+"access_stock_warehouse_orderpoint","stock.warehouse.orderpoint","model_stock_warehouse_orderpoint",,1,0,0,0
+"access_mrp_procurement_compute_all","mrp.procurement.compute.all","model_mrp_procurement_compute_all",,1,0,0,0
+"access_mrp_procurement_orderpoint_compute","mrp.procurement.orderpoint.compute","model_mrp_procurement_orderpoint_compute",,1,0,0,0
+"access_mrp_make_procurement","make.procurement","model_make_procurement",,1,0,0,0
+"access_mrp_make_procurement","mrp.procurement.compute","model_mrp_procurement_compute",,1,0,0,0
diff --git a/addons/mrp_procurement/security/mrp_procurement_security.xml b/addons/mrp_procurement/security/mrp_procurement_security.xml
new file mode 100644
index 00000000000..a0f2ef431bf
--- /dev/null
+++ b/addons/mrp_procurement/security/mrp_procurement_security.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+ mrp_procurement multi-company
+
+
+ ['|',('company_id','child_of',[user.company_id.id]),('company_id','=',False)]
+
+
+
+ stock_warehouse.orderpoint multi-company
+
+
+ ['|',('company_id','child_of',[user.company_id.id]),('company_id','=',False)]
+
+
+
+
\ No newline at end of file
diff --git a/addons/mrp_procurement/wizard/__init__.py b/addons/mrp_procurement/wizard/__init__.py
new file mode 100644
index 00000000000..ae70ffbf941
--- /dev/null
+++ b/addons/mrp_procurement/wizard/__init__.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL ().
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+import orderpoint_procurement
+import mrp_procurement
+import schedulers_all
+import make_procurement_product
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/mrp/wizard/make_procurement_product.py b/addons/mrp_procurement/wizard/make_procurement_product.py
similarity index 96%
rename from addons/mrp/wizard/make_procurement_product.py
rename to addons/mrp_procurement/wizard/make_procurement_product.py
index a2dd62327bb..96f00b89eb4 100644
--- a/addons/mrp/wizard/make_procurement_product.py
+++ b/addons/mrp_procurement/wizard/make_procurement_product.py
@@ -83,8 +83,8 @@ class make_procurement(osv.osv_memory):
wf_service.trg_validate(uid, 'mrp.procurement', procure_id, 'button_confirm', cr)
- id2 = data_obj._get_id(cr, uid, 'mrp', 'mrp_procurement_tree_view')
- id3 = data_obj._get_id(cr, uid, 'mrp', 'mrp_procurement_form_view')
+ id2 = data_obj._get_id(cr, uid, 'mrp_procurement', 'mrp_procurement_tree_view')
+ id3 = data_obj._get_id(cr, uid, 'mrp_procurement', 'mrp_procurement_form_view')
if id2:
id2 = data_obj.browse(cr, uid, id2, context=context).res_id
diff --git a/addons/mrp/wizard/make_procurement_view.xml b/addons/mrp_procurement/wizard/make_procurement_view.xml
similarity index 100%
rename from addons/mrp/wizard/make_procurement_view.xml
rename to addons/mrp_procurement/wizard/make_procurement_view.xml
diff --git a/addons/mrp/wizard/mrp_procurement.py b/addons/mrp_procurement/wizard/mrp_procurement.py
similarity index 100%
rename from addons/mrp/wizard/mrp_procurement.py
rename to addons/mrp_procurement/wizard/mrp_procurement.py
diff --git a/addons/mrp/wizard/mrp_procurement_view.xml b/addons/mrp_procurement/wizard/mrp_procurement_view.xml
similarity index 100%
rename from addons/mrp/wizard/mrp_procurement_view.xml
rename to addons/mrp_procurement/wizard/mrp_procurement_view.xml
diff --git a/addons/mrp/wizard/orderpoint_procurement.py b/addons/mrp_procurement/wizard/orderpoint_procurement.py
similarity index 100%
rename from addons/mrp/wizard/orderpoint_procurement.py
rename to addons/mrp_procurement/wizard/orderpoint_procurement.py
diff --git a/addons/mrp/wizard/orderpoint_procurement_view.xml b/addons/mrp_procurement/wizard/orderpoint_procurement_view.xml
similarity index 100%
rename from addons/mrp/wizard/orderpoint_procurement_view.xml
rename to addons/mrp_procurement/wizard/orderpoint_procurement_view.xml
diff --git a/addons/mrp/wizard/schedulers_all.py b/addons/mrp_procurement/wizard/schedulers_all.py
similarity index 100%
rename from addons/mrp/wizard/schedulers_all.py
rename to addons/mrp_procurement/wizard/schedulers_all.py
diff --git a/addons/mrp/wizard/schedulers_all_view.xml b/addons/mrp_procurement/wizard/schedulers_all_view.xml
similarity index 84%
rename from addons/mrp/wizard/schedulers_all_view.xml
rename to addons/mrp_procurement/wizard/schedulers_all_view.xml
index b8b465e03e9..33861287278 100644
--- a/addons/mrp/wizard/schedulers_all_view.xml
+++ b/addons/mrp_procurement/wizard/schedulers_all_view.xml
@@ -30,8 +30,5 @@
key2="client_action_multi"
id="action_compute_schedulers"/>
-
-
-
diff --git a/addons/mrp_repair/mrp_repair_view.xml b/addons/mrp_repair/mrp_repair_view.xml
index 9f629ad8a46..667e9763827 100644
--- a/addons/mrp_repair/mrp_repair_view.xml
+++ b/addons/mrp_repair/mrp_repair_view.xml
@@ -115,7 +115,7 @@
-
+
diff --git a/addons/mrp_repair/wizard/cancel_repair.py b/addons/mrp_repair/wizard/cancel_repair.py
index 371b7ba82e3..ecc88ef6aae 100644
--- a/addons/mrp_repair/wizard/cancel_repair.py
+++ b/addons/mrp_repair/wizard/cancel_repair.py
@@ -57,23 +57,24 @@ class repair_cancel(osv.osv_memory):
@param context: A standard dictionary
@return: New arch of view.
"""
- record_id = context and context.get('active_id', False) or False
res = super(repair_cancel, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar,submenu=False)
- if record_id:
- try:
- repair_order = self.pool.get('mrp.repair').browse(cr, uid, record_id)
- if not repair_order.invoiced:
- res['arch'] = """
- """
- except:
- return res
+ record_id = context and context.get('active_id', False) or False
+ active_model = context.get('active_model')
+
+ if not record_id or (active_model and active_model != 'mrp.repair'):
+ return res
+
+ repair_order = self.pool.get('mrp.repair').browse(cr, uid, record_id)
+ if not repair_order.invoiced:
+ res['arch'] = """
+ """
return res
repair_cancel()
diff --git a/addons/point_of_sale/posrule_data.xml b/addons/point_of_sale/posrule_data.xml
index c0fa11bc7f0..5fa46ad43a8 100644
--- a/addons/point_of_sale/posrule_data.xml
+++ b/addons/point_of_sale/posrule_data.xml
@@ -95,7 +95,7 @@
ref('stock.menu_action_picking_tree7'),
ref('stock.menu_action_picking_tree8'),
ref('stock.menu_action_picking_tree9'),
- ref('mrp.menu_mrp_procurement_action3'),
+ ref('mrp_procurement.menu_mrp_procurement_action3'),
ref('point_of_sale.menu_point_root')])]" name="menu_access"/>
@@ -132,7 +132,7 @@
-
+
@@ -206,7 +206,7 @@
-
+
@@ -474,7 +474,7 @@
-
+
@@ -497,7 +497,7 @@
name="Reporting"
parent="stock.menu_stock_root" groups="base.group_user"/>
-
+
diff --git a/addons/point_of_sale/posrule_data2.xml b/addons/point_of_sale/posrule_data2.xml
index 680ae25d7b7..927584e92ce 100644
--- a/addons/point_of_sale/posrule_data2.xml
+++ b/addons/point_of_sale/posrule_data2.xml
@@ -177,7 +177,7 @@
ref('stock.menu_action_picking_tree7'),
ref('stock.menu_action_picking_tree8'),
ref('stock.menu_action_picking_tree9'),
- ref('mrp.menu_mrp_procurement_action3'),
+ ref('mrp_procurement.menu_mrp_procurement_action3'),
ref('point_of_sale.menu_point_root')])]" name="menu_access"/>
@@ -214,7 +214,7 @@
-
+
@@ -557,7 +557,7 @@
-
+
diff --git a/addons/point_of_sale/statement_data.xml b/addons/point_of_sale/statement_data.xml
index 098f4cb2b00..67c94170666 100644
--- a/addons/point_of_sale/statement_data.xml
+++ b/addons/point_of_sale/statement_data.xml
@@ -33,7 +33,7 @@
-
+
diff --git a/addons/product/partner_view.xml b/addons/product/partner_view.xml
index 66e4ba84c37..6b756eb8d7f 100644
--- a/addons/product/partner_view.xml
+++ b/addons/product/partner_view.xml
@@ -9,7 +9,7 @@
-
+
diff --git a/addons/purchase/__init__.py b/addons/purchase/__init__.py
index 41c673c0104..301e32ebca9 100644
--- a/addons/purchase/__init__.py
+++ b/addons/purchase/__init__.py
@@ -25,6 +25,7 @@ import stock
import wizard
import report
import stock
+import company
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/purchase/__openerp__.py b/addons/purchase/__openerp__.py
index 6687b330b2c..909b785fe72 100644
--- a/addons/purchase/__openerp__.py
+++ b/addons/purchase/__openerp__.py
@@ -31,7 +31,7 @@
""",
'author': 'Tiny',
'website': 'http://www.openerp.com',
- 'depends': ['base', 'account', 'stock', 'process'],
+ 'depends': ['base', 'account', 'stock', 'process', 'mrp_procurement'],
'init_xml': [],
'update_xml': [
@@ -39,6 +39,7 @@
'security/ir.model.access.csv',
'purchase_workflow.xml',
'purchase_sequence.xml',
+ 'company_view.xml',
'purchase_data.xml',
'wizard/purchase_order_group_view.xml',
'wizard/purchase_installer.xml',
diff --git a/addons/purchase/company.py b/addons/purchase/company.py
new file mode 100644
index 00000000000..2a01605782c
--- /dev/null
+++ b/addons/purchase/company.py
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL ().
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+from osv import osv,fields
+
+class company(osv.osv):
+ _inherit = 'res.company'
+ _columns = {
+ 'po_lead': fields.float('Purchase Lead Time', required=True,
+ help="This is the leads/security time for each purchase order."),
+ }
+ _defaults = {
+ 'po_lead': lambda *a: 1.0,
+ }
+company()
+
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/purchase/company_view.xml b/addons/purchase/company_view.xml
new file mode 100644
index 00000000000..d7707fe32c7
--- /dev/null
+++ b/addons/purchase/company_view.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+ res.company.mrp.config
+ res.company
+ form
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py
index 2bcc62c06ac..a7d69159873 100644
--- a/addons/purchase/purchase.py
+++ b/addons/purchase/purchase.py
@@ -19,6 +19,7 @@
#
##############################################################################
+from mx import DateTime
from osv import fields
from osv import osv
import time
@@ -692,5 +693,86 @@ class purchase_order_line(osv.osv):
return True
purchase_order_line()
+class mrp_procurement(osv.osv):
+ _inherit = 'mrp.procurement'
+ _columns = {
+ 'purchase_id': fields.many2one('purchase.order', 'Purchase Order'),
+ }
+
+ def action_po_assign(self, cr, uid, ids, context={}):
+ """ This is action which call from workflow to assign purchase order to procurements
+ @return: True
+ """
+ res = self.make_po(cr, uid, ids, context=context)
+ res = res.values()
+ return len(res) and res[0] or 0 #TO CHECK: why workflow is generated error if return not integer value
+
+ def make_po(self, cr, uid, ids, context={}):
+ """ Make purchase order from procurement
+ @return: New created Purchase Orders procurement wise
+ """
+ res = {}
+ company = self.pool.get('res.users').browse(cr, uid, uid, context).company_id
+ partner_obj = self.pool.get('res.partner')
+ uom_obj = self.pool.get('product.uom')
+ pricelist_obj = self.pool.get('product.pricelist')
+ prod_obj = self.pool.get('product.product')
+ acc_pos_obj = self.pool.get('account.fiscal.position')
+ po_obj = self.pool.get('purchase.order')
+ for procurement in self.browse(cr, uid, ids):
+ res_id = procurement.move_id.id
+ partner = procurement.product_id.seller_ids[0].name
+ partner_id = partner.id
+ address_id = partner_obj.address_get(cr, uid, [partner_id], ['delivery'])['delivery']
+ pricelist_id = partner.property_product_pricelist_purchase.id
+
+ uom_id = procurement.product_id.uom_po_id.id
+
+ qty = uom_obj._compute_qty(cr, uid, procurement.product_uom.id, procurement.product_qty, uom_id)
+ if procurement.product_id.seller_ids[0].qty:
+ qty = max(qty,procurement.product_id.seller_ids[0].qty)
+
+ price = pricelist_obj.price_get(cr, uid, [pricelist_id], procurement.product_id.id, qty, False, {'uom': uom_id})[pricelist_id]
+
+ newdate = DateTime.strptime(procurement.date_planned, '%Y-%m-%d %H:%M:%S')
+ newdate = newdate - DateTime.RelativeDateTime(days=company.po_lead)
+ newdate = newdate - procurement.product_id.seller_ids[0].delay
+
+ #Passing partner_id to context for purchase order line integrity of Line name
+ context.update({'lang': partner.lang, 'partner_id': partner_id})
+
+ product = prod_obj.browse(cr, uid, procurement.product_id.id, context=context)
+
+ line = {
+ 'name': product.partner_ref,
+ 'product_qty': qty,
+ 'product_id': procurement.product_id.id,
+ 'product_uom': uom_id,
+ 'price_unit': price,
+ 'date_planned': newdate.strftime('%Y-%m-%d %H:%M:%S'),
+ 'move_dest_id': res_id,
+ 'notes': product.description_purchase,
+ }
+
+ taxes_ids = procurement.product_id.product_tmpl_id.supplier_taxes_id
+ taxes = acc_pos_obj.map_tax(cr, uid, partner.property_account_position, taxes_ids)
+ line.update({
+ 'taxes_id': [(6,0,taxes)]
+ })
+ purchase_id = po_obj.create(cr, uid, {
+ 'origin': procurement.origin,
+ 'partner_id': partner_id,
+ 'partner_address_id': address_id,
+ 'location_id': procurement.location_id.id,
+ 'pricelist_id': pricelist_id,
+ 'order_line': [(0,0,line)],
+ 'company_id': procurement.company_id.id,
+ 'fiscal_position': partner.property_account_position and partner.property_account_position.id or False
+ })
+ res[procurement.id] = purchase_id
+ self.write(cr, uid, [procurement.id], {'state': 'running', 'purchase_id': purchase_id})
+ return res
+mrp_procurement()
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/purchase/purchase_view.xml b/addons/purchase/purchase_view.xml
index c301116db2a..fe6fa0a5e80 100644
--- a/addons/purchase/purchase_view.xml
+++ b/addons/purchase/purchase_view.xml
@@ -322,7 +322,22 @@
-
+
+
+
+
+ mrp.procurement.form.inherit
+ mrp.procurement
+
+ form
+
+
+
+
+
+
diff --git a/addons/purchase/purchase_workflow.xml b/addons/purchase/purchase_workflow.xml
index 26f83d5a554..d7684be1875 100644
--- a/addons/purchase/purchase_workflow.xml
+++ b/addons/purchase/purchase_workflow.xml
@@ -177,6 +177,33 @@
+
+
+
+
+ buy
+ subflow
+
+ action_po_assign()
+
+
+
+
+
+ check_buy()
+
+
+
+
+
+ subflow.delivery_done
+
+
+
+
+
+ subflow.cancel
+
diff --git a/addons/sale/__init__.py b/addons/sale/__init__.py
index ebc12a1089e..71f33623c55 100644
--- a/addons/sale/__init__.py
+++ b/addons/sale/__init__.py
@@ -26,9 +26,10 @@
import sale
import stock
import product
-import mrp
+#import mrp
import wizard
import report
+import company
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/sale/__openerp__.py b/addons/sale/__openerp__.py
index a6ff79b38cd..23e72c60775 100644
--- a/addons/sale/__openerp__.py
+++ b/addons/sale/__openerp__.py
@@ -42,13 +42,14 @@
""",
'author': 'Tiny',
'website': 'http://www.openerp.com',
- 'depends': ['product', 'stock', 'mrp', 'process'],
+ 'depends': ['product', 'stock', 'mrp_procurement', 'process'],
'init_xml': [],
'update_xml': [
'wizard/sale_make_invoice_advance.xml',
'wizard/sale_line_invoice.xml',
'security/sale_security.xml',
'security/ir.model.access.csv',
+ 'company_view.xml',
'sale_workflow.xml',
'sale_sequence.xml',
'sale_data.xml',
@@ -56,7 +57,7 @@
'report/sale_report_view.xml',
'sale_report.xml',
'stock_view.xml',
- 'process/sale_process.xml',
+# 'process/sale_process.xml',
],
'demo_xml': ['sale_demo.xml'],
'installable': True,
diff --git a/addons/sale/company.py b/addons/sale/company.py
new file mode 100644
index 00000000000..401a1a9c1d8
--- /dev/null
+++ b/addons/sale/company.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL ().
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+from osv import osv,fields
+
+class company(osv.osv):
+ _inherit = 'res.company'
+ _columns = {
+ 'security_lead': fields.float('Security Days', required=True,
+ help="This is the days added to what you promise to customers "\
+ "for security purpose"),
+ }
+ _defaults = {
+ 'security_lead': lambda *a: 5.0,
+ }
+company()
+
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/sale/company_view.xml b/addons/sale/company_view.xml
new file mode 100644
index 00000000000..ead9128d6f3
--- /dev/null
+++ b/addons/sale/company_view.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+ res.company.mrp.config
+ res.company
+ form
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/sale/process/sale_process.xml b/addons/sale/process/sale_process.xml
index 5da1a96f8d4..58e4be14d84 100644
--- a/addons/sale/process/sale_process.xml
+++ b/addons/sale/process/sale_process.xml
@@ -35,7 +35,7 @@
-
+
@@ -63,12 +63,12 @@
-
-
+
+
-
+
@@ -202,7 +202,7 @@
-
+
diff --git a/addons/sale/sale_demo.xml b/addons/sale/sale_demo.xml
index 259b5d75e39..d6ab6a7bc0c 100644
--- a/addons/sale/sale_demo.xml
+++ b/addons/sale/sale_demo.xml
@@ -1,6 +1,16 @@
+
+
+
+
+
+
+
+
+
@@ -395,9 +395,9 @@
icon="gtk-cancel" />
-
-
-
+
+
+
diff --git a/addons/sale/security/ir.model.access.csv b/addons/sale/security/ir.model.access.csv
index 44ce9f7d1fa..7af8c1e74a7 100644
--- a/addons/sale/security/ir.model.access.csv
+++ b/addons/sale/security/ir.model.access.csv
@@ -11,10 +11,7 @@
"access_account_analytic_account_salesman","account_analytic_account salesman","analytic.model_account_analytic_account","group_sale_user",1,1,1,1
"access_stock_picking_salesman","stock_picking salesman","stock.model_stock_picking","group_sale_user",1,1,1,1
"access_stock_move_salesman","stock_move salesman","stock.model_stock_move","group_sale_user",1,1,1,0
-"access_mrp_property_salesman","mrp.property salesman","mrp.model_mrp_property","group_sale_user",1,0,0,0
-"access_mrp_procurement_salesman","mrp.procurement salesman","mrp.model_mrp_procurement","group_sale_user",1,1,1,1
-"access_sale_order_mrp_user","sale.order mrp worker","model_sale_order","mrp.group_mrp_user",1,0,0,0
-"access_sale_order_line_mrp_user","sale.order.line mrp worker","model_sale_order_line","mrp.group_mrp_user",1,0,0,0
+"access_mrp_procurement_salesman","mrp.procurement salesman","mrp_procurement.model_mrp_procurement","group_sale_user",1,1,1,1
"access_sale_order_stock_worker","sale.order stock worker","model_sale_order","stock.group_stock_user",1,1,0,0
"access_sale_order_line_stock_worker","sale.order.line stock worker","model_sale_order_line","stock.group_stock_user",1,1,0,0
"access_sale_order_manager","sale.order.manager","model_sale_order","group_sale_manager",1,1,1,1
diff --git a/addons/stock/stock.py b/addons/stock/stock.py
index 111ae31ded4..3795351e03a 100644
--- a/addons/stock/stock.py
+++ b/addons/stock/stock.py
@@ -1214,7 +1214,7 @@ class stock_move(osv.osv):
'origin': fields.related('picking_id','origin',type='char', size=64, relation="stock.picking", string="Origin"),
'move_stock_return_history': fields.many2many('stock.move', 'stock_move_return_history', 'move_id', 'return_move_id', 'Move Return History',readonly=True),
'delivered_id': fields.many2one('stock.delivery', 'Product delivered'),
- 'scraped': fields.boolean('Scraped'),
+ 'scraped': fields.related('location_dest_id','scrap_location',type='boolean',relation='stock.location',string='Scraped'),
}
_constraints = [
(_check_tracking,
diff --git a/addons/stock/stock_data.xml b/addons/stock/stock_data.xml
index 704782eddd8..9b3bf1fb9d5 100644
--- a/addons/stock/stock_data.xml
+++ b/addons/stock/stock_data.xml
@@ -37,6 +37,11 @@
view
terp-mrp
+
+ Scraped
+
+ True
+
Inventory loss
diff --git a/addons/stock/stock_demo.xml b/addons/stock/stock_demo.xml
index de4eccdde55..806722cd24f 100644
--- a/addons/stock/stock_demo.xml
+++ b/addons/stock/stock_demo.xml
@@ -198,13 +198,9 @@
-
-
-
-
diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml
index bb7331f4b58..3c9f1d393ad 100644
--- a/addons/stock/stock_view.xml
+++ b/addons/stock/stock_view.xml
@@ -606,7 +606,7 @@
-
+
@@ -756,7 +756,7 @@
-
+
@@ -934,7 +934,7 @@
-
+
@@ -952,7 +952,7 @@
states="draft,waiting,confirmed,assigned" />
@@ -1109,7 +1109,7 @@
-
+
diff --git a/addons/stock/wizard/stock_move.py b/addons/stock/wizard/stock_move.py
index ea592bf86fa..00b7b616aa5 100644
--- a/addons/stock/wizard/stock_move.py
+++ b/addons/stock/wizard/stock_move.py
@@ -86,7 +86,9 @@ class stock_move_consume(osv.osv_memory):
if 'product_uom' in fields:
res.update({'product_uom': move.product_uom.id})
if 'product_qty' in fields:
- res.update({'product_qty': move.product_qty})
+ res.update({'product_qty': move.product_qty})
+ if 'location_id' in fields:
+ res.update({'location_id': move.location_id.id})
return res
@@ -120,9 +122,41 @@ class stock_move_scrap(osv.osv_memory):
_inherit = "stock.move.consume"
_defaults = {
- 'location_id': lambda *x: False
+ 'location_id': lambda *x: False
}
+ def default_get(self, cr, uid, fields, context=None):
+ """
+ Get default values
+
+ @param self: The object pointer.
+ @param cr: A database cursor
+ @param uid: ID of the user currently logged in
+ @param fields: List of fields for default value
+ @param context: A standard dictionary
+
+ @return: default values of fields
+
+ """
+ res = super(stock_move_consume, self).default_get(cr, uid, fields, context=context)
+ move = self.pool.get('stock.move').browse(cr, uid, context['active_id'], context=context)
+ location_obj = self.pool.get('stock.location')
+ scrpaed_location_ids = location_obj.search(cr, uid, [('scrap_location','=',True)])
+
+ if 'product_id' in fields:
+ res.update({'product_id': move.product_id.id})
+ if 'product_uom' in fields:
+ res.update({'product_uom': move.product_uom.id})
+ if 'product_qty' in fields:
+ res.update({'product_qty': move.product_qty})
+ if 'location_id' in fields:
+ if scrpaed_location_ids:
+ res.update({'location_id': scrpaed_location_ids[0]})
+ else:
+ res.update({'location_id': False})
+
+ return res
+
def move_scrap(self, cr, uid, ids, context={}):
"""
To move scraped products
diff --git a/addons/stock/wizard/stock_move_view.xml b/addons/stock/wizard/stock_move_view.xml
index 481722f8d7f..5f58072f17a 100644
--- a/addons/stock/wizard/stock_move_view.xml
+++ b/addons/stock/wizard/stock_move_view.xml
@@ -40,7 +40,7 @@