← Back to team overview

openerp-dev-web team mailing list archive

[Merge] lp:~openerp-dev/openobject-addons/trunk-crm-imp2 into lp:openobject-addons

 

tfr (Openerp) has proposed merging lp:~openerp-dev/openobject-addons/trunk-crm-imp2 into lp:openobject-addons.

Requested reviews:
  OpenERP Core Team (openerp)

For more details, see:
https://code.launchpad.net/~openerp-dev/openobject-addons/trunk-crm-imp2/+merge/52998
-- 
https://code.launchpad.net/~openerp-dev/openobject-addons/trunk-crm-imp2/+merge/52998
Your team OpenERP R&D Team is subscribed to branch lp:~openerp-dev/openobject-addons/trunk-crm-imp2.
=== modified file 'crm/wizard/crm_merge_opportunities.py'
--- crm/wizard/crm_merge_opportunities.py	2011-02-24 15:03:09 +0000
+++ crm/wizard/crm_merge_opportunities.py	2011-03-11 11:02:21 +0000
@@ -108,6 +108,7 @@
                 'street' : self._get_first_not_null('street', op_ids),
                 'street2' : self._get_first_not_null('street2', op_ids),
                 'zip' : self._get_first_not_null('zip', op_ids),
+                'state' : 'open'
 
             }
 

=== modified file 'crm/wizard/crm_send_email.py'
--- crm/wizard/crm_send_email.py	2011-02-28 11:08:04 +0000
+++ crm/wizard/crm_send_email.py	2011-03-11 11:02:21 +0000
@@ -57,9 +57,25 @@
         'body': fields.text('Message Body', required=True),
         'state': fields.selection(AVAILABLE_STATES, string='Set New State To', required=True),
         'attachment_ids' : fields.one2many('crm.send.mail.attachment', 'wizard_id', 'Attachment'),
-        'html': fields.boolean('HTML formatting?', help="Select this if you want to send email with HTML formatting."), 
+        'html': fields.boolean('HTML formatting?', help="Select this if you want to send email with HTML formatting."),
     }
 
+    def action_mass_send(self, cr, uid, ids, context=None):
+
+        if not context:
+            context = {}
+
+        context.update({'mail' : 'new'})
+        actives_ids = context.get('active_ids')
+        print "mass_mail", context.get('mass_mail')
+        model = context.get('active_model')
+        case_pool = self.pool.get(model)
+        for id in actives_ids:
+            context.update({'active_id' : id})
+            self.action_send(cr, uid, ids, context=context)
+
+        return {'type': 'ir.actions.act_window_close'}
+
     def action_send(self, cr, uid, ids, context=None):
         """ This sends an email to ALL the addresses of the selected partners.
         """
@@ -75,6 +91,8 @@
         case_pool = self.pool.get(model)
         res_id = context and context.get('active_id', False) or False
 
+
+
         for obj in self.browse(cr, uid, ids, context=context):
             attach = [
                 (x.name, base64.decodestring(x.binary)) for x in obj.attachment_ids
@@ -110,8 +128,14 @@
                 res_id = hist.res_id
                 ref_id = hist.ref_id
                 case = case_pool.browse(cr, uid, res_id, context=context)
+
             emails = re.findall(r'([^ ,<@]+@[^> ,]+)', obj.email_to or '')
+            if context.get('mass_mail'):
+                email_temp = case.email_from and tools.ustr(case.email_from) or ''
+                emails = re.findall(r'([^ ,<@]+@[^> ,]+)', email_temp)
+
             email_cc = re.findall(r'([^ ,<@]+@[^> ,]+)', obj.email_cc or '')
+
             emails = filter(None, emails)
             body = obj.body
 
@@ -180,10 +204,11 @@
 
         user_obj = self.pool.get('res.users')
         user_mail_from = user_obj._get_email_from(cr, uid, [uid], context=context)[uid]
-
         for case in mod_obj.browse(cr, uid, res_id, context=context):
             if 'email_to' in fields:
                 res.update({'email_to': case.email_from and tools.ustr(case.email_from) or ''})
+                if context.get('mass_mail'):
+                    res.update({'email_to': ''})
             if 'email_from' in fields:
                 res.update({'email_from': user_mail_from and tools.ustr(user_mail_from) or ''})
             if 'reply_to' in fields:
@@ -191,8 +216,12 @@
                     res.update({'reply_to': case.section_id and case.section_id.reply_to or False})
             if 'subject' in fields:
                 res.update({'subject': tools.ustr(context.get('subject', case.name) or '')})
+                if context.get('mass_mail'):
+                    res.update({'subject': ''})
             if 'email_cc' in fields:
                 res.update({'email_cc': tools.ustr(case.email_cc or '')})
+                if context.get('mass_mail'):
+                    res.update({'email_cc': ''})
             if 'body' in fields:
                 res.update({'body': u'\n'+(tools.ustr(case.user_id.signature or ''))})
             if 'state' in fields:

=== modified file 'crm/wizard/crm_send_email_view.xml'
--- crm/wizard/crm_send_email_view.xml	2011-01-31 08:44:19 +0000
+++ crm/wizard/crm_send_email_view.xml	2011-03-11 11:02:21 +0000
@@ -44,6 +44,46 @@
             </field>
         </record>
 
+        <record model="ir.ui.view" id="crm_send_new_mass_mail_view">
+            <field name="name">crm.new.send.mass.mail.form</field>
+            <field name="model">crm.send.mail</field>
+            <field name="type">form</field>
+            <field name="arch" type="xml">
+                <form string="Send Mail" col="4">
+                    <group colspan="4" col="2">
+                    <field name="email_from"/>
+                    <field name="reply_to"/>
+                    <field name="email_to" invisible="True" />
+                    <field name="email_cc"/>
+                    <field name="subject" />
+                    <field name="html"/>
+                    </group>
+                    <notebook colspan="6">
+                        <page string="Message">
+                            <field name="body" nolabel="1" colspan="4" default_focus="1"/>
+                        </page>
+                        <page string="Attachments">
+                            <field name="attachment_ids" colspan="4" nolabel="1">
+                                <form string="Attachment">
+                                    <field name="binary" filename="name" />
+                                    <field name="name" />
+                                </form>
+                                <tree string="Attachments">
+                                    <field name="name" />
+                                </tree>
+                            </field>
+                        </page>
+                    </notebook>
+                    <separator string="" colspan="6"/>
+                    <group colspan="6" col="4" >
+                        <field name="state" />
+                        <button string="_Cancel" icon="gtk-cancel" special="cancel" />
+                        <button name="action_mass_send" type="object" string="_Send to All" icon="gtk-go-forward" />
+                    </group>
+                </form>
+            </field>
+        </record>
+
 <!-- Send New Mail action -->
 
         <record model="ir.actions.act_window" id="action_crm_send_mail">
@@ -56,6 +96,14 @@
         </record>
 
 
+        <act_window id="action_crm_send_mass_mail"
+            multi="True"
+            key2="client_action_multi" name="Send emails"
+            res_model="crm.send.mail" src_model="crm.lead"
+            view_mode="form" target="new" view_type="form"
+            context="{'mass_mail' : True}"
+            view_id="crm_send_new_mass_mail_view"/>
+
     <!-- Reply to Mail view -->
 
         <record model="ir.ui.view" id="crm_reply_mail_view">
@@ -89,6 +137,9 @@
             </field>
         </record>
 
+
+
+
 <!-- Reply to Mail action -->
 
         <record model="ir.actions.act_window" id="action_crm_reply_mail">

=== modified file 'crm_partner_assign/__openerp__.py'
--- crm_partner_assign/__openerp__.py	2011-02-08 10:11:14 +0000
+++ crm_partner_assign/__openerp__.py	2011-03-11 11:02:21 +0000
@@ -36,6 +36,7 @@
         'wizard/crm_forward_to_partner_view.xml',
         'crm_lead_view.xml',
         'report/crm_lead_report_view.xml',
+        'report/crm_partner_report_view.xml',
     ],
     'test': ['test/test_crm_partner_assign.yml'],
     'installable': True,

=== modified file 'crm_partner_assign/partner_geo_assign.py'
--- crm_partner_assign/partner_geo_assign.py	2011-02-24 11:21:25 +0000
+++ crm_partner_assign/partner_geo_assign.py	2011-03-11 11:02:21 +0000
@@ -142,21 +142,6 @@
                         ('country', '=', part.country_id.id),
                     ], context=context)
 
-                # 3. third way: other countries, small area
-                if not part_ids:
-                    part_ids = self.pool.get('res.partner').search(cr, uid, [
-                        ('partner_weight','>',0),
-                        ('partner_latitude','>',result[0]-2), ('partner_latitude','<',result[0]+2),
-                        ('partner_longitude','>',result[1]-1.5), ('partner_longitude','<',result[1]+1.5)
-                    ], context=context)
-
-                # 4. fourth way: other countries, big area
-                if not part_ids:
-                    part_ids = self.pool.get('res.partner').search(cr, uid, [
-                        ('partner_weight','>',0),
-                        ('partner_latitude','>',result[0]-4), ('partner_latitude','<',result[0]+4),
-                        ('partner_longitude','>',result[1]-3), ('partner_longitude','<',result[1]+3)
-                    ], context=context)
 
                 # 5. fifth way: anywhere in same country
                 if not part_ids:

=== modified file 'crm_partner_assign/report/__init__.py'
--- crm_partner_assign/report/__init__.py	2011-01-14 00:11:01 +0000
+++ crm_partner_assign/report/__init__.py	2011-03-11 11:02:21 +0000
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 ##############################################################################
-#    
+#
 #    OpenERP, Open Source Management Solution
 #    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
 #
@@ -15,9 +15,10 @@
 #    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 <http://www.gnu.org/licenses/>.     
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 ##############################################################################
 
 import crm_lead_report
+import crm_partner_report
 

=== added file 'crm_partner_assign/report/crm_partner_report.py'
--- crm_partner_assign/report/crm_partner_report.py	1970-01-01 00:00:00 +0000
+++ crm_partner_assign/report/crm_partner_report.py	2011-03-11 11:02:21 +0000
@@ -0,0 +1,63 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    OpenERP, Open Source Management Solution
+#    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
+#
+#    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 <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from osv import fields,osv
+import tools
+
+
+class crm_partner_report_assign(osv.osv):
+    """ CRM Lead Report """
+    _name = "crm.partner.report.assign"
+    _auto = False
+    _description = "CRM Partner Report"
+    _columns = {
+        'name': fields.char('Partner name', size=64, required=False, readonly=True),
+        'grade_id':fields.many2one('res.partner.grade', 'Grade', readonly=True),
+        'user_id':fields.many2one('res.users', 'User', readonly=True),
+        'country_id':fields.many2one('res.country', 'Country', readonly=True),
+        'section_id':fields.many2one('crm.case.section', 'Sales Team', readonly=True),
+        'nbr': fields.integer('# of Partner', readonly=True),
+        'opp': fields.integer('# of Opportunity', readonly=True),
+    }
+
+    def init(self, cr):
+
+        """
+            CRM Lead Report
+            @param cr: the current row, from the database cursor
+        """
+        tools.drop_view_if_exists(cr, 'crm_partner_report_assign')
+        cr.execute("""
+            CREATE OR REPLACE VIEW crm_partner_report_assign AS (
+                SELECT
+                    p.id,
+                    p.name,
+                    a.country_id,
+                    p.grade_id,
+                    p.user_id,
+                    p.section_id,
+                    1 as nbr,
+                    (SELECT count(id) FROM crm_lead WHERE partner_assigned_id=p.id) AS opp
+                FROM
+                    res_partner p
+                    left join res_partner_address a on (p.id=a.partner_id)
+            )""")
+
+crm_partner_report_assign()

=== added file 'crm_partner_assign/report/crm_partner_report_view.xml'
--- crm_partner_assign/report/crm_partner_report_view.xml	1970-01-01 00:00:00 +0000
+++ crm_partner_assign/report/crm_partner_report_view.xml	2011-03-11 11:02:21 +0000
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+    <data>
+
+        <!--     Opportunity tree view  -->
+        <record id="view_report_crm_partner_assign_filter" model="ir.ui.view">
+            <field name="name">crm.partner.report.assign.select</field>
+            <field name="model">crm.partner.report.assign</field>
+            <field name="type">search</field>
+            <field name="arch" type="xml">
+                <search string="Partner assigned Analysis">
+                    <group col="20" colspan="8">
+                        <field name="country_id" />
+                        <field name="grade_id"/>
+                        <field name="user_id"/>
+                        <field name="section_id"/>
+                   </group>
+                   <newline/>
+                   <group  expand="1" string="Group By...">
+                       <filter string="Salesman" name="user" icon="terp-personal"
+                            domain="[]" context="{'group_by':'user_id'}" />
+                       <filter string="Country" icon="terp-go-home" name="group_country" context="{'group_by':'country_id'}" />
+                        <separator orientation="vertical" />
+                        <filter string="Section" icon="terp-personal+"
+                            domain="[]"
+                            context="{'group_by':'section_id'}" />
+                        <filter string="Grade" name="group_grade" icon="terp-stock_symbol-selection"
+                            domain="[]" context="{'group_by':'grade_id'}" />
+                        <separator orientation="vertical" />
+                  </group>
+               </search>
+            </field>
+        </record>
+
+<!-- Crm Lead Assign report Graph View -->
+
+       <record id="view_report_crm_partner_assign_tree" model="ir.ui.view">
+            <field name="name">crm.partner.assign.report.tree</field>
+            <field name="model">crm.partner.report.assign</field>
+            <field name="type">tree</field>
+            <field name="arch" type="xml">
+            <tree string="Opportunities Assignment Analysis">
+                <field name="name" invisible="1"/>
+                <field name="country_id" invisible="1"/>
+                <field name="grade_id" invisible="1"/>
+                <field name="section_id" invisible="1" groups="base.group_extended"/>
+                <field name="user_id" invisible="1"/>
+                <field name="nbr" string="#Partner" sum="#Partner"/>
+                <field name="opp"/>
+             </tree>
+            </field>
+       </record>
+
+       <!-- Leads by user and section Action -->
+
+       <record id="action_report_crm_partner_assign" model="ir.actions.act_window">
+            <field name="name">Partner Assignment  Analysis</field>
+            <field name="res_model">crm.partner.report.assign</field>
+            <field name="context">{'search_default_group_country': 1, 'search_default_group_grade': 1, 'group_by_no_leaf':1,'group_by':[]}</field>
+            <field name="view_mode">tree</field>
+            <field name="domain">[('grade_id', '!=', False)]</field>
+        </record>
+
+       <menuitem id="menu_report_crm_partner_assign_tree"
+           groups="base.group_extended"
+           parent="base.next_id_64" action="action_report_crm_partner_assign" sequence="5"/>
+
+    </data>
+</openerp>

=== modified file 'crm_partner_assign/wizard/crm_forward_to_partner.py'
--- crm_partner_assign/wizard/crm_forward_to_partner.py	2011-02-24 15:03:09 +0000
+++ crm_partner_assign/wizard/crm_forward_to_partner.py	2011-03-11 11:02:21 +0000
@@ -44,9 +44,10 @@
     _defaults = {
         'name' : 'email',
         'history': 'latest',
-        'email_from': lambda self, cr, uid, *a: self.pool.get('res.users')._get_email_from(cr, uid, uid)[uid]
+        'email_from': lambda self, cr, uid, *a: self.pool.get('res.users')._get_email_from(cr, uid, uid)[uid],
     }
 
+
     def get_whole_history(self, cr, uid, ids, context=None):
         """This function gets whole communication history and returns as top posting style
         @param self: The object pointer
@@ -87,7 +88,7 @@
         @param uid: the current user’s ID for security checks,
         @param ids: List of Mail’s IDs
         @param user: Changed User id
-        @param partner: Changed Partner id  
+        @param partner: Changed Partner id
         """
         if not user:
             return {'value': {'email_to': False}}
@@ -146,7 +147,7 @@
         @param uid: the current user’s ID for security checks,
         @param ids: List of Mail’s IDs
         @param user: Changed User id
-        @param partner: Changed Partner id  
+        @param partner: Changed Partner id
         """
         if not partner_id:
             return {'value' : {'email_to' : False, 'address_id': False}}
@@ -155,13 +156,13 @@
         addr = partner_obj.address_get(cr, uid, [partner_id], ['contact'])
         data = {'address_id': addr['contact']}
         data.update(self.on_change_address(cr, uid, ids, addr['contact'])['value'])
-        
+
         partner = partner_obj.browse(cr, uid, [partner_id])
         user_id = partner and partner[0].user_id or False
         email = user_id and user_id.user_email or ''
         data.update({'email_cc' : email})
         return {
-            'value' : data, 
+            'value' : data,
             'domain' : {'address_id' : partner_id and "[('partner_id', '=', partner_id)]" or "[]"}
             }
 
@@ -236,23 +237,23 @@
                     body.append("%s: %s" % (field_definition.string, value or ''))
         elif lead.type == 'opportunity':
             pa = lead.partner_address_id
-            body = [
-                "Partner: %s" % (lead.partner_id and lead.partner_id.name_get()[0][1]), 
-                "Contact: %s" % (pa.name or ''), 
-                "Title: %s" % (pa.title or ''), 
-                "Function: %s" % (pa.function or ''), 
-                "Street: %s" % (pa.street or ''), 
-                "Street2: %s" % (pa.street2 or ''), 
-                "Zip: %s" % (pa.zip or ''), 
-                "City: %s" % (pa.city or ''), 
-                "Country: %s" % (pa.country_id and pa.country_id.name_get()[0][1] or ''), 
-                "State: %s" % (pa.state_id and pa.state_id.name_get()[0][1] or ''), 
-                "Email: %s" % (pa.email or ''), 
-                "Phone: %s" % (pa.phone or ''), 
-                "Fax: %s" % (pa.fax or ''), 
-                "Mobile: %s" % (pa.mobile or ''), 
-                "Lead Category: %s" % (lead.categ_id and lead.categ_id.name or ''), 
-                "Details: %s" % (lead.description or ''), 
+            body += [
+                "Partner: %s" % (lead.partner_id and lead.partner_id.name_get()[0][1]),
+                "Contact: %s" % (pa.name or ''),
+                "Title: %s" % (pa.title or ''),
+                "Function: %s" % (pa.function or ''),
+                "Street: %s" % (pa.street or ''),
+                "Street2: %s" % (pa.street2 or ''),
+                "Zip: %s" % (pa.zip or ''),
+                "City: %s" % (pa.city or ''),
+                "Country: %s" % (pa.country_id and pa.country_id.name_get()[0][1] or ''),
+                "State: %s" % (pa.state_id and pa.state_id.name_get()[0][1] or ''),
+                "Email: %s" % (pa.email or ''),
+                "Phone: %s" % (pa.phone or ''),
+                "Fax: %s" % (pa.fax or ''),
+                "Mobile: %s" % (pa.mobile or ''),
+                "Lead Category: %s" % (lead.categ_id and lead.categ_id.name or ''),
+                "Details: %s" % (lead.description or ''),
             ]
         return "\n".join(body + ['---'])
 
@@ -260,26 +261,66 @@
         """
         This function gets default values
         """
+
         if context is None:
             context = {}
 
         defaults = super(crm_lead_forward_to_partner, self).default_get(cr, uid, fields, context=context)
-
         active_id = context.get('active_id')
         if not active_id:
             return defaults
 
         lead_proxy = self.pool.get('crm.lead')
+        partner_obj = self.pool.get('res.partner')
         lead = lead_proxy.browse(cr, uid, active_id, context=context)
 
+        email_cc = ''
+        email = ''
+        if lead.partner_assigned_id:
+            partner = partner_obj.browse(cr, uid, [lead.partner_assigned_id.id])
+            user_id = partner and partner[0].user_id or False
+            email_cc = user_id and user_id.user_email or ''
+
+            addr = partner_obj.address_get(cr, uid, [partner[0].id], ['contact'])
+            email = self.pool.get('res.partner.address').browse(cr, uid, addr['contact']).email
+
         body = self._get_case_history(cr, uid, defaults.get('history', 'latest'), lead.id, context=context)
         defaults.update({
             'subject' : '%s: %s' % (_('Fwd'), lead.name),
             'body' : body,
-            'email_cc' : ''
+            'email_cc' : email_cc,
+            'email_to' : email or 'dummy@xxxxxxxx'
         })
         return defaults
 
 crm_lead_forward_to_partner()
 
+class crm_lead_mass_forward_to_partner(osv.osv_memory):
+    _name = 'crm.lead.mass.forward.to.partner'
+    _inherit = 'crm.lead.forward.to.partner'
+
+    def action_mass_forward(self, cr, uid, ids, context=None):
+        if not context:
+            context = {}
+
+        active_ids = context.get('active_ids')
+        case_obj = self.pool.get('crm.lead')
+        for case in case_obj.browse(cr, uid, active_ids, context=context):
+            if not case.partner_assigned_id:
+                case_obj.assign_partner(cr,uid, [case.id], context=context)
+                case = case_obj.browse(cr, uid, case.id, context=context)
+
+            if not case.partner_assigned_id:
+                continue
+
+            context.update({'active_id' : case.id})
+            value = self.default_get(cr, uid, ['body', 'email_to', 'email_cc', 'subject', 'history'], context=context)
+            self.write(cr, uid, ids, value, context=context)
+            self.action_forward(cr,uid, ids, context=context)
+
+        return {'type': 'ir.actions.act_window_close'}
+
+
+crm_lead_mass_forward_to_partner()
+
 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

=== modified file 'crm_partner_assign/wizard/crm_forward_to_partner_view.xml'
--- crm_partner_assign/wizard/crm_forward_to_partner_view.xml	2011-01-14 00:11:01 +0000
+++ crm_partner_assign/wizard/crm_forward_to_partner_view.xml	2011-03-11 11:02:21 +0000
@@ -38,14 +38,70 @@
                 </button>
             </field>
         </record>
+
         <record model="ir.actions.act_window" id="crm_lead_forward_to_partner_act">
             <field name="name">Forward to Partner</field>
             <field name="res_model">crm.lead.forward.to.partner</field>
             <field name="view_type">form</field>
             <field name="view_mode">form</field>
-            <field name="view_id" ref="crm_lead_forward_to_partner_form1"/>
+            <field name="view_id" ref="crm_lead_forward_to_partner_form"/>
             <field name="target">new</field>
         </record>
 
+
+        <record model="ir.ui.view" id="crm_forward_mass_mail_view">
+            <field name="name">crm.new.mass.forward.mail.form</field>
+            <field name="model">crm.lead.mass.forward.to.partner</field>
+            <field name="type">form</field>
+            <field name="arch" type="xml">
+                <form string="Send Mail" col="4">
+                    <group colspan="4" col="2">
+                    <separator string="Forward to Partner" colspan="4" />
+
+                    <field name="history" colspan="2" on_change="on_change_history(history, context)" invisible="1"/>
+                    <field name="email_from"/>
+                    <field name="reply_to"/>
+                    <field name="email_to" invisible="1" />
+                    <field name="email_cc" invisible="1" />
+                    <field name="subject"  invisible="1" />
+                    <field name="html"/>
+                    </group>
+                    <notebook colspan="6" >
+                        <page string="Message" >
+                            <field name="body" nolabel="1" colspan="4" default_focus="1" readonly="1"/>
+                        </page>
+                        <page string="Attachments" >
+                            <field name="attachment_ids" colspan="4" nolabel="1">
+                                <form string="Attachment">
+                                    <field name="binary" filename="name" />
+                                    <field name="name" />
+                                </form>
+                                <tree string="Attachments">
+                                    <field name="name" />
+                                </tree>
+                            </field>
+                        </page>
+                    </notebook>
+                    <separator string="" colspan="6"/>
+                    <group colspan="6" col="4" >
+                        <field name="state" />
+                        <button string="_Cancel" icon="gtk-cancel" special="cancel" />
+                        <button name="action_mass_forward" type="object" string="_Mass forward" icon="gtk-go-forward" />
+                    </group>
+                </form>
+            </field>
+        </record>
+
+        <act_window id="action_crm_send_mass_forward"
+            multi="True"
+            key2="client_action_multi" name="Mass forward to partner"
+            res_model="crm.lead.mass.forward.to.partner" src_model="crm.lead"
+            view_mode="form" target="new" view_type="form"
+            context="{'mass_forward' : True}"
+            view_id="crm_forward_mass_mail_view"
+        />
+
+
+
     </data>
 </openerp>

=== modified file 'document/document.py'
--- document/document.py	2011-02-28 10:49:36 +0000
+++ document/document.py	2011-03-11 11:02:21 +0000
@@ -279,10 +279,22 @@
         else:
             if vals.get('file_size'):
                 del vals['file_size']
-        if not self._check_duplication(cr, uid, vals):
-            raise osv.except_osv(_('ValidateError'), _('File name must be unique!'))
-        result = super(document_file, self).create(cr, uid, vals, context)
-        cr.commit() # ?
+        result = self._check_duplication(cr, uid, vals)
+        if not result:
+            domain = [
+                ('res_id', '=', vals['res_id']),
+                ('res_model', '=', vals['res_model']),
+                ('datas_fname', '=', vals['datas_fname']),
+            ]
+            attach_ids = self.search(cr, uid, domain, context=context)
+            super(document_file, self).write(cr, uid, attach_ids, 
+                                             {'datas' : vals['datas']},
+                                             context=context)
+            result = attach_ids[0]
+        else:
+            #raise osv.except_osv(_('ValidateError'), _('File name must be unique!'))
+            result = super(document_file, self).create(cr, uid, vals, context)
+            cr.commit() # ?
         return result
 
     def __get_partner_id(self, cr, uid, res_model, res_id, context=None):

=== modified file 'hr/hr.py'
--- hr/hr.py	2011-03-10 12:49:14 +0000
+++ hr/hr.py	2011-03-11 11:02:21 +0000
@@ -154,7 +154,7 @@
         'work_email': fields.char('Work E-mail', size=240),
         'work_location': fields.char('Office Location', size=32),
         'notes': fields.text('Notes'),
-        'parent_id': fields.related('department_id', 'manager_id', relation='hr.employee', string='Manager', type='many2one', store=True, select=True, readonly=True, help="It is linked with manager of Department"),
+        'parent_id': fields.related('department_id', 'manager_id', relation='hr.employee', string='Manager', type='many2one', store=True, select=True, help="It is linked with manager of Department"),
         'category_ids': fields.many2many('hr.employee.category', 'employee_category_rel','category_id','emp_id','Category'),
         'child_ids': fields.one2many('hr.employee', 'parent_id', 'Subordinates'),
         'resource_id': fields.many2one('resource.resource', 'Resource', ondelete='cascade', required=True),


Follow ups