Bhumi Thakkar (Open ERP) has proposed merging 
lp:~openerp-dev/openobject-addons/trunk-social-mrp-bth into 
lp:~openerp-dev/openobject-addons/trunk-social-jra.

Requested reviews:
  OpenERP R&D Team (openerp-dev)

For more details, see:
https://code.launchpad.net/~openerp-dev/openobject-addons/trunk-social-mrp-bth/+merge/96119

Hello,

Notifications in mrp,product,bom.

Thanks,
Bhumi Thakkar (BTH)
-- 
https://code.launchpad.net/~openerp-dev/openobject-addons/trunk-social-mrp-bth/+merge/96119
Your team OpenERP R&D Team is requested to review the proposed merge of 
lp:~openerp-dev/openobject-addons/trunk-social-mrp-bth into 
lp:~openerp-dev/openobject-addons/trunk-social-jra.
=== modified file 'mrp/mrp.py'
--- mrp/mrp.py	2012-02-13 18:07:41 +0000
+++ mrp/mrp.py	2012-03-06 13:49:41 +0000
@@ -130,6 +130,7 @@
     """
     _name = 'mrp.bom'
     _description = 'Bill of Material'
+    _inherit = ['mail.thread']
 
     def _child_compute(self, cr, uid, ids, name, arg, context=None):
         """ Gets child bom.
@@ -312,7 +313,7 @@
         phantom = False
         if bom.type == 'phantom' and not bom.bom_lines:
             newbom = self._bom_find(cr, uid, bom.product_id.id, bom.product_uom.id, properties)
-            
+
             if newbom:
                 res = self._bom_explode(cr, uid, self.browse(cr, uid, [newbom])[0], factor*bom.product_qty, properties, addthis=True, level=level+10)
                 result = result + res[0]
@@ -358,6 +359,19 @@
         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_notification(cr, uid, [obj_id], context=context)
+        return obj_id
+
+    def create_notification(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, ids, _('System notification'),
+                        _("Bill of Material is <b>Created</b> for <em>%s</em> product.") % (prod.id.name_template), type='notification', context=context)
+        return True
+
 mrp_bom()
 
 class mrp_bom_revision(osv.osv):
@@ -393,6 +407,7 @@
     _name = 'mrp.production'
     _description = 'Manufacturing Order'
     _date_name  = 'date_planned'
+    _inherit = ['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,12 +512,54 @@
         (_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_notification(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'):
                 raise osv.except_osv(_('Invalid action !'), _('Cannot delete a manufacturing order in state \'%s\'') % production.state)
         return super(mrp_production, self).unlink(cr, uid, ids, context=context)
 
+    def create_notification(self, cr, uid, ids, context=None):
+        for obj in self.browse(cr, uid, ids, context=context):
+            if obj.user_id.id :
+                self.message_subscribe(cr, uid, ids, [obj.user_id.id], context=context)
+                self.message_append_note(cr, uid, ids, _('System notification'),
+                        _("Manufacturing Order is <b>Created</b>."), type='notification', need_action_user_id=obj.user_id.id, context=context)
+            else :
+                self.message_append_note(cr, uid, ids, _('System notification'),
+                        _("Manufacturing Order is <b>Created</b>."), type='notification', context=context)
+        return True
+
+    def cancel_notification(self, cr, uid, ids, context=None):
+        message = _("Manufacturing order is <b>cancelled</b>.")
+        self.message_append_note(cr, uid, ids, '', message, context=context)
+        return True
+
+    def ready_notification(self, cr, uid, ids, context=None):
+        message = _("Manufacturing order is <b>ready to produce</b>.")
+        self.message_append_note(cr, uid, ids, '', message, context=context)
+        return True
+
+    def inproduction_notification(self, cr, uid, ids, context=None):
+        message = _("Manufacturing order is <b>in production</b>.")
+        self.message_append_note(cr, uid, ids, '', message, context=context)
+        return True
+
+    def done_notification(self, cr, uid, ids, context=None):
+        self.message_mark_done(cr, uid, ids, context)
+        message = _("Manufacturing order is <b>done</b>.")
+        self.message_append_note(cr, uid, ids, '', message, context=context)
+        return True
+
+    def waiting_notification(self, cr, uid, ids, context=None):
+        message = _("Manufacturing order is <b>waiting for goods</b>.")
+        self.message_append_note(cr, uid, ids, '', message, context=context)
+        return True
+
     def copy(self, cr, uid, id, default=None, context=None):
         if default is None:
             default = {}
@@ -629,9 +686,10 @@
                 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.cancel_notification(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 +701,18 @@
             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.ready_notification(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')})
+        self.write(cr, uid, ids, {'state': 'done', 'date_finished': time.strftime('%Y-%m-%d %H:%M:%S')})
+        self.done_notification(cr, uid, ids, context)
+        return True
 
     def test_production_done(self, cr, uid, ids):
         """ Tests whether production is done or not.
@@ -670,9 +728,9 @@
         return res
 
     def _get_subproduct_factor(self, cr, uid, production_id, move_id=None, context=None):
-        """ Compute the factor to compute the qty of procucts to produce for the given production_id. By default, 
-            it's always equal to the quantity encoded in the production order or the production wizard, but if the 
-            module mrp_subproduct is installed, then we must use the move_id to identify the product to produce 
+        """ Compute the factor to compute the qty of procucts to produce for the given production_id. By default,
+            it's always equal to the quantity encoded in the production order or the production wizard, but if the
+            module mrp_subproduct is installed, then we must use the move_id to identify the product to produce
             and its quantity.
         :param production_id: ID of the mrp.order
         :param move_id: ID of the stock move that needs to be produced. Will be used in mrp_subproduct.
@@ -698,7 +756,6 @@
             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 = {}
 
@@ -733,7 +790,7 @@
                         prod_name = scheduled.product_id.name_get()[0][1]
                         raise osv.except_osv(_('Warning!'), _('You are going to consume total %s quantities of "%s".\nBut you can only consume up to total %s quantities.') % (qty, prod_name, qty_avail))
                     if qty <= 0.0:
-                        # we already have more qtys consumed than we need 
+                        # we already have more qtys consumed than we need
                         continue
 
                     raw_product[0].action_consume(qty, raw_product[0].location_id.id, context=context)
@@ -819,11 +876,12 @@
                     } )
         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.inproduction_notification(cr, uid, ids, context)
         return True
 
     def test_if_product(self, cr, uid, ids):
@@ -890,14 +948,14 @@
                         'state': 'waiting',
                         'company_id': production.company_id.id,
                 })
-          
+
     def _make_production_internal_shipment(self, cr, uid, production, context=None):
         ir_sequence = self.pool.get('ir.sequence')
         stock_picking = self.pool.get('stock.picking')
         routing_loc = None
         pick_type = 'internal'
         address_id = False
-        
+
         # Take routing address as a Shipment Address.
         # If usage of routing location is a internal, make outgoing shipment otherwise internal shipment
         if production.bom_id.routing_id and production.bom_id.routing_id.location_id:
@@ -926,7 +984,7 @@
         stock_move = self.pool.get('stock.move')
         source_location_id = production.product_id.product_tmpl_id.property_stock_production.id
         destination_location_id = production.location_dest_id.id
-        move_name = _('PROD: %s') + production.name 
+        move_name = _('PROD: %s') + production.name
         data = {
             'name': move_name,
             'date': production.date_planned,
@@ -983,7 +1041,7 @@
         for production in self.browse(cr, uid, ids, context=context):
             shipment_id = self._make_production_internal_shipment(cr, uid, production, context=context)
             produce_move_id = self._make_production_produce_line(cr, uid, production, context=context)
-            
+
             # Take routing location as a Source Location.
             source_location_id = production.location_src_id.id
             if production.bom_id.routing_id and production.bom_id.routing_id.location_id:
@@ -994,14 +1052,14 @@
                 shipment_move_id = self._make_production_internal_shipment_line(cr, uid, line, shipment_id, consume_move_id,\
                                  destination_location_id=source_location_id, context=context)
                 self._make_production_line_procurement(cr, uid, line, shipment_move_id, context=context)
-                    
+
             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.waiting_notification(cr, uid, [production.id], context);
         return shipment_id
 
     def force_production(self, cr, uid, ids, *args):
@@ -1019,6 +1077,7 @@
     _name = 'mrp.production.workcenter.line'
     _description = 'Work Order'
     _order = 'sequence'
+    _inherit = ['mail.thread']
 
     _columns = {
         'name': fields.char('Work Order', size=64, required=True),

=== modified file 'mrp/mrp_view.xml'
--- mrp/mrp_view.xml	2012-02-16 16:29:09 +0000
+++ mrp/mrp_view.xml	2012-03-06 13:49:41 +0000
@@ -410,6 +410,7 @@
                             <field colspan="4" name="property_ids" nolabel="1" groups="base.group_extended"/>
                         </page>
                     </notebook>
+                    <field name="message_ids_social" widget="ThreadView"/>
                 </form>
             </field>
         </record>
@@ -644,6 +645,7 @@
                         <label string="" colspan="2"/>
                         <field name="product_uos_qty" groups="product.group_uos"/>
                         <field name="product_uos" groups="product.group_uos"/>
+                        <field name="user_id"/>
                     </group>
 
                     <notebook colspan="4">
@@ -773,16 +775,14 @@
                             <field colspan="4" name="product_lines" nolabel="1" widget="one2many_list"/>
                         </page>
                         <page string="Extra Information">
-                            <field name="user_id"/>
                             <field name="company_id" groups="base.group_multi_company" widget="selection"/>
                             <field name="priority" groups="base.group_extended"/>
                             <newline/>
-                            <field name="date_start"/>
-                            <field name="date_finished"/>
                             <field name="picking_id" groups="base.group_extended"/>
                             <field name="move_prod_id" groups="base.group_extended"/>
                         </page>
                     </notebook>
+                    <field name="message_ids_social" widget="ThreadView"/>
                 </form>
             </field>
         </record>

=== modified file 'mrp_operations/mrp_operations.py'
--- mrp_operations/mrp_operations.py	2012-01-31 13:36:57 +0000
+++ mrp_operations/mrp_operations.py	2012-03-06 13:49:41 +0000
@@ -156,11 +156,62 @@
                     prod_obj.write(cr, uid, [prod.production_id.id], {'date_start':dstart}, context=context, mini=False)
         return result
 
+    def draft_notification(self, cr, uid, ids):
+        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 = _("<em>%s</em> Work Order is <b>created</b>.") % (workorder.name)
+                prod_obj.message_append_note(cr, uid, [prod.id], '', message)
+                womessage = _("Work Order is <b>created</b> for <em>%s</em> production order.") % (prod.id.name)
+        self.message_append_note(cr, uid, ids, '', womessage)
+        return True
+
+    def start_notification(self, cr, uid, ids):
+        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 = _("<em>%s</em> Work Order is <b>started</b>.") % (workorder.name)
+                prod_obj.message_append_note(cr, uid, [prod.id], '', message)
+                womessage = _("Work Order is <b>started</b> for <em>%s</em> production order.") % (prod.id.name)
+        self.message_append_note(cr, uid, ids, '', womessage)
+        return True
+
+    def done_notification(self, cr, uid, ids):
+        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 = _("<em>%s</em>Work Order is <b>finished</b>.") % (workorder.name)
+                prod_obj.message_append_note(cr, uid, [prod.id], '', message)
+                womessage = _("Work Order is <b>done</b> for <em>%s</em> production order.") % (prod.id.name)
+        self.message_append_note(cr, uid, ids, '', womessage)
+        return True
+
+    def pending_notification(self, cr, uid, ids):
+        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 = _("<em>%s</em>Work Order is <b>pending</b>.") % (workorder.name)
+                prod_obj.message_append_note(cr, uid, [prod.id], '', message)
+                womessage = _("Work Order is <b>pending</b> for <em>%s</em> production order.") % (prod.id.name)
+        self.message_append_note(cr, uid, ids, '', womessage)
+        return True
+
+    def cancel_notification(self, cr, uid, ids):
+        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 = _("<em>%s</em>Work Order is <b>cancelled</b>.") % (workorder.name)
+                prod_obj.message_append_note(cr, uid, [prod.id], '', message)
+                womessage = _("Work Order is <b>cancelled</b> for <em>%s</em> production order.") % (prod.id.name)
+        self.message_append_note(cr, uid, ids, '', womessage)
+        return True
+
     def action_draft(self, cr, uid, ids):
         """ Sets state to draft.
         @return: True
         """
         self.write(cr, uid, ids, {'state':'draft'})
+        self.draft_notification(cr, uid, ids)
         return True
 
     def action_start_working(self, cr, uid, ids):
@@ -169,6 +220,7 @@
         """
         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.start_notification(cr, uid, ids)
         return True
 
     def action_done(self, cr, uid, ids):
@@ -185,6 +237,7 @@
         delay += (date_finished-date_start).seconds / float(60*60)
 
         self.write(cr, uid, ids, {'state':'done', 'date_finished': date_now,'delay':delay})
+        self.done_notification(cr, uid, ids)
         self.modify_production_order_state(cr,uid,ids,'done')
         return True
 
@@ -193,6 +246,7 @@
         @return: True
         """
         self.write(cr, uid, ids, {'state':'cancel'})
+        self.cancel_notification(cr, uid, ids)
         return True
 
     def action_pause(self, cr, uid, ids):
@@ -200,6 +254,7 @@
         @return: True
         """
         self.write(cr, uid, ids, {'state':'pause'})
+        self.pending_notification(cr, uid, ids)
         return True
 
     def action_resume(self, cr, uid, ids):
@@ -207,6 +262,7 @@
         @return: True
         """
         self.write(cr, uid, ids, {'state':'startworking'})
+        self.start_notification(cr, uid, ids)
         return True
 
 mrp_production_workcenter_line()
@@ -251,7 +307,7 @@
             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

=== modified file 'mrp_operations/mrp_operations_view.xml'
--- mrp_operations/mrp_operations_view.xml	2012-01-31 13:36:57 +0000
+++ mrp_operations/mrp_operations_view.xml	2012-03-06 13:49:41 +0000
@@ -118,6 +118,7 @@
                     </group>
                 </page>
                 </notebook>
+                <field name="message_ids_social" widget="ThreadView"/>
             </form>
         </field>
     </record>

=== modified file 'product/product.py'
--- product/product.py	2012-02-14 14:34:20 +0000
+++ product/product.py	2012-03-06 13:49:41 +0000
@@ -167,7 +167,7 @@
         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 @@
     _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 @@
     _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 @@
     _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,18 @@
         '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_notification(cr, uid, [obj_id], context=context)
+        return obj_id
+
+    def create_notification(self, cr, uid, ids, context=None):
+        for obj in self.browse(cr, uid, ids, context=context):
+            self.message_append_note(cr, uid, ids, _('System notification'),
+                        _("Product is <b>Created</b>."), type='notification', context=context)
+        return True
+
     def unlink(self, cr, uid, ids, context=None):
         unlink_ids = []
         unlink_product_tmpl_ids = []

=== modified file 'product/product_view.xml'
--- product/product_view.xml	2012-02-09 17:00:46 +0000
+++ product/product_view.xml	2012-03-06 13:49:41 +0000
@@ -87,7 +87,7 @@
                     </group>
                     <group colspan="1" col="1">
                         <field name="product_image" widget='image' nolabel="1"/>
-                    </group> 
+                    </group>
                    </group>
 
                     <notebook colspan="4">
@@ -192,6 +192,7 @@
                             </field>
                         </page>
                     </notebook>
+                    <field name="message_ids_social" widget="ThreadView"/>
                 </form>
             </field>
         </record>
@@ -257,24 +258,24 @@
             <field name="view_mode">tree,form,kanban</field>
             <field name="view_type">form</field>
             <field name="context">{"search_default_filter_to_sell":1}</field>
-            <field name="view_id" ref="product_product_tree_view"/>  
-            <field name="search_view_id" ref="product_search_form_view"/>            
+            <field name="view_id" ref="product_product_tree_view"/>
+            <field name="search_view_id" ref="product_search_form_view"/>
             <field name="help">You must define a Product for everything you buy or sell. Products can be raw materials, stockable products, consumables or services. The Product form contains detailed information about your products related to procurement logistics, sales price, product category, suppliers and so on.</field>
         </record>
-        
+
         <record id="open_view_product_tree1" model="ir.actions.act_window.view">
             <field name="sequence" eval="1"/>
             <field name="view_mode">tree</field>
            <field name="view_id" ref="product_product_tree_view"/>
             <field name="act_window_id" ref="product_normal_action_sell"/>
         </record>
-        
+
         <record id="open_view_product_form1" model="ir.actions.act_window.view">
             <field name="sequence" eval="2"/>
             <field name="view_mode">form</field>
             <field name="view_id" ref="product_normal_form_view"/>
             <field name="act_window_id" ref="product_normal_action_sell"/>
-        </record> 
+        </record>
 
         <menuitem id="base.menu_product" name="Products" parent="base.menu_base_partner" sequence="9"/>
         <menuitem action="product.product_normal_action_sell" id="product.menu_products" parent="base.menu_product" sequence="1"/>

=== modified file 'stock/wizard/stock_change_product_qty.py'
--- stock/wizard/stock_change_product_qty.py	2011-12-22 13:46:20 +0000
+++ stock/wizard/stock_change_product_qty.py	2012-03-06 13:49:41 +0000
@@ -26,6 +26,7 @@
 
 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,19 @@
 
             inventry_obj.action_confirm(cr, uid, [inventory_id], context=context)
             inventry_obj.action_done(cr, uid, [inventory_id], context=context)
-
+            self.quantity_change_notification(cr, uid, [data.id], context)
         return {}
 
+    def quantity_change_notification (self, cr, uid, ids, context=None):
+        prod_obj = self.pool.get('product.product')
+        location_obj = self.pool.get('stock.location')
+        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):
+                message = _("<b>Quantity is changed</b> to <em>%s</em> for <em>%s</em> location.") % (data.new_quantity,location_name)
+                prod_obj.message_append_note(cr, uid, [prod.id], '', message)
+
 stock_change_product_qty()
 
 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

_______________________________________________
Mailing list: https://launchpad.net/~openerp-dev-gtk
Post to     : [email protected]
Unsubscribe : https://launchpad.net/~openerp-dev-gtk
More help   : https://help.launchpad.net/ListHelp

Reply via email to