diff --git a/addons/mrp/mrp.py b/addons/mrp/mrp.py
index 1f70f55e505..8e550ba4119 100644
--- a/addons/mrp/mrp.py
+++ b/addons/mrp/mrp.py
@@ -130,6 +130,7 @@ class mrp_bom(osv.osv):
"""
_name = 'mrp.bom'
_description = 'Bill of Material'
+ _inherit = ['mail.thread']
def _child_compute(self, cr, uid, ids, name, arg, context=None):
""" Gets child bom.
@@ -358,6 +359,18 @@ class mrp_bom(osv.osv):
default.update({'name': bom_data['name'] + ' ' + _('Copy'), 'bom_id':False})
return super(mrp_bom, self).copy_data(cr, uid, id, default, context=context)
+ def create(self, cr, uid, vals, context=None):
+ obj_id = super(mrp_bom, self).create(cr, uid, vals, context=context)
+ self.create_send_note(cr, uid, [obj_id], context=context)
+ return obj_id
+
+ def create_send_note(self, cr, uid, ids, context=None):
+ prod_obj = self.pool.get('product.product')
+ for obj in self.browse(cr, uid, ids, context=context):
+ for prod in prod_obj.browse(cr, uid, [obj.product_id], context=context):
+ self.message_append_note(cr, uid, [obj.id], body=_("Bill of Material has been created for %s product.") % (prod.id.name_template), context=context)
+ return True
+
mrp_bom()
class mrp_bom_revision(osv.osv):
@@ -393,6 +406,7 @@ class mrp_production(osv.osv):
_name = 'mrp.production'
_description = 'Manufacturing Order'
_date_name = 'date_planned'
+ _inherit = ['ir.needaction', 'mail.thread']
def _production_calc(self, cr, uid, ids, prop, unknow_none, context=None):
""" Calculates total hours and total no. of cycles for a production order.
@@ -497,6 +511,11 @@ class mrp_production(osv.osv):
(_check_qty, 'Order quantity cannot be negative or zero!', ['product_qty']),
]
+ def create(self, cr, uid, vals, context=None):
+ obj_id = super(mrp_production, self).create(cr, uid, vals, context=context)
+ self.create_send_note(cr, uid, [obj_id], context=context)
+ return obj_id
+
def unlink(self, cr, uid, ids, context=None):
for production in self.browse(cr, uid, ids, context=context):
if production.state not in ('draft', 'cancel'):
@@ -629,9 +648,10 @@ class mrp_production(osv.osv):
move_obj.action_cancel(cr, uid, [x.id for x in production.move_created_ids])
move_obj.action_cancel(cr, uid, [x.id for x in production.move_lines])
self.write(cr, uid, ids, {'state': 'cancel'})
+ self.action_cancel_send_note(cr, uid, ids, context)
return True
- def action_ready(self, cr, uid, ids):
+ def action_ready(self, cr, uid, ids, context=None):
""" Changes the production state to Ready and location id of stock move.
@return: True
"""
@@ -643,18 +663,18 @@ class mrp_production(osv.osv):
if production.move_prod_id:
move_obj.write(cr, uid, [production.move_prod_id.id],
{'location_id': production.location_dest_id.id})
-
- message = _("Manufacturing order '%s' is ready to produce.") % ( name,)
- self.log(cr, uid, production_id, message)
+ self.action_ready_send_note(cr, uid, [production_id], context)
return True
- def action_production_end(self, cr, uid, ids):
+ def action_production_end(self, cr, uid, ids, context=None):
""" Changes production state to Finish and writes finished date.
@return: True
"""
for production in self.browse(cr, uid, ids):
self._costs_generate(cr, uid, production)
- return self.write(cr, uid, ids, {'state': 'done', 'date_finished': time.strftime('%Y-%m-%d %H:%M:%S')})
+ write_res = self.write(cr, uid, ids, {'state': 'done', 'date_finished': time.strftime('%Y-%m-%d %H:%M:%S')})
+ self.action_done_send_note(cr, uid, ids, context)
+ return write_res
def test_production_done(self, cr, uid, ids):
""" Tests whether production is done or not.
@@ -698,7 +718,6 @@ class mrp_production(osv.osv):
if (produced_product.scrapped) or (produced_product.product_id.id <> production.product_id.id):
continue
produced_qty += produced_product.product_qty
-
if production_mode in ['consume','consume_produce']:
consumed_data = {}
@@ -819,11 +838,12 @@ class mrp_production(osv.osv):
} )
return amount
- def action_in_production(self, cr, uid, ids):
+ def action_in_production(self, cr, uid, ids, context=None):
""" Changes state to In Production and writes starting date.
@return: True
"""
self.write(cr, uid, ids, {'state': 'in_production', 'date_start': time.strftime('%Y-%m-%d %H:%M:%S')})
+ self.action_in_production_send_note(cr, uid, ids, context)
return True
def test_if_product(self, cr, uid, ids):
@@ -997,11 +1017,7 @@ class mrp_production(osv.osv):
wf_service.trg_validate(uid, 'stock.picking', shipment_id, 'button_confirm', cr)
production.write({'state':'confirmed'}, context=context)
- message = _("Manufacturing order '%s' is scheduled for the %s.") % (
- production.name,
- datetime.strptime(production.date_planned,'%Y-%m-%d %H:%M:%S').strftime('%m/%d/%Y'),
- )
- self.log(cr, uid, production.id, message)
+ self.action_confirm_send_note(cr, uid, [production.id], context);
return shipment_id
def force_production(self, cr, uid, ids, *args):
@@ -1012,6 +1028,55 @@ class mrp_production(osv.osv):
pick_obj = self.pool.get('stock.picking')
pick_obj.force_assign(cr, uid, [prod.picking_id.id for prod in self.browse(cr, uid, ids)])
return True
+
+ # ---------------------------------------------------
+ # OpenChatter methods and notifications
+ # ---------------------------------------------------
+
+ def get_needaction_user_ids(self, cr, uid, ids, context=None):
+ result = dict.fromkeys(ids, [])
+ for obj in self.browse(cr, uid, ids, context=context):
+ if obj.state == 'draft' and obj.user_id:
+ result[obj.id] = [obj.user_id.id]
+ return result
+
+ def message_get_subscribers(self, cr, uid, ids, context=None):
+ sub_ids = self.message_get_subscribers_ids(cr, uid, ids, context=context);
+ for obj in self.browse(cr, uid, ids, context=context):
+ if obj.user_id:
+ sub_ids.append(obj.user_id.id)
+ return self.pool.get('res.users').read(cr, uid, sub_ids, context=context)
+
+ def create_send_note(self, cr, uid, ids, context=None):
+ self.message_append_note(cr, uid, ids, body=_("Manufacturing order has been created."), context=context)
+ return True
+
+ def action_cancel_send_note(self, cr, uid, ids, context=None):
+ message = _("Manufacturing order has been canceled.")
+ self.message_append_note(cr, uid, ids, body=message, context=context)
+ return True
+
+ def action_ready_send_note(self, cr, uid, ids, context=None):
+ message = _("Manufacturing order is ready to produce.")
+ self.message_append_note(cr, uid, ids, body=message, context=context)
+ return True
+
+ def action_in_production_send_note(self, cr, uid, ids, context=None):
+ message = _("Manufacturing order is in production.")
+ self.message_append_note(cr, uid, ids, body=message, context=context)
+ return True
+
+ def action_done_send_note(self, cr, uid, ids, context=None):
+ message = _("Manufacturing order has been done.")
+ self.message_append_note(cr, uid, ids, body=message, context=context)
+ return True
+
+ def action_confirm_send_note(self, cr, uid, ids, context=None):
+ for obj in self.browse(cr, uid, ids, context=context):
+ message = _("Manufacturing order has been confirmed and is scheduled for the %s.") % (obj.date_planned)
+ self.message_append_note(cr, uid, [obj.id], body=message, context=context)
+ return True
+
mrp_production()
@@ -1019,6 +1084,7 @@ class mrp_production_workcenter_line(osv.osv):
_name = 'mrp.production.workcenter.line'
_description = 'Work Order'
_order = 'sequence'
+ _inherit = ['mail.thread']
_columns = {
'name': fields.char('Work Order', size=64, required=True),
diff --git a/addons/mrp/mrp_view.xml b/addons/mrp/mrp_view.xml
index f96147e9344..ef8645a6081 100644
--- a/addons/mrp/mrp_view.xml
+++ b/addons/mrp/mrp_view.xml
@@ -410,6 +410,8 @@
+
+
@@ -644,6 +646,7 @@
+
@@ -773,7 +776,6 @@
-
@@ -783,6 +785,7 @@
+
diff --git a/addons/mrp_operations/mrp_operations.py b/addons/mrp_operations/mrp_operations.py
index fbf307e860e..580280bf7da 100644
--- a/addons/mrp_operations/mrp_operations.py
+++ b/addons/mrp_operations/mrp_operations.py
@@ -156,22 +156,24 @@ class mrp_production_workcenter_line(osv.osv):
prod_obj.write(cr, uid, [prod.production_id.id], {'date_start':dstart}, context=context, mini=False)
return result
- def action_draft(self, cr, uid, ids):
+ def action_draft(self, cr, uid, ids, context=None):
""" Sets state to draft.
@return: True
"""
self.write(cr, uid, ids, {'state':'draft'})
+ self.action_draft_send_note(cr, uid, ids, context=context)
return True
- def action_start_working(self, cr, uid, ids):
+ def action_start_working(self, cr, uid, ids, context=None):
""" Sets state to start working and writes starting date.
@return: True
"""
self.modify_production_order_state(cr, uid, ids, 'start')
self.write(cr, uid, ids, {'state':'startworking', 'date_start': time.strftime('%Y-%m-%d %H:%M:%S')})
+ self.action_start_send_note(cr, uid, ids, context=context)
return True
- def action_done(self, cr, uid, ids):
+ def action_done(self, cr, uid, ids, context=None):
""" Sets state to done, writes finish date and calculates delay.
@return: True
"""
@@ -185,28 +187,76 @@ class mrp_production_workcenter_line(osv.osv):
delay += (date_finished-date_start).seconds / float(60*60)
self.write(cr, uid, ids, {'state':'done', 'date_finished': date_now,'delay':delay})
+ self.action_done_send_note(cr, uid, ids, context=context)
self.modify_production_order_state(cr,uid,ids,'done')
return True
- def action_cancel(self, cr, uid, ids):
+ def action_cancel(self, cr, uid, ids, context=None):
""" Sets state to cancel.
@return: True
"""
self.write(cr, uid, ids, {'state':'cancel'})
+ self.action_cancel_send_note(cr, uid, ids, context=context)
return True
- def action_pause(self, cr, uid, ids):
+ def action_pause(self, cr, uid, ids, context=None):
""" Sets state to pause.
@return: True
"""
self.write(cr, uid, ids, {'state':'pause'})
+ self.action_pending_send_note(cr, uid, ids, context=context)
return True
- def action_resume(self, cr, uid, ids):
+ def action_resume(self, cr, uid, ids, context=None):
""" Sets state to startworking.
@return: True
"""
self.write(cr, uid, ids, {'state':'startworking'})
+ self.action_start_send_note(cr, uid, ids, context=context)
+ return True
+
+ # -------------------------------------------------------
+ # OpenChatter methods and notifications
+ # -------------------------------------------------------
+
+ def action_draft_send_note(self, cr, uid, ids, context=None):
+ prod_obj = self.pool.get('mrp.production')
+ for workorder in self.browse(cr, uid, ids):
+ for prod in prod_obj.browse(cr, uid, [workorder.production_id]):
+ message = _("Work order has been created for production order %s.") % (prod.id.name)
+ self.message_append_note(cr, uid, [workorder.id], body=message, context=context)
+ return True
+
+ def action_start_send_note(self, cr, uid, ids, context=None):
+ prod_obj = self.pool.get('mrp.production')
+ for workorder in self.browse(cr, uid, ids):
+ for prod in prod_obj.browse(cr, uid, [workorder.production_id]):
+ message = _("Work order has been started for production order %s.") % (prod.id.name)
+ self.message_append_note(cr, uid, [workorder.id], body=message, context=context)
+ return True
+
+ def action_done_send_note(self, cr, uid, ids, context=None):
+ prod_obj = self.pool.get('mrp.production')
+ for workorder in self.browse(cr, uid, ids):
+ for prod in prod_obj.browse(cr, uid, [workorder.production_id]):
+ message = _("Work order has been done for production order %s.") % (prod.id.name)
+ self.message_append_note(cr, uid, [workorder.id], body=message, context=context)
+ return True
+
+ def action_pending_send_note(self, cr, uid, ids, context=None):
+ prod_obj = self.pool.get('mrp.production')
+ for workorder in self.browse(cr, uid, ids):
+ for prod in prod_obj.browse(cr, uid, [workorder.production_id]):
+ message = _("Work order is pending for production order %s.") % (prod.id.name)
+ self.message_append_note(cr, uid, [workorder.id], body=message, context=context)
+ return True
+
+ def action_cancel_send_note(self, cr, uid, ids, context=None):
+ prod_obj = self.pool.get('mrp.production')
+ for workorder in self.browse(cr, uid, ids):
+ for prod in prod_obj.browse(cr, uid, [workorder.production_id]):
+ message = _("Work order has been cancelled for production order %s.") % (prod.id.name)
+ self.message_append_note(cr, uid, [workorder.id], body=message, context=context)
return True
mrp_production_workcenter_line()
@@ -251,7 +301,7 @@ class mrp_production(osv.osv):
if prod.workcenter_lines:
wf_service.trg_validate(uid, 'mrp.production.workcenter.line', prod.workcenter_lines[0].id, 'button_start_working', cr)
return super(mrp_production,self).action_in_production(cr, uid, ids)
-
+
def action_cancel(self, cr, uid, ids, context=None):
""" Cancels work order if production order is canceled.
@return: Super method
diff --git a/addons/mrp_operations/mrp_operations_view.xml b/addons/mrp_operations/mrp_operations_view.xml
index 00b4947122e..b588ab53b8f 100644
--- a/addons/mrp_operations/mrp_operations_view.xml
+++ b/addons/mrp_operations/mrp_operations_view.xml
@@ -118,6 +118,7 @@
+
diff --git a/addons/product/product.py b/addons/product/product.py
index 0d5fa31ac11..bf3f85ff794 100644
--- a/addons/product/product.py
+++ b/addons/product/product.py
@@ -167,7 +167,7 @@ class product_uom(osv.osv):
if value == 'reference':
return {'value': {'factor': 1, 'factor_inv': 1}}
return {}
-
+
def write(self, cr, uid, ids, vals, context=None):
if 'category_id' in vals:
for uom in self.browse(cr, uid, ids, context=context):
@@ -231,7 +231,7 @@ class product_category(osv.osv):
_parent_store = True
_parent_order = 'sequence, name'
_order = 'parent_left'
-
+
def _check_recursion(self, cr, uid, ids, context=None):
level = 100
while len(ids):
@@ -259,7 +259,7 @@ class product_template(osv.osv):
_description = "Product Template"
def _get_main_product_supplier(self, cr, uid, product, context=None):
- """Determines the main (best) product supplier for ``product``,
+ """Determines the main (best) product supplier for ``product``,
returning the corresponding ``supplierinfo`` record, or False
if none were found. The default strategy is to select the
supplier with the highest priority (i.e. smallest sequence).
@@ -503,6 +503,7 @@ class product_product(osv.osv):
_description = "Product"
_table = "product_product"
_inherits = {'product.template': 'product_tmpl_id'}
+ _inherit = ['mail.thread']
_order = 'default_code,name_template'
_columns = {
'qty_available': fields.function(_product_qty_available, type='float', string='Quantity On Hand'),
@@ -526,7 +527,15 @@ class product_product(osv.osv):
'color': fields.integer('Color Index'),
'product_image': fields.binary('Image'),
}
-
+
+ def create(self, cr, uid, vals, context=None):
+ obj_id = super(product_product, self).create(cr, uid, vals, context=context)
+ self.create_send_note(cr, uid, [obj_id], context=context)
+ return obj_id
+
+ def create_send_note(self, cr, uid, ids, context=None):
+ return self.message_append_note(cr, uid, ids, body=_("Product has been created."), context=context)
+
def unlink(self, cr, uid, ids, context=None):
unlink_ids = []
unlink_product_tmpl_ids = []
diff --git a/addons/product/product_view.xml b/addons/product/product_view.xml
index e751edc0ae2..63be91125bf 100644
--- a/addons/product/product_view.xml
+++ b/addons/product/product_view.xml
@@ -69,27 +69,26 @@
+
diff --git a/addons/stock/wizard/stock_change_product_qty.py b/addons/stock/wizard/stock_change_product_qty.py
index 9d3de5692f0..162aea77f86 100644
--- a/addons/stock/wizard/stock_change_product_qty.py
+++ b/addons/stock/wizard/stock_change_product_qty.py
@@ -26,6 +26,7 @@ import tools
class stock_change_product_qty(osv.osv_memory):
_name = "stock.change.product.qty"
+ _inherit = ['mail.thread']
_description = "Change Product Quantity"
_columns = {
'product_id' : fields.many2one('product.product', 'Product'),
@@ -98,9 +99,24 @@ class stock_change_product_qty(osv.osv_memory):
inventry_obj.action_confirm(cr, uid, [inventory_id], context=context)
inventry_obj.action_done(cr, uid, [inventory_id], context=context)
-
+ self.change_product_qty_send_note(cr, uid, [data.id], context)
return {}
+ def change_product_qty_send_note (self, cr, uid, ids, context=None):
+ prod_obj = self.pool.get('product.product')
+ location_obj = self.pool.get('stock.location')
+ prod_temp_obj = self.pool.get('product.template')
+ uom_obj = self.pool.get('product.uom')
+
+ for data in self.browse(cr, uid, ids, context=context):
+ for location in location_obj.browse(cr, uid, [data.location_id.id], context=context):
+ location_name = location.name
+ for prod in prod_obj.browse(cr, uid, [data.product_id.id], context=context):
+ for prod_temp in prod_temp_obj.browse(cr, uid, [prod.product_tmpl_id.id], context=context):
+ for uom in uom_obj.browse(cr, uid, [prod_temp.uom_id.id], context=context):
+ message = _("Quantity has been changed to %s %s for %s location.") % (data.new_quantity,uom.name,location_name)
+ prod_obj.message_append_note(cr, uid, [prod.id], body=message, context=context)
+
stock_change_product_qty()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: