[MRG] merge with lp:openobject-addons
bzr revid: tpa@tinyerp.com-20130531050544-n51h4w32mqdbok79
This commit is contained in:
@@ -13,6 +13,7 @@ from openerp.tools import mute_logger
|
||||
# Validation Library https://pypi.python.org/pypi/validate_email/1.1
|
||||
from .validate_email import validate_email
|
||||
|
||||
import openerp
|
||||
from openerp.osv import osv, orm
|
||||
from openerp.osv import fields
|
||||
from openerp.osv.orm import browse_record
|
||||
@@ -101,14 +102,26 @@ class MergePartnerAutomatic(osv.TransientModel):
|
||||
'current_line_id': fields.many2one('base.partner.merge.line', 'Current Line'),
|
||||
'line_ids': fields.one2many('base.partner.merge.line', 'wizard_id', 'Lines'),
|
||||
'partner_ids': fields.many2many('res.partner', string='Contacts'),
|
||||
'dst_partner_id': fields.many2one('res.partner', string='Destination Contact'),
|
||||
|
||||
'exclude_contact': fields.boolean('A user associated to the contact'),
|
||||
'exclude_journal_item': fields.boolean('Journal Items associated to the contact'),
|
||||
'maximum_group': fields.integer("Maximum of Group of Contacts"),
|
||||
}
|
||||
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
res = super(MergePartnerAutomatic, self).default_get(cr, uid, fields, context)
|
||||
if context.get('active_model') == 'res.partner' and context.get('active_ids'):
|
||||
partner_ids = context['active_ids']
|
||||
res['state'] = 'selection'
|
||||
res['partner_ids'] = partner_ids
|
||||
res['dst_partner_id'] = self._get_ordered_partner(cr, uid, partner_ids, context=context)[-1].id
|
||||
return res
|
||||
|
||||
_defaults = {
|
||||
'state': 'option',
|
||||
'state': 'option'
|
||||
}
|
||||
|
||||
def get_fk_on(self, cr, table):
|
||||
@@ -204,8 +217,8 @@ class MergePartnerAutomatic(osv.TransientModel):
|
||||
if proxy is None:
|
||||
return
|
||||
domain = [(field_model, '=', 'res.partner'), (field_id, '=', src.id)]
|
||||
ids = proxy.search(cr, uid, domain, context=context)
|
||||
return proxy.write(cr, uid, ids, {field_id: dst_partner.id}, context=context)
|
||||
ids = proxy.search(cr, openerp.SUPERUSER_ID, domain, context=context)
|
||||
return proxy.write(cr, openerp.SUPERUSER_ID, ids, {field_id: dst_partner.id}, context=context)
|
||||
|
||||
update_records = functools.partial(update_records, context=context)
|
||||
|
||||
@@ -219,9 +232,9 @@ class MergePartnerAutomatic(osv.TransientModel):
|
||||
|
||||
proxy = self.pool['ir.model.fields']
|
||||
domain = [('ttype', '=', 'reference')]
|
||||
record_ids = proxy.search(cr, uid, domain, context=context)
|
||||
record_ids = proxy.search(cr, openerp.SUPERUSER_ID, domain, context=context)
|
||||
|
||||
for record in proxy.browse(cr, uid, record_ids, context=context):
|
||||
for record in proxy.browse(cr, openerp.SUPERUSER_ID, record_ids, context=context):
|
||||
proxy_model = self.pool[record.model]
|
||||
|
||||
field_type = proxy_model._columns.get(record.name).__class__._type
|
||||
@@ -233,11 +246,11 @@ class MergePartnerAutomatic(osv.TransientModel):
|
||||
domain = [
|
||||
(record.name, '=', 'res.partner,%d' % partner.id)
|
||||
]
|
||||
model_ids = proxy_model.search(cr, uid, domain, context=context)
|
||||
model_ids = proxy_model.search(cr, openerp.SUPERUSER_ID, domain, context=context)
|
||||
values = {
|
||||
record.name: 'res.partner,%d' % dst_partner.id,
|
||||
}
|
||||
proxy_model.write(cr, uid, model_ids, values, context=context)
|
||||
proxy_model.write(cr, openerp.SUPERUSER_ID, model_ids, values, context=context)
|
||||
|
||||
def _update_values(self, cr, uid, src_partners, dst_partner, context=None):
|
||||
_logger.debug('_update_values for dst_partner: %s for src_partners: %r', dst_partner.id, list(map(operator.attrgetter('id'), src_partners)))
|
||||
@@ -266,22 +279,31 @@ class MergePartnerAutomatic(osv.TransientModel):
|
||||
_logger.info('Skip recursive partner hierarchies for parent_id %s of partner: %s', parent_id, dst_partner.id)
|
||||
|
||||
@mute_logger('openerp.osv.expression', 'openerp.osv.orm')
|
||||
def _merge(self, cr, uid, partner_ids, context=None):
|
||||
def _merge(self, cr, uid, partner_ids, dst_partner=None, context=None):
|
||||
proxy = self.pool.get('res.partner')
|
||||
|
||||
partner_ids = proxy.exists(cr, uid, list(partner_ids), context=context)
|
||||
if len(partner_ids) < 2:
|
||||
return
|
||||
|
||||
partners = proxy.browse(cr, uid, list(partner_ids), context=context)
|
||||
ordered_partners = sorted(sorted(partners,
|
||||
key=operator.attrgetter('create_date'), reverse=True),
|
||||
key=operator.attrgetter('active'), reverse=True)
|
||||
if len(partner_ids) > 3:
|
||||
raise osv.except_osv(_('Error'), _("For safety reasons, you cannot merge more than 3 contacts together. You can re-open the wizard several times if needed."))
|
||||
|
||||
dst_partner = ordered_partners[-1]
|
||||
src_partners = ordered_partners[:-1]
|
||||
if openerp.SUPERUSER_ID != uid and len(set(partner.email for partner in proxy.browse(cr, uid, partner_ids, context=context))) > 1:
|
||||
raise osv.except_osv(_('Error'), _("All contacts must have the same email. Only the Administrator can merge contacts with different emails."))
|
||||
|
||||
if dst_partner and dst_partner.id in partner_ids:
|
||||
src_partners = proxy.browse(cr, uid, [id for id in partner_ids if id != dst_partner.id], context=context)
|
||||
else:
|
||||
ordered_partners = self._get_ordered_partner(cr, uid, partner_ids, context)
|
||||
dst_partner = ordered_partners[-1]
|
||||
src_partners = ordered_partners[:-1]
|
||||
_logger.info("dst_partner: %s", dst_partner.id)
|
||||
|
||||
if openerp.SUPERUSER_ID != uid and self._model_is_installed(cr, uid, 'account.move.line', context=context) and \
|
||||
self.pool.get('account.move.line').search(cr, openerp.SUPERUSER_ID, [('partner_id', 'in', [partner.id for partner in src_partners])], context=context):
|
||||
raise osv.except_osv(_('Error'), _("Only the destination contact may be linked to existing Journal Items. Please ask the Administrator if you need to merge several contacts linked to existing Journal Items."))
|
||||
|
||||
call_it = lambda function: function(cr, uid, src_partners, dst_partner,
|
||||
context=context)
|
||||
|
||||
@@ -289,12 +311,12 @@ class MergePartnerAutomatic(osv.TransientModel):
|
||||
call_it(self._update_reference_fields)
|
||||
call_it(self._update_values)
|
||||
|
||||
_logger.info("---merged---")
|
||||
|
||||
_logger.info('(uid = %s) merged the partners %r with %s', uid, list(map(operator.attrgetter('id'), src_partners)), dst_partner.id)
|
||||
dst_partner.message_post(body='%s %s'%(_("Merged with the following partners:"), ", ".join('%s<%s>(ID %s)' % (p.name, p.email or 'n/a', p.id) for p in src_partners)))
|
||||
|
||||
for partner in src_partners:
|
||||
partner.unlink()
|
||||
|
||||
|
||||
def clean_emails(self, cr, uid, context=None):
|
||||
"""
|
||||
Clean the email address of the partner, if there is an email field with
|
||||
@@ -414,9 +436,16 @@ class MergePartnerAutomatic(osv.TransientModel):
|
||||
this = self.browse(cr, uid, ids[0], context=context)
|
||||
if this.current_line_id:
|
||||
this.current_line_id.unlink()
|
||||
return self._next_screen(this)
|
||||
return self._next_screen(cr, uid, this, context)
|
||||
|
||||
def _next_screen(self, this):
|
||||
def _get_ordered_partner(self, cr, uid, partner_ids, context=None):
|
||||
partners = self.pool.get('res.partner').browse(cr, uid, list(partner_ids), context=context)
|
||||
ordered_partners = sorted(sorted(partners,
|
||||
key=operator.attrgetter('create_date'), reverse=True),
|
||||
key=operator.attrgetter('active'), reverse=True)
|
||||
return ordered_partners
|
||||
|
||||
def _next_screen(self, cr, uid, this, context=None):
|
||||
this.refresh()
|
||||
values = {}
|
||||
if this.line_ids:
|
||||
@@ -426,6 +455,7 @@ class MergePartnerAutomatic(osv.TransientModel):
|
||||
values.update({
|
||||
'current_line_id': current_line.id,
|
||||
'partner_ids': [(6, 0, current_partner_ids)],
|
||||
'dst_partner_id': self._get_ordered_partner(cr, uid, current_partner_ids, context)[-1].id,
|
||||
'state': 'selection',
|
||||
})
|
||||
else:
|
||||
@@ -525,7 +555,7 @@ class MergePartnerAutomatic(osv.TransientModel):
|
||||
query = self._generate_query(groups, this.maximum_group)
|
||||
self._process_query(cr, uid, ids, query, context=context)
|
||||
|
||||
return self._next_screen(this)
|
||||
return self._next_screen(cr, uid, this, context)
|
||||
|
||||
def automatic_process_cb(self, cr, uid, ids, context=None):
|
||||
assert is_integer_list(ids)
|
||||
@@ -666,7 +696,7 @@ class MergePartnerAutomatic(osv.TransientModel):
|
||||
# p1.parent_id = p1.id
|
||||
# """)
|
||||
|
||||
return self._next_screen(this)
|
||||
return self._next_screen(cr, uid, this, context)
|
||||
|
||||
def merge_cb(self, cr, uid, ids, context=None):
|
||||
assert is_integer_list(ids)
|
||||
@@ -685,33 +715,12 @@ class MergePartnerAutomatic(osv.TransientModel):
|
||||
'target': 'new',
|
||||
}
|
||||
|
||||
self._merge(cr, uid, partner_ids, context=context)
|
||||
self._merge(cr, uid, partner_ids, this.dst_partner_id, context=context)
|
||||
|
||||
this.current_line_id.unlink()
|
||||
if this.current_line_id:
|
||||
this.current_line_id.unlink()
|
||||
|
||||
return self._next_screen(this)
|
||||
|
||||
def merge_multi(self, cr, uid, ids, context=None):
|
||||
|
||||
active_model = context.get('active_model')
|
||||
if active_model != 'res.partner':
|
||||
raise osv.except_osv(
|
||||
_('Error'),
|
||||
_('This wizard can only used with the Partners')
|
||||
)
|
||||
|
||||
partner_ids = context.get('active_ids', [])
|
||||
|
||||
MINIMAL_NUMBER = 2
|
||||
if len(partner_ids) < MINIMAL_NUMBER:
|
||||
raise osv.except_osv(
|
||||
_('Error'),
|
||||
_("You can't use this wizard with only one Partner")
|
||||
)
|
||||
|
||||
self._merge(cr, uid, partner_ids, context=context)
|
||||
|
||||
return True
|
||||
return self._next_screen(cr, uid, this, context)
|
||||
|
||||
def auto_set_parent_id(self, cr, uid, ids, context=None):
|
||||
assert is_integer_list(ids)
|
||||
|
||||
@@ -68,9 +68,9 @@
|
||||
OpenERP will propose you to merge only those having
|
||||
all these fields in common. (not one of the fields).
|
||||
</p>
|
||||
<group attrs="{'invisible': [('state', 'not in', ('selection', 'finished'))]}">
|
||||
<group attrs="{'invisible': ['|', ('state', 'not in', ('selection', 'finished')), ('number_group', '=', 0)]}">
|
||||
<field name="state" invisible="1" />
|
||||
<field name="number_group" invisible="0" />
|
||||
<field name="number_group"/>
|
||||
</group>
|
||||
<group string="Search duplicates based on duplicated data in"
|
||||
attrs="{'invisible': [('state', 'not in', ('option',))]}">
|
||||
@@ -98,15 +98,15 @@
|
||||
redirected to the aggregated contact. You can remove
|
||||
contacts from this list to avoid merging them.
|
||||
</p>
|
||||
<field name="dst_partner_id" domain="[('id', 'in', partner_ids and partner_ids[0] and partner_ids[0][2] or False)]" attrs="{'required': [('state', '=', 'selection')]}"/>
|
||||
<field name="partner_ids" nolabel="1">
|
||||
<tree string="Partners">
|
||||
<field name="id" />
|
||||
<field name="name" />
|
||||
<field name="display_name" />
|
||||
<field name="email" />
|
||||
<field name="is_company" />
|
||||
<field name="vat" />
|
||||
<field name="country_id" />
|
||||
<field name="parent_id" />
|
||||
</tree>
|
||||
</field>
|
||||
</group>
|
||||
@@ -114,24 +114,9 @@
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.server"
|
||||
id="ir_actions_server_merge_automatic">
|
||||
<field name="code">pool.get('base.partner.merge.automatic.wizard').merge_multi(cr, uid, None, context)</field>
|
||||
<field name="condition">True</field>
|
||||
<field name="model_id" ref="base.model_res_partner" />
|
||||
<field name="name">Automatic Merge</field>
|
||||
<field name="sequence" eval="5" />
|
||||
<field name="state">code</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.values" id="ir_open_merge_automatic">
|
||||
<field name="key2" eval="'client_action_multi'" />
|
||||
<field name="model">res.partner</field>
|
||||
<field name="name">Automatic Merge</field>
|
||||
<field name="value" eval="'ir.actions.server,%d' % ir_actions_server_merge_automatic" />
|
||||
</record>
|
||||
|
||||
<act_window id="action_partner_merge" res_model="base.partner.merge.automatic.wizard" src_model="res.partner"
|
||||
target="new" multi="True" key2="client_action_multi" view_mode="form" name="Automatic Merge"/>
|
||||
|
||||
</data>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<field name="res_model">event.registration</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="name">Registrations</field>
|
||||
<field name="view_mode">calendar,tree,form,graph</field>
|
||||
<field name="view_mode">tree,form,calendar,graph</field>
|
||||
<field name="context">{'search_default_event_id': active_id, 'default_event_id': active_id}</field>
|
||||
</record>
|
||||
|
||||
@@ -101,19 +101,13 @@
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Email Configuration" groups="base.group_no_one">
|
||||
<group>
|
||||
<page string="Event Details" groups="base.group_no_one">
|
||||
<group colspan="4">
|
||||
<field name="reply_to"/>
|
||||
<group>
|
||||
<field name="email_registration_id"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="email_confirmation_id"/>
|
||||
</group>
|
||||
<field name="email_registration_id"/>
|
||||
<field name="email_confirmation_id"/>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Event Description">
|
||||
<field name="note" colspan="4" nolabel="1"/>
|
||||
<field name="note" nolabel="1" placeholder="Event Description..."/>
|
||||
</page>
|
||||
<page string="Registrations">
|
||||
<group>
|
||||
|
||||
@@ -70,6 +70,8 @@ class sale_order_line(osv.osv):
|
||||
'''
|
||||
create registration with sales order
|
||||
'''
|
||||
if context is None:
|
||||
context = {}
|
||||
registration_obj = self.pool.get('event.registration')
|
||||
sale_obj = self.pool.get('sale.order')
|
||||
for order_line in self.browse(cr, uid, ids, context=context):
|
||||
@@ -83,7 +85,8 @@ class sale_order_line(osv.osv):
|
||||
'origin': order_line.order_id.name,
|
||||
'event_id': order_line.event_id.id,
|
||||
}
|
||||
message = _("The registration has been created for event <i>%s</i> from the Sale Order %s. ") % (order_line.event_id.name, order_line.order_id.name)
|
||||
context.update({'mail_create_nolog': True, 'message': message })
|
||||
registration_id = registration_obj.create(cr, uid, dic, context=context)
|
||||
message = _("The registration %s has been created from the Sales Order %s.") % (registration_id, order_line.order_id.name)
|
||||
registration_obj.message_post(cr, uid, [registration_id], body=message, context=context)
|
||||
return super(sale_order_line, self).button_confirm(cr, uid, ids, context=context)
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
|
||||
{
|
||||
'name': 'Timesheets',
|
||||
'name': 'Time Tracking',
|
||||
'version': '1.0',
|
||||
'category': 'Human Resources',
|
||||
'sequence': 23,
|
||||
|
||||
@@ -6,6 +6,11 @@
|
||||
<field name="model">mail.mail</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Email message" version="7.0">
|
||||
<header>
|
||||
<button name="send" string="Send Now" type="object" states='outgoing' class="oe_highlight"/>
|
||||
<button name="mark_outgoing" string="Retry" type="object" states='exception,cancel'/>
|
||||
<button name="cancel" string="Cancel" type="object" states='outgoing'/>
|
||||
</header>
|
||||
<sheet>
|
||||
<label for="subject" class="oe_edit_only"/>
|
||||
<h2><field name="subject"/></h2>
|
||||
|
||||
Reference in New Issue
Block a user