[IMP] crm_partner_assign: clean test case and APIs
authorHarry (OpenERP) <hmo@tinyerp.com>
Wed, 26 Oct 2011 09:21:33 +0000 (14:51 +0530)
committerHarry (OpenERP) <hmo@tinyerp.com>
Wed, 26 Oct 2011 09:21:33 +0000 (14:51 +0530)
bzr revid: hmo@tinyerp.com-20111026092133-xdrikqkxs4e5usw3

addons/crm/crm_lead.py
addons/crm_partner_assign/__openerp__.py
addons/crm_partner_assign/partner_geo_assign.py
addons/crm_partner_assign/res_partner_demo.xml [new file with mode: 0644]
addons/crm_partner_assign/test/process/partner_assign.yml
addons/crm_partner_assign/test/ui/partner_assign_form.yml [deleted file]
addons/crm_partner_assign/wizard/__init__.py
addons/crm_partner_assign/wizard/crm_forward_to_partner.py
addons/crm_partner_assign/wizard/crm_forward_to_partner_view.xml
addons/crm_partner_assign/wizard/crm_merge_opportunity.py [deleted file]

index 788903c..2268796 100644 (file)
@@ -335,7 +335,7 @@ class crm_lead(crm_case, osv.osv):
         return self.set_priority(cr, uid, ids, '3')
 
     
-    def _merge_data(self, cr, uid, ids, oldest, context=None):
+    def _merge_data(self, cr, uid, ids, oldest, fields, context=None):
         # prepare opportunity data into dictionary for merging
         opportunities = self.browse(cr, uid, ids, context=context)
         def _get_first_not_null(attr):
@@ -353,40 +353,20 @@ class crm_lead(crm_case, osv.osv):
         def _concat_all(attr):
             return ', '.join([getattr(opportunity, attr) or '' for opportunity in opportunities if hasattr(opportunity, attr)])
 
-        data = {
-            'partner_id': _get_first_not_null_id('partner_id'),  # !!
-            'title': _get_first_not_null_id('title'),
-            'name' : _get_first_not_null('name'),  #not lost
-            'categ_id' : _get_first_not_null_id('categ_id'), # !!
-            'channel_id' : _get_first_not_null_id('channel_id'), # !!
-            'city' : _get_first_not_null('city'),  # !!
-            'company_id' : _get_first_not_null_id('company_id'), #!!
-            'contact_name' : _get_first_not_null('contact_name'), #not lost
-            'country_id' : _get_first_not_null_id('country_id'), #!!
-            'partner_address_id' : _get_first_not_null_id('partner_address_id'), #!!
-            'type_id' : _get_first_not_null_id('type_id'), #!!
-            'user_id' : _get_first_not_null_id('user_id'), #!!
-            'section_id' : _get_first_not_null_id('section_id'), #!!
-            'state_id' : _get_first_not_null_id('state_id'),
-            'description' : _concat_all('description'),  #not lost
-            'email' : _get_first_not_null('email'), # !!
-            'fax' : _get_first_not_null('fax'),
-            'mobile' : _get_first_not_null('mobile'),
-            'partner_name' : _get_first_not_null('partner_name'),
-            'phone' : _get_first_not_null('phone'),
-            'probability' : _get_first_not_null('probability'),
-            'planned_revenue' : _get_first_not_null('planned_revenue'),
-            'street' : _get_first_not_null('street'),
-            'street2' : _get_first_not_null('street2'),
-            'zip' : _get_first_not_null('zip'),
-            'state' : 'open',
-            'create_date' : _get_first_not_null('create_date'),
-            'date_action_last': _get_first_not_null('date_action_last'),
-            'date_action_next': _get_first_not_null('date_action_next'),
-            'email_from' : _get_first_not_null('email_from'),
-            'email_cc' : _get_first_not_null('email_cc'),
-            'partner_name' : _get_first_not_null('partner_name'),
-        }
+        data = {}
+        for field_name in fields:
+            field_info = self._all_columns.get(field_name)
+            if field_info is None:
+                continue
+            field = field_info.column
+            if field._type in ('many2many', 'one2many'):
+                continue  
+            elif field._type == 'many2one':
+                data[field_name] = _get_first_not_null_id(field_name)  # !!
+            elif field._type == 'text':
+                data[field_name] = _concat_all(field_name)  #not lost
+            else:
+                data[field_name] = _get_first_not_null(field_name)  #not lost
         return data
 
     def _merge_find_oldest(self, cr, uid, ids, context=None):
@@ -401,35 +381,45 @@ class crm_lead(crm_case, osv.osv):
         oldest_id = opportunity_ids[0]
         return self.browse(cr, uid, oldest_id, context=context)
 
+    def _mail_body_text(self, cr, uid, lead, fields, title=False, context=None):
+        body = []
+        if title:
+            body.append("%s\n" % (title))
+        for field_name in fields:
+            field_info = self._all_columns.get(field_name)
+            if field_info is None:
+                continue
+            field = field_info.column
+            value = None
+
+            if field._type == 'selection':
+                if hasattr(field.selection, '__call__'):
+                    key = field.selection(self, cr, uid, context=context)
+                else:
+                    key = field.selection
+                value = dict(key).get(lead[field_name], lead[field_name])
+            elif field._type == 'many2one':
+                if lead[field_name]:
+                    value = lead[field_name].name_get()[0][1]
+            else:
+                value = lead[field_name]
+
+            body.append("%s: %s\n" % (field.string, value or ''))
+        return "\n".join(body + ['---'])
+
     def _merge_notification(self, cr, uid, opportunity_id, opportunities, context=None):
         #TOFIX: mail template should be used instead of fix body, subject text
         details = []
         merge_message = _('Merged opportunities')
         subject = [merge_message]
+        fields = ['name', 'partner_id', 'stage_id', 'section_id', 'user_id', 'categ_id', 'channel_id', 'company_id', 'contact_name',
+                  'email_from', 'phone', 'fax', 'mobile', 'state_id', 'description', 'probability', 'planned_revenue',
+                  'country_id', 'city', 'street', 'street2', 'zip']
         for opportunity in opportunities:
             subject.append(opportunity.name)
-            details.append(_('%s : %s\n  Partner: %s\n  Stage: %s\n  Section: %s\n   Salesman: %s\n   Category: %s\n   Channel: %s\n   Company: %s\n   Contact name: %s\n   Email: %s\n   Phone number: %s\n   Fax: %s\n   Mobile: %s\n   State: %s\n   Description: %s\n   Probability: %s\n   Planned revennue: %s\n   Country: %s\n   City: %s\n   Street: %s\n   Street 2: %s\n   Zip 2: %s')  % (merge_message, opportunity.name, opportunity.partner_id.name or '',
-                        opportunity.stage_id.name or '',
-                        opportunity.section_id.name or '',
-                        opportunity.user_id.name or '',
-                        opportunity.categ_id.name or '',
-                        opportunity.channel_id.name or '',
-                        opportunity.company_id.name or '',
-                        opportunity.contact_name or '',
-                        opportunity.email_from or '',
-                        opportunity.phone or '',
-                        opportunity.fax or '',
-                        opportunity.mobile or '',
-                        opportunity.state_id.name or '',
-                        opportunity.description or '',
-                        opportunity.probability or '',
-                        opportunity.planned_revenue or '',
-                        opportunity.country_id.name or '',
-                        opportunity.city or '',
-                        opportunity.street or '',
-                        opportunity.street2 or '',
-                        opportunity.zip or '',
-                        ))
+            title = "%s : %s" % (merge_message, opportunity.name)
+            details.append(self._mail_body_text(cr, uid, opportunity, fields, title=title, context=context))
+            
         subject = subject[0] + ", ".join(subject[1:])
         details = "\n\n".join(details)
         return self.message_append(cr, uid, [opportunity_id], subject, body_text=details, context=context)
@@ -493,7 +483,12 @@ class crm_lead(crm_case, osv.osv):
             first_opportunity = opportunities_list[0]
             tail_opportunities = opportunities_list[1:]
 
-        data = self._merge_data(cr, uid, ids, oldest, context=context)
+        fields = ['partner_id', 'title', 'name', 'categ_id', 'channel_id', 'city', 'company_id', 'contact_name', 'country_id', 
+            'partner_address_id', 'type_id', 'user_id', 'section_id', 'state_id', 'description', 'email', 'fax', 'mobile',
+            'partner_name', 'phone', 'probability', 'planned_revenue', 'street', 'street2', 'zip', 'create_date', 'date_action_last',
+            'date_action_next', 'email_from', 'email_cc', 'partner_name']
+        
+        data = self._merge_data(cr, uid, ids, oldest, fields, context=context)
 
         # merge data into first opportunity
         self.write(cr, uid, [first_opportunity.id], data, context=context)
@@ -507,6 +502,8 @@ class crm_lead(crm_case, osv.osv):
         #delete tail opportunities
         self.unlink(cr, uid, [x.id for x in tail_opportunities], context=context)
 
+        #open first opportunity
+        self.case_open(cr, uid, [first_opportunity.id])
         return first_opportunity.id
 
     def _convert_opportunity_data(self, cr, uid, lead, customer, section_id=False, context=None):
@@ -571,9 +568,17 @@ class crm_lead(crm_case, osv.osv):
         })
         return partner_id
 
-    def _lead_assign_partner(self, cr, uid, ids, partner_id, context=None):
-        contact_id = self.pool.get('res.partner').address_get(cr, uid, [partner_id])['default']
-        return self.write(cr, uid, ids, {'partner_id' : partner_id, 'partner_address_id': contact_id}, context=context)
+    def assign_partner(self, cr, uid, ids, partner_id=None, context=None):
+        res = False
+        res_partner = self.pool.get('res.partner')
+        if partner_id:
+            contact_id = res_partner.address_get(cr, uid, [partner_id])['default']
+            res = self.write(cr, uid, ids, {'partner_id' : partner_id, 'partner_address_id': contact_id}, context=context)
+            partner = res_partner.browse(cr, uid, partner_id, context=context)
+            if partner.user_id:
+                for lead_id in ids:
+                    self.allocate_salesman(cr, uid, [lead_id], [partner.user_id.id], context=context)
+        return res
 
     def _lead_create_partner_address(self, cr, uid, lead, partner_id, context=None):
         address = self.pool.get('res.partner.address')
@@ -609,7 +614,7 @@ class crm_lead(crm_case, osv.osv):
                 if not partner_id:
                     partner_id = self._lead_create_partner(cr, uid, lead, context=context)
                 self._lead_create_partner_address(cr, uid, lead, partner_id, context=context)
-            self._lead_assign_partner(cr, uid, [lead.id], partner_id, context=context)
+            self.assign_partner(cr, uid, [lead.id], partner_id, context=context)
             partner_ids[lead.id] = partner_id
         return partner_ids
 
index 0b9e14c..1752c52 100644 (file)
@@ -38,6 +38,9 @@ You can also use the geolocalization without using the GPS coordinates.
     """,
     'author': 'OpenERP SA',
     'depends': ['crm'],
+    'demo_xml': [
+        'res_partner_demo.xml',
+    ],
     'update_xml': [
         'security/ir.model.access.csv',
         'res_partner_view.xml',
@@ -46,8 +49,9 @@ You can also use the geolocalization without using the GPS coordinates.
         'report/crm_lead_report_view.xml',
         'report/crm_partner_report_view.xml',
     ],
-    'test': ['test/process/partner_assign.yml',
-             'test/ui/partner_assign_form.yml'],
+    'test': [
+        'test/process/partner_assign.yml',
+    ],
     'installable': True,
     'active': False,
     'certificate': '00503409558942442061',
index 2b67f80..1e7168f 100644 (file)
@@ -24,22 +24,25 @@ from osv import fields
 import urllib,re
 import random, time
 from tools.translate import _
+import tools
 
 def geo_find(addr):
+    addr = addr.encode('utf8')
+    regex = '<coordinates>([+-]?[0-9\.]+),([+-]?[0-9\.]+),([+-]?[0-9\.]+)</coordinates>'
+    url = 'http://maps.google.com/maps/geo?q=' + urllib.quote(addr) + '&output=xml&oe=utf8&sensor=false'
     try:
-        regex = '<coordinates>([+-]?[0-9\.]+),([+-]?[0-9\.]+),([+-]?[0-9\.]+)</coordinates>'
-        url = 'http://maps.google.com/maps/geo?q=' + urllib.quote(addr) + '&output=xml&oe=utf8&sensor=false'
         xml = urllib.urlopen(url).read()
-        if '<error>' in xml:
-            return None
-        result = re.search(regex, xml, re.M|re.I)
-        if not result:
-            return None
-        return float(result.group(2)),float(result.group(1))
     except Exception, e:
         raise osv.except_osv(_('Network error'),
                              _('Could not contact geolocation servers, please make sure you have a working internet connection (%s)') % e)
 
+    if '<error>' in xml:
+        return None
+    result = re.search(regex, xml, re.M|re.I)
+    if not result:
+        return None
+    return float(result.group(2)),float(result.group(1))
+    
 
 class res_partner_grade(osv.osv):
     _order = 'sequence'
@@ -74,9 +77,13 @@ class res_partner(osv.osv):
         for partner in self.browse(cr, uid, ids, context=context):
             if not partner.address:
                 continue
-            part = partner.address[0]
-            addr = ', '.join(filter(None, [part.street, (part.zip or '')+' '+(part.city or ''), part.state_id and part.state_id.name, part.country_id and part.country_id.name]))
-            result = geo_find(addr.encode('utf8'))
+            contact = partner.address[0] #TOFIX: should be get latitude and longitude for default contact?
+            addr = ', '.join(filter(None, [
+                    contact.street, 
+                    "%s %s" % (contact.zip , contact.city), 
+                    contact.state_id and contact.state_id.name, 
+                    contact.country_id and contact.country_id.name]))
+            result = geo_find(tools.ustr(addr))
             if result:
                 self.write(cr, uid, [partner.id], {
                     'partner_latitude': result[0],
@@ -94,14 +101,13 @@ class crm_lead(osv.osv):
         'partner_assigned_id': fields.many2one('res.partner', 'Assigned Partner', help="Partner this case has been forwarded/assigned to.", select=True),
         'date_assign': fields.date('Assignation Date', help="Last date this case was forwarded/assigned to a partner"),
     }
+    def _merge_data(self, cr, uid, ids, oldest, fields, context=None):
+        fields += ['partner_latitude', 'partner_longitude', 'partner_assigned_id', 'date_assign']
+        return super(crm_lead, self)._merge_data(cr, uid, ids, oldest, fields, context=context)
+
     def onchange_assign_id(self, cr, uid, ids, partner_assigned_id, context=None):
         """This function updates the "assignation date" automatically, when manually assign a partner in the geo assign tab
-            @param self: The object pointer
-            @param cr: the current row, from the database cursor,
-            @param uid: the current user’s ID for security checks,
-            @param ids: List of stage’s IDs
-            @stage_id: change state id on run time """
-
+        """
         if not partner_assigned_id:
             return {'value':{'date_assign': False}}
         else:
@@ -112,72 +118,102 @@ class crm_lead(osv.osv):
                          'user_id' : user_id}
                    }
 
-    def assign_partner(self, cr, uid, ids, context=None):
-        ok = False
-        for part in self.browse(cr, uid, ids, context=context):
-            if not part.country_id:
+    def assign_partner(self, cr, uid, ids, partner_id=None, context=None):
+        partner_ids = {}
+        res = False
+        if partner_id is None:
+            partner_ids = self.search_geo_partner(cr, uid, ids, context=context)
+        for lead in self.browse(cr, uid, ids, context=context):
+            if not partner_id:
+                partner_id = partner_ids.get(lead.id, False)
+            res = super(crm_lead, self).assign_partner(cr, uid, [lead.id], partner_id, context=context)
+            self.write(cr, uid, [lead.id], {'date_assign': time.strftime('%Y-%m-%d'), 'partner_assigned_id': partner_id}, context=context)
+        return res
+        
+
+    def assign_geo_localize(self, cr, uid, ids, latitude=False, longitude=False, context=None):
+        for lead in self.browse(cr, uid, ids, context=context):
+            if not lead.country_id:
                 continue
-            addr = ', '.join(filter(None, [part.street, (part.zip or '')+' '+(part.city or ''), part.state_id and part.state_id.name, part.country_id and part.country_id.name]))
-            result = geo_find(addr.encode('utf8'))
-            if result:
-                self.write(cr, uid, [part.id], {
-                    'partner_latitude': result[0],
-                    'partner_longitude': result[1]
-                }, context=context)
-
+            addr = ', '.join(filter(None, [
+                    lead.street, 
+                    "%s %s" % (lead.zip, lead.city), 
+                    lead.state_id and lead.state_id.name or '', 
+                    lead.country_id and lead.country_id.name or ''
+            ]))
+            result = geo_find(tools.ustr(addr))
+            if not latitude and result:
+                latitude = result[0]
+            if not longitude and result:
+                longitude = result[1]
+            self.write(cr, uid, [lead.id], {
+                'partner_latitude': latitude,
+                'partner_longitude': longitude
+            }, context=context)
+        return True
+        
+    def search_geo_partner(self, cr, uid, ids, context=None):
+        res_partner = self.pool.get('res.partner')
+        res_partner_ids = {}
+        self.assign_geo_localize(cr, uid, ids, context=context)
+        for lead in self.browse(cr, uid, ids, context=context):
+            partner_ids = []
+            if not lead.country_id:
+                continue
+            latitude = lead.partner_latitude
+            longitude = lead.partner_longitude
+            if latitude and longitude:
                 # 1. first way: in the same country, small area
-                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),
-                    ('country', '=', part.country_id.id),
+                partner_ids = res_partner.search(cr, uid, [
+                    ('partner_weight', '>', 0),
+                    ('partner_latitude', '>', latitude - 2), ('partner_latitude', '<', latitude + 2),
+                    ('partner_longitude', '>', longitude - 1.5), ('partner_longitude', '<', longitude + 1.5),
+                    ('country', '=', lead.country_id.id),
                 ], context=context)
 
                 # 2. second way: in the same country, 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),
-                        ('country', '=', part.country_id.id),
+                if not partner_ids:
+                    partner_ids = res_partner.search(cr, uid, [
+                        ('partner_weight', '>', 0),
+                        ('partner_latitude', '>', latitude - 4), ('partner_latitude', '<', latitude + 4),
+                        ('partner_longitude', '>', longitude - 3), ('partner_longitude', '<' , longitude + 3),
+                        ('country', '=', lead.country_id.id),
                     ], context=context)
 
 
                 # 5. fifth way: anywhere in same country
-                if not part_ids:
+                if not partner_ids:
                     # still haven't found any, let's take all partners in the country!
-                    part_ids = self.pool.get('res.partner').search(cr, uid, [
-                        ('partner_weight','>',0),
-                        ('country', '=', part.country_id.id),
+                    partner_ids = partner.search(cr, uid, [
+                        ('partner_weight', '>', 0),
+                        ('country', '=', lead.country_id.id),
                     ], context=context)
 
                 # 6. sixth way: closest partner whatsoever, just to have at least one result
-                if not part_ids:
+                if not partner_ids:
                     # warning: point() type takes (longitude, latitude) as parameters in this order!
                     cr.execute("""SELECT id, distance
                                   FROM  (select id, (point(partner_longitude, partner_latitude) <-> point(%s,%s)) AS distance FROM res_partner
                                   WHERE partner_longitude is not null
                                         AND partner_latitude is not null
                                         AND partner_weight > 0) AS d
-                                  ORDER BY distance LIMIT 1""", (result[1],result[0]))
+                                  ORDER BY distance LIMIT 1""", (longitude, latitude))
                     res = cr.dictfetchone()
                     if res:
-                        part_ids.append(res['id'])
+                        partner_ids.append(res['id'])
 
-                total = 0
+                total_weight = 0
                 toassign = []
-                for part2 in self.pool.get('res.partner').browse(cr, uid, part_ids, context=context):
-                    total += part2.partner_weight
-                    toassign.append( (part2.id, total) )
+                for partner in res_partner.browse(cr, uid, partner_ids, context=context):
+                    total_weight += partner.partner_weight
+                    toassign.append( (partner.id, total_weight) )
+
                 random.shuffle(toassign) # avoid always giving the leads to the first ones in db natural order!
-                mypartner = random.randint(0,total)
-                for t in toassign:
-                    if mypartner<=t[1]:
-                        vals = self.onchange_assign_id(cr,uid, ids, t[0], context=context)['value']
-                        vals.update({'partner_assigned_id': t[0], 'date_assign': time.strftime('%Y-%m-%d')})
-                        self.write(cr, uid, [part.id], vals, context=context)
+                nearest_weight = random.randint(0, total_weight)
+                for partner_id, weight in toassign:
+                    if nearest_weight <= weight:
+                        res_partner_ids[lead.id] = partner_id
                         break
-            ok = True
-        return ok
+        return res_partner_ids
 crm_lead()
 
diff --git a/addons/crm_partner_assign/res_partner_demo.xml b/addons/crm_partner_assign/res_partner_demo.xml
new file mode 100644 (file)
index 0000000..66ee1fb
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<openerp>
+    <data>
+        <record id="res_partner_grade_first" model="res.partner.grade">
+            <field name="name">First</field>
+            <field name="sequence">1</field>
+        </record>
+        <record id="base.res_partner_ericdubois0" model="res.partner">
+            <field name="grade_id" ref="res_partner_grade_first"/>
+            <field name="partner_weight">10</field>
+        </record>
+    </data>
+</openerp>
index 43c413f..01d771f 100644 (file)
@@ -1,58 +1,38 @@
 -
   In order to test find nearest Partner functionality and assign to opportunity ,
-  so First i create a grade 'First' for partner.
 -
-  !record {model: res.partner.grade, id: res_partner_grade_first}:
-    name: First
-    sequence: 1
+  I Set Geo Lattitude and Longitude according to partner address.
 -
-  I assign grade 'First' to the partner 'Eric' and give more probability to assign a lead to this partner.
--
-  !record {model: res.partner, id: base.res_partner_ericdubois0}:
-    grade_id: res_partner_grade_first
-    partner_weight: 10
+  !python {model: res.partner}: |
+    self.geo_localize(cr, uid, [ref('base.res_partner_ericdubois0')], context)
 -
-  Set Lattitude and Longitude according to partner address.
+ I check Geo Lattitude and Longitude of partner after set
 -
   !python {model: res.partner}: |
-    self.geo_localize(cr, uid, [ref('base.res_partner_ericdubois0')], context)
     partner = self.browse(cr, uid, ref('base.res_partner_ericdubois0'))
     assert partner.partner_latitude == 50.4530495 , "Lattitude is wrong"
     assert partner.partner_longitude == 3.9693885 , "Longitude is wrong"
 -
-  I would like to change the assign partner on opportunity, so find nearest partner assign to this opportunity.
+  I assign nearest partner to opportunity.
 -
   !python {model: crm.lead}: |
-    res = self.onchange_assign_id(cr, uid, [ref('crm.crm_case_abcfuelcounits0')], ref('base.res_partner_ericdubois0'), context)
-    assert res['value']['user_id'] == ref('base.user_demo'), "User not correct"
-    self.assign_partner(cr, uid, [ref('crm.crm_case_abcfuelcounits0')], context)
+    self.assign_partner(cr, uid, [ref('crm.crm_case_abcfuelcounits0')], context=context)
 -
-  In order to assigned partner to opportunity, so i test latitude and longitude of partner of opportunity
-  and opportuniy assign to assigned partner.
+  I check assigned partner of opportunity who is nearest Geo Lattitude and Longitude of opportunity.
 -
   !python {model: crm.lead}: |
-    lead = self.browse(cr, uid, [ref('crm.crm_case_abcfuelcounits0')])[0]
+    lead = self.browse(cr, uid, ref('crm.crm_case_abcfuelcounits0'))
+    assert lead.partner_assigned_id.id == ref('base.res_partner_ericdubois0') , "Opportuniy is not assigned nearest partner"
     assert lead.partner_latitude == 50.8495239 , "Lattitude is wrong"
     assert lead.partner_longitude == 4.3667002 , "Longitude is wrong"
-    assert lead.partner_assigned_id.id == ref('base.res_partner_ericdubois0') , "Opportuniy not assign partner"
--
-  Oppportuniry forword to its nearest partner, so first i create record of forword mail
--
-  !record {model: crm.lead.forward.to.partner, id: crm_lead_forward_to_partner_rec}:
-    send_to: email
-    email_from: 'admin@openerp.com'
-    email_to: 'admin@tinyerp.com'
-    subject: 'Openerp lead forward'
-    history: latest 
+    
 -
-  I forword this opportunity to its nearest partner.
+  I forward this opportunity to its nearest partner.
 -
   !python {model: crm.lead.forward.to.partner}: |
-    from tools import config
-    host = config.get('smtp_user', '127.0.0.1')
-    assert config.get(host, True), 'SMTP not configured !'
+    context.update({'active_model': 'crm.lead', 'active_id': ref('crm.crm_case_abcfuelcounits0'), 'active_ids': [ref('crm.crm_case_abcfuelcounits0')]})
+    forward_id = self.create(cr, uid, {'send_to': 'partner'}, context=context)
     try:
-      self.action_forward(cr, uid, ref("crm_lead_forward_to_partner_rec"), context={'active_id': ref('crm.crm_case_abcfuelcounits0'),
-      'active_ids': [ref('crm.crm_case_abcfuelcounits0')], 'active_model': 'crm.lead'})
+      self.action_forward(cr, uid, ref("crm_lead_forward_to_partner_rec"), context=context)
     except:
       pass
diff --git a/addons/crm_partner_assign/test/ui/partner_assign_form.yml b/addons/crm_partner_assign/test/ui/partner_assign_form.yml
deleted file mode 100644 (file)
index 747297a..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
--
-  For onchange on partner , i assign an email address to Administrator user.
--
-  !record {model: res.users, id: base.user_root}:
-    user_email: admin@openerp.com
-
--
-  I check onchange on email, partner, history and test the data accordingly change.
--
-  !python {model: crm.lead.forward.to.partner}: |
-    context.update({'history': 'latest', 'active_id': ref('crm.crm_case_abcfuelcounits0')})
-    email = self.on_change_email(cr, uid, [ref('crm.crm_case_abcfuelcounits0')], ref('base.user_root'))
-    assert email['value']['email_to'] == "Administrator <admin@openerp.com>", "Email is not correct"
-    partner = self.on_change_partner(cr, uid, [ref('crm.crm_case_abcfuelcounits0')], ref('base.res_partner_desertic_hispafuentes'))
-    assert partner['value']['address_id'] == ref('base.res_partner_desertic_hispafuentes'), "Address invalid"
-    assert partner['value']['email_to'] == 'info@axelor.com', "Email id incorrect"
-    history = self.on_change_history(cr, uid, [ref('crm.crm_case_abcfuelcounits0')], context.get('history'), context)
-    assert history, "History is blank"
\ No newline at end of file
index be6c153..9224173 100644 (file)
@@ -20,4 +20,3 @@
 ##############################################################################
 
 import crm_forward_to_partner
-import crm_merge_opportunity
index cdaf8f1..29a60ba 100644 (file)
@@ -24,6 +24,7 @@ import time
 import re
 from osv import osv, fields
 from tools.translate import _
+from mail.mail_message import to_email
 
 class crm_lead_forward_to_partner(osv.osv_memory):
     """Forwards lead history"""
@@ -46,48 +47,8 @@ class crm_lead_forward_to_partner(osv.osv_memory):
     }
 
 
-    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
-        @param cr: the current row, from the database cursor,
-        @param uid: the current user’s ID for security checks,
-        @param ids: List of history IDs
-        @param context: A standard dictionary for contextual values
-        """
-        whole = []
-        for hist_id in ids:
-            whole.append(self.get_latest_history(cr, uid, hist_id, context=context))
-        whole = '\n\n'.join(whole)
-        return whole or ''
-
-    def get_latest_history(self, cr, uid, hist_id, context=None):
-        """This function gets latest communication and returns as top posting style
-        @param self: The object pointer
-        @param cr: the current row, from the database cursor,
-        @param uid: the current user’s ID for security checks,
-        @param hist_id: Id of latest history
-        @param context: A standard dictionary for contextual values
-        """
-        log_pool = self.pool.get('mail.message')
-        hist = log_pool.browse(cr, uid, hist_id, context=context)
-        header = '-------- Original Message --------'
-        sender = 'From: %s' %(hist.email_from or '')
-        to = 'To: %s' % (hist.email_to or '')
-        sentdate = 'Date: %s' % (hist.date or '')
-        desc = '\n%s'%(hist.body_text)
-        original = [header, sender, to, sentdate, desc]
-        original = '\n'.join(original)
-        return original
-
+    
     def on_change_email(self, cr, uid, ids, user):
-        """This function fills email information based on user selected
-        @param self: The object pointer
-        @param cr: the current row, from the database cursor,
-        @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
-        """
         if not user:
             return {'value': {'email_to': False}}
         email = self.pool.get('res.users')._get_email_from(cr, uid, [user])[user]
@@ -98,54 +59,19 @@ class crm_lead_forward_to_partner(osv.osv_memory):
             * info: Forward the case information
             * whole: Send the whole history
             * latest: Send the latest histoy
-        @param self: The object pointer
-        @param cr: the current row, from the database cursor,
-        @param uid: the current user’s ID for security checks,
-        @param ids: List of history IDs
-        @param context: A standard dictionary for contextual values
         """
         #TODO: ids and context are not comming
-        res = False
+        res = {}
         res_id = context.get('active_id')
-        msg_val = self._get_case_history(cr, uid, history_type, res_id, context=context)
+        model = context.get('active_model')
+        body_text = self._get_body_text(cr, uid, model, res_id, history_type, context=context)
+        context['mail.compose.message.body'] = history_type
         if msg_val:
-            res = {'value': {'body_text' : '\n\n' + msg_val}}
+            res = {'value': {'body_text' : body_text}}
         return res
-
-    def _get_case_history(self, cr, uid, history_type, res_id, context=None):
-        if not res_id:
-            return
-
-        msg_val = ''
-        case_info = self.get_lead_details(cr, uid, res_id, context=context)
-        model_pool = self.pool.get('crm.lead')
-
-        if history_type == 'info':
-            msg_val = case_info
-
-        elif history_type == 'whole':
-            log_ids = model_pool.browse(cr, uid, res_id, context=context).message_ids
-            log_ids = map(lambda x: x.id, filter(lambda x: x.email_from, log_ids))
-            msg_val = case_info + '\n\n' + self.get_whole_history(cr, uid, log_ids, context=context)
-
-        elif history_type == 'latest':
-            log_ids = model_pool.browse(cr, uid, res_id, context=context).message_ids
-            log_ids = filter(lambda x: x.email_from and x.id, log_ids)
-            if not log_ids:
-                msg_val = case_info
-            else:
-                msg_val = case_info + '\n\n' + self.get_latest_history(cr, uid, log_ids[0].id, context=context)
-
-        return msg_val
-
+    
     def on_change_partner(self, cr, uid, ids, partner_id):
         """This function fills address information based on partner/user selected
-        @param self: The object pointer
-        @param cr: the current row, from the database cursor,
-        @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
         """
         if not partner_id:
             return {'value' : {'email_to' : False, 'address_id': False}}
@@ -158,11 +84,11 @@ class crm_lead_forward_to_partner(osv.osv_memory):
         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})
+        data.update({'email_cc' : email, 'user_id': user_id and user_id.id or False})
         return {
             'value' : data,
             'domain' : {'address_id' : partner_id and "[('partner_id', '=', partner_id)]" or "[]"}
-            }
+        }
 
     def on_change_address(self, cr, uid, ids, address_id):
         email = ''
@@ -170,155 +96,126 @@ class crm_lead_forward_to_partner(osv.osv_memory):
             email = self.pool.get('res.partner.address').browse(cr, uid, address_id).email
         return {'value': {'email_to' : email}}
 
-    def send_mail(self, cr, uid, ids, context=None):
-        if context is None:
-            context = {}
-        super(crm_lead_forward_to_partner, self).send_mail(cr, uid, ids, context=context)
-        self.action_forward(cr, uid, ids, context)
-        return {'type': 'ir.actions.act_window_close'}
-
     def action_forward(self, cr, uid, ids, context=None):
         """
         Forward the lead to a partner
         """
         if context is None:
             context = {}
-        this = self.browse(cr, uid, ids[0], context=context)
-        case_pool = self.pool.get(context.get('active_model'))
-        res_id = context and context.get('active_id', False) or False
-        case = case_pool.browse(cr, uid, res_id, context=context)
-        context.update({'mail': 'forward'})
-
-        to_write = {'date_assign': time.strftime('%Y-%m-%d')}
-        if (this.send_to == 'partner' and this.partner_id):
-            to_write['partner_assigned_id'] = this.partner_id.id
-
-        if this.send_to == 'user':
-            to_write.update({'user_id' : this.user_id.id})
-        email_re = r'([^ ,<@]+@[^> ,]+)'
-        email_cc = re.findall(email_re, case.email_cc or '')
-        new_cc = []
-        if case.email_cc:
-            new_cc.append(case.email_cc)
-        for to in this.email_to.split(','):
-            email_to = re.findall(email_re, to)
-            email_to = email_to and email_to[0] or ''
-            if email_to not in email_cc:
-                new_cc.append(to)
-        to_write.update({'email_cc' : ', '.join(new_cc) })
-        case_pool.write(cr, uid, case.id, to_write, context=context)
-        return {'type': 'ir.actions.act_window_close'}
+        res = {'type': 'ir.actions.act_window_close'}
+        model = context.get('active_model')
+        if model not in ('crm.lead'):
+            return res
 
-    def get_lead_details(self, cr, uid, lead_id, context=None):
-        body = []
-        lead_proxy = self.pool.get('crm.lead')
-        lead = lead_proxy.browse(cr, uid, lead_id, context=context)
-        if not lead.type or lead.type == 'lead' or not lead.partner_address_id:
-                field_names = [
-                    'partner_name', 'title', 'function', 'street', 'street2',
-                    'zip', 'city', 'country_id', 'state_id', 'email_from',
-                    'phone', 'fax', 'mobile', 'categ_id', 'description',
-                ]
-
-                for field_name in field_names:
-                    field_definition = lead_proxy._columns[field_name]
-                    value = None
-
-                    if field_definition._type == 'selection':
-                        if hasattr(field_definition.selection, '__call__'):
-                            key = field_definition.selection(lead_proxy, cr, uid, context=context)
-                        else:
-                            key = field_definition.selection
-                        value = dict(key).get(lead[field_name], lead[field_name])
-                    elif field_definition._type == 'many2one':
-                        if lead[field_name]:
-                            value = lead[field_name].name_get()[0][1]
-                    else:
-                        value = lead[field_name]
-
-                    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 ''),
-            ]
-        return "\n".join(body + ['---'])
+        this = self.browse(cr, uid, ids[0], context=context)
+        lead = self.pool.get(model)
+        lead_id = context and context.get('active_id', False) or False
+        lead_ids = lead_id and [lead_id] or []
+        mode = context.get('mail.compose.message.mode')
+        if mode == 'mass_mail':
+            lead_ids = context and context.get('active_ids', []) or []
+            value = self.default_get(cr, uid, ['body_text', 'email_to', 'email_cc', 'subject', 'history'], context=context)
+            self.write(cr, uid, ids, value, context=context)
+            context['mail.compose.message.mode'] = mode
+
+        self.send_mail(cr, uid, ids, context=context)
+        for case in lead.browse(cr, uid, lead_ids, context=context):
+            if (this.send_to == 'partner' and this.partner_id):
+                lead.assign_partner(cr, uid, [case.id], this.partner_id.id, context=context)
+
+            if this.send_to == 'user':
+                lead.assign_salesman(cr, uid, [case.id], [this.user_id.id], context=context)
+
+            email_cc = to_email(case.email_cc)
+            email_cc = email_to and email_cc[0] or ''
+            new_cc = []
+            if email_cc:
+                new_cc.append(email_cc)
+            for to in this.email_to.split(','):
+                email_to = to_email(to)
+                email_to = email_to and email_to[0] or ''
+                if email_to not in new_cc:
+                    new_cc.append(to)
+            update_vals = {'email_cc' : ', '.join(new_cc) }
+            lead.write(cr, uid, case.id, update_vals, context=context)
+        return res
 
-    def default_get(self, cr, uid, fields, context=None):
-        """
-        This function gets default values
+    def _get_info_body_text(self, cr, uid, lead, context=None):
+        field_names = []
+        proxy = self.pool.get(lead._name)
+        if lead.type == 'opportunity':
+            field_names += ['partner_id']
+        field_names += [
+           'partner_name' , 'title', 'function', 'street', 'street2',
+            'zip', 'city', 'country_id', 'state_id', 'email_from',
+            'phone', 'fax', 'mobile', 'categ_id', 'description',
+        ]
+        return proxy._mail_body_text(cr, uid, lead, field_names, context=context)
+
+    def _get_message_body_text(self, cr, uid, lead, mode='whole', context=None):
+        """This function gets whole communication history and returns as top posting style
         """
-
+        mail_message = self.pool.get('mail.message')
+        message_ids = []
+        body = self._get_info_body_text(cr, uid, lead, context=context)
+        if mode in ('whole', 'latest'):
+            message_ids = lead.message_ids
+            message_ids = map(lambda x: x.id, filter(lambda x: x.email_from, message_ids))
+            if mode == 'latest' and len(message_ids):
+                message_ids = [message_ids[0]]
+            for message in mail_message.browse(cr, uid, message_ids, context=context):
+                header = '-------- Original Message --------'
+                sender = 'From: %s' %(message.email_from or '')
+                to = 'To: %s' % (message.email_to or '')
+                sentdate = 'Date: %s' % (message.date or '')
+                desc = '\n%s'%(message.body_text)
+                original = [header, sender, to, sentdate, desc]
+                original = '\n'.join(original)
+                body += original
+        return body or ''
+
+    def get_value(self, cr, uid, model, res_id, context=None):
         if context is None:
             context = {}
+        res = super(crm_lead_forward_to_partner, self).get_value(cr, uid,  model, res_id, context=context)
+        if model not in ("crm.lead"):
+            return res
+        proxy = self.pool.get(model)
+        partner = self.pool.get('res.partner')
+        lead = proxy.browse(cr, uid, res_id, context=context)
+        mode = context.get('mail.compose.message.mode')
+        if mode == "forward":
+            body_type = context.get('mail.compose.message.body')
+            email_cc = res.get('email_cc', "")
+            email = res.get('email_to', "")
+            subject = '%s: %s - %s' % (_('Fwd'), 'Lead forward', lead.name)
+            body = self._get_message_body_text(cr, uid, lead, body_type, context=context)
+            partner_assigned_id = lead.partner_assigned_id and lead.partner_assigned_id.id or False
+            user_id = False
+            if not partner_assigned_id:
+                partner_assigned_id = lead.search_geo_partner(cr, uid, [lead.id], context=None).get(lead.id, False)
+            if partner_assigned_id:
+                assigned_partner = partner.browse(cr, uid, partner_assigned_id, context=context)
+                user_id = assigned_partner.user_id and assigned_partner.user_id.id or False
+                email_cc = assigned_partner.user_id and assigned_partner.user_id.user_email or ''
+                email = assigned_partner.email
+            
+            
+            res.update({
+                'subject' : subject,
+                'body_text' : body,
+                'email_cc' : email_cc,
+                'email_to' : email,
+                'partner_assigned_id': partner_assigned_id,
+                'user_id': user_id,
+            })
+        return res
+        
 
-        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 - %s' % (_('Fwd'), 'Openerp lead forward', lead.name),
-            'body_text' : body,
-            'email_cc' : email_cc,
-            'email_to' : email or 'dummy@dummy.ly'
-        })
-        return defaults
-
-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:
+    def default_get(self, cr, uid, fields, context=None):
+        if context is None:
             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_text', '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'}
-
-
+        context['mail.compose.message.mode'] = 'forward'
+        context['mail.compose.message.body'] = 'info'
+        return super(crm_lead_forward_to_partner, self).default_get(cr, uid, fields, context=context)
 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
index aa2c45e..645c729 100644 (file)
@@ -45,7 +45,7 @@
                     <group col="4" colspan="4">
                         <label string="" colspan="1"/>
                         <button icon="gtk-close" special="cancel" string="Close"/>
-                        <button icon="gtk-ok" name="send_mail" string="Send" type="object"/>
+                        <button name="action_forward" string="Send" type="object" icon="gtk-go-forward"/>
                     </group>
                 </form>
             </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_text" 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"
+            res_model="crm.lead.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"
+            context="{'mail.compose.message.mode' : 'mass_mail'}"
+            view_id="crm_lead_forward_to_partner_form"
         />
 
 
diff --git a/addons/crm_partner_assign/wizard/crm_merge_opportunity.py b/addons/crm_partner_assign/wizard/crm_merge_opportunity.py
deleted file mode 100644 (file)
index 3993a5d..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-# -*- 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 osv, fields
-from tools.translate import _
-
-
-class crm_merge_opportunity_assign_partner(osv.osv_memory):
-    """Merge two Opportunities"""
-
-    _inherit = 'crm.merge.opportunity'
-    
-    def _update_data(self, op_ids, oldest_opp):
-               data = super(crm_merge_opportunity_assign_partner, self)._update_data(op_ids, oldest_opp)
-                       
-               new_data = {
-                       'partner_latitude': self._get_first_not_null('partner_latitude', op_ids, oldest_opp),
-                       'partner_longitude': self._get_first_not_null('partner_longitude', op_ids, oldest_opp),
-                       'partner_assigned_id': self._get_first_not_null_id('partner_assigned_id', op_ids, oldest_opp), 
-                       'date_assign' : self._get_first_not_null('date_assign', op_ids, oldest_opp),
-               }
-               data.update(new_data)
-               return data
-
-crm_merge_opportunity_assign_partner()