@@ -207,63 +207,64 @@ class invite_attendee_wizard(osv.osv_memory):
|
||||
}
|
||||
|
||||
def do_invite(self, cr, uid, ids, context={}):
|
||||
datas = self.read(cr, uid, ids)[0]
|
||||
model = False
|
||||
model_field = False
|
||||
if not context or not context.get('model'):
|
||||
return {}
|
||||
else:
|
||||
model = context.get('model')
|
||||
model_field = context.get('attendee_field', False)
|
||||
obj = self.pool.get(model)
|
||||
res_obj = obj.browse(cr, uid, context['active_id'])
|
||||
type = datas.get('type')
|
||||
att_obj = self.pool.get('calendar.attendee')
|
||||
vals = {}
|
||||
mail_to = []
|
||||
if not model == 'calendar.attendee':
|
||||
vals = {'ref': '%s,%s' % (model, base_calendar_id2real_id(context['active_id']))}
|
||||
|
||||
if type == 'internal':
|
||||
user_obj = self.pool.get('res.users')
|
||||
for user_id in datas.get('user_ids', []):
|
||||
user = user_obj.browse(cr, uid, user_id)
|
||||
vals.update({'user_id': user_id,
|
||||
'email': user.address_id.email})
|
||||
if user.address_id.email:
|
||||
mail_to.append(user.address_id.email)
|
||||
|
||||
elif type == 'external' and datas.get('email'):
|
||||
vals.update({'email': datas['email']})
|
||||
mail_to.append(datas['email'])
|
||||
elif type == 'partner':
|
||||
add_obj = self.pool.get('res.partner.address')
|
||||
for contact in add_obj.browse(cr, uid, datas['contact_ids']):
|
||||
for att_id in ids:
|
||||
datas = self.read(cr, uid, att_id)
|
||||
model = False
|
||||
model_field = False
|
||||
if not context or not context.get('model'):
|
||||
return {}
|
||||
else:
|
||||
model = context.get('model')
|
||||
model_field = context.get('attendee_field', False)
|
||||
obj = self.pool.get(model)
|
||||
res_obj = obj.browse(cr, uid, context['active_id'])
|
||||
type = datas.get('type')
|
||||
att_obj = self.pool.get('calendar.attendee')
|
||||
vals = {}
|
||||
mail_to = []
|
||||
if not model == 'calendar.attendee':
|
||||
vals = {'ref': '%s,%s' % (model, base_calendar_id2real_id(context['active_id']))}
|
||||
|
||||
if type == 'internal':
|
||||
user_obj = self.pool.get('res.users')
|
||||
if not datas.get('user_ids'):
|
||||
raise osv.except_osv(_('Error!'), ("Please select any User"))
|
||||
for user_id in datas.get('user_ids'):
|
||||
user = user_obj.browse(cr, uid, user_id)
|
||||
vals.update({'user_id': user_id,
|
||||
'email': user.address_id.email})
|
||||
if user.address_id.email:
|
||||
mail_to.append(user.address_id.email)
|
||||
|
||||
elif type == 'external' and datas.get('email'):
|
||||
vals.update({'email': datas['email']})
|
||||
mail_to.append(datas['email'])
|
||||
elif type == 'partner':
|
||||
add_obj = self.pool.get('res.partner.address')
|
||||
for contact in add_obj.browse(cr, uid, datas['contact_ids']):
|
||||
vals.update({
|
||||
'partner_address_id': contact.id,
|
||||
'email': contact.email})
|
||||
if contact.email:
|
||||
mail_to.append(contact.email)
|
||||
|
||||
if model == 'calendar.attendee':
|
||||
att = att_obj.browse(cr, uid, context['active_id'])
|
||||
vals.update({
|
||||
'partner_address_id': contact.id,
|
||||
'email': contact.email})
|
||||
if contact.email:
|
||||
mail_to.append(contact.email)
|
||||
|
||||
if model == 'calendar.attendee':
|
||||
att = att_obj.browse(cr, uid, context['active_id'])
|
||||
vals.update({
|
||||
'parent_ids' : [(4, att.id)],
|
||||
'ref': att.ref
|
||||
})
|
||||
att_id = att_obj.create(cr, uid, vals)
|
||||
if model_field:
|
||||
obj.write(cr, uid, res_obj.id, {model_field: [(4, att_id)]})
|
||||
|
||||
if datas.get('send_mail'):
|
||||
if not mail_to:
|
||||
name = map(lambda x: x[1], filter(lambda x: type==x[0], \
|
||||
self._columns['type'].selection))
|
||||
raise osv.except_osv(_('Error!'), ("%s must have an email \
|
||||
Address to send mail") % (name[0]))
|
||||
att_obj._send_mail(cr, uid, [att_id], mail_to, \
|
||||
email_from=tools.config.get('email_from', False))
|
||||
|
||||
'parent_ids' : [(4, att.id)],
|
||||
'ref': att.ref
|
||||
})
|
||||
if datas.get('send_mail'):
|
||||
if not mail_to:
|
||||
name = map(lambda x: x[1], filter(lambda x: type==x[0], \
|
||||
self._columns['type'].selection))
|
||||
raise osv.except_osv(_('Error!'), ("%s must have an email \
|
||||
Address to send mail") % (name[0]))
|
||||
att_obj._send_mail(cr, uid, [att_id], mail_to, \
|
||||
email_from=tools.config.get('email_from', False))
|
||||
att_id = att_obj.create(cr, uid, vals)
|
||||
if model_field:
|
||||
obj.write(cr, uid, res_obj.id, {model_field: [(4, att_id)]})
|
||||
return {}
|
||||
|
||||
|
||||
@@ -313,12 +314,14 @@ class calendar_attendee(osv.osv):
|
||||
if name == 'delegated_to':
|
||||
todata = []
|
||||
for parent in attdata.parent_ids:
|
||||
todata.append('MAILTO:' + parent.email)
|
||||
if parent.email:
|
||||
todata.append('MAILTO:' + parent.email)
|
||||
result[id][name] = ', '.join(todata)
|
||||
if name == 'delegated_from':
|
||||
fromdata = []
|
||||
for child in attdata.child_ids:
|
||||
fromdata.append('MAILTO:' + child.email)
|
||||
if child.email:
|
||||
fromdata.append('MAILTO:' + child.email)
|
||||
result[id][name] = ', '.join(fromdata)
|
||||
if name == 'event_date':
|
||||
if attdata.ref:
|
||||
@@ -481,18 +484,20 @@ request was delegated to"),
|
||||
self.write(cr, uid, ids, {'state': 'tentative'}, context)
|
||||
|
||||
def do_accept(self, cr, uid, ids, context=None, *args):
|
||||
vals = self.read(cr, uid, ids, context=context)[0]
|
||||
user = vals.get('user_id')
|
||||
if user:
|
||||
ref = vals.get('ref', None)
|
||||
if ref:
|
||||
model, event = ref.split(',')
|
||||
model_obj = self.pool.get(model)
|
||||
event_ref = model_obj.browse(cr, uid, event, context=context)[0]
|
||||
if event_ref.user_id.id != user[0]:
|
||||
defaults = {'user_id': user[0]}
|
||||
new_event = model_obj.copy(cr, uid, event, default=defaults, context=context)
|
||||
self.write(cr, uid, ids, {'state': 'accepted'}, context)
|
||||
for invite in ids:
|
||||
vals = self.read(cr, uid, invite, context=context)
|
||||
user = vals.get('user_id')
|
||||
if user:
|
||||
ref = vals.get('ref', None)
|
||||
if ref:
|
||||
model, event = ref.split(',')
|
||||
model_obj = self.pool.get(model)
|
||||
event_ref = model_obj.browse(cr, uid, event, context=context)[0]
|
||||
if event_ref.user_id.id != user[0]:
|
||||
defaults = {'user_id': user[0]}
|
||||
new_event = model_obj.copy(cr, uid, event, default=defaults, context=context)
|
||||
self.write(cr, uid, invite, {'state': 'accepted'}, context)
|
||||
return True
|
||||
|
||||
def do_decline(self, cr, uid, ids, context=None, *args):
|
||||
self.write(cr, uid, ids, {'state': 'declined'}, context)
|
||||
@@ -729,7 +734,7 @@ class calendar_event(osv.osv):
|
||||
def _get_rulestring(self, cr, uid, ids, name, arg, context=None):
|
||||
result = {}
|
||||
for event in ids:
|
||||
datas = self.read(cr, uid, ids)[0]
|
||||
datas = self.read(cr, uid, event)
|
||||
if datas.get('rrule_type'):
|
||||
if datas.get('rrule_type') == 'none':
|
||||
result[event] = False
|
||||
@@ -811,9 +816,9 @@ rule or repeating pattern for anexception to a recurrence set"),
|
||||
'interval': lambda *x: 1,
|
||||
}
|
||||
|
||||
def modify_this(self, cr, uid, ids, defaults, real_date, context=None, *args):
|
||||
ids = map(lambda x: base_calendar_id2real_id(x), ids)
|
||||
datas = self.read(cr, uid, ids[0], context=context)
|
||||
def modify_this(self, cr, uid, event_id, defaults, real_date, context=None, *args):
|
||||
event_id = base_calendar_id2real_id(event_id)
|
||||
datas = self.read(cr, uid, event_id, context=context)
|
||||
defaults.update({
|
||||
'recurrent_uid': base_calendar_id2real_id(datas['id']),
|
||||
'recurrent_id': defaults.get('date') or real_date,
|
||||
@@ -823,12 +828,12 @@ rule or repeating pattern for anexception to a recurrence set"),
|
||||
exdate = datas['exdate'] and datas['exdate'].split(',') or []
|
||||
if real_date and defaults.get('date'):
|
||||
exdate.append(real_date)
|
||||
self.write(cr, uid, ids, {'exdate': ','.join(exdate)}, context=context)
|
||||
new_id = self.copy(cr, uid, ids[0], default=defaults, context=context)
|
||||
self.write(cr, uid, event_id, {'exdate': ','.join(exdate)}, context=context)
|
||||
new_id = self.copy(cr, uid, event_id, default=defaults, context=context)
|
||||
return new_id
|
||||
|
||||
def modify_all(self, cr, uid, ids, defaults, context=None, *args):
|
||||
ids = map(lambda x: base_calendar_id2real_id(x), ids)
|
||||
def modify_all(self, cr, uid, event_id, defaults, context=None, *args):
|
||||
event_id = base_calendar_id2real_id(event_id)
|
||||
defaults.pop('id')
|
||||
defaults.update({'table': self._table})
|
||||
|
||||
@@ -838,7 +843,7 @@ rule or repeating pattern for anexception to a recurrence set"),
|
||||
qry += ", alarm_id=%(alarm_id)s"
|
||||
if defaults.get('location'):
|
||||
qry += ", location='%(location)s'"
|
||||
qry += "WHERE id=%s" % (ids[0])
|
||||
qry += "WHERE id=%s" % (event_id)
|
||||
cr.execute(qry % (defaults))
|
||||
return True
|
||||
|
||||
@@ -984,23 +989,26 @@ rule or repeating pattern for anexception to a recurrence set"),
|
||||
else:
|
||||
select = ids
|
||||
new_ids = []
|
||||
for id in select:
|
||||
if len(str(id).split('-')) > 1:
|
||||
data = self.read(cr, uid, id, ['date', 'date_deadline', 'rrule', 'duration'])
|
||||
for event_id in select:
|
||||
if len(str(event_id).split('-')) > 1:
|
||||
data = self.read(cr, uid, event_id, ['date', 'date_deadline', \
|
||||
'rrule', 'duration'])
|
||||
if data.get('rrule'):
|
||||
real_date = data.get('date')
|
||||
data.update(vals)
|
||||
new_id = self.modify_this(cr, uid, [id], data, real_date, context)
|
||||
new_id = self.modify_this(cr, uid, event_id, data, \
|
||||
real_date, context)
|
||||
context.update({'active_id': new_id,'active_ids': [new_id]})
|
||||
continue
|
||||
id = base_calendar_id2real_id(id)
|
||||
if not id in new_ids:
|
||||
new_ids.append(id)
|
||||
event_id = base_calendar_id2real_id(event_id)
|
||||
if not event_id in new_ids:
|
||||
new_ids.append(event_id)
|
||||
res = super(calendar_event, self).write(cr, uid, new_ids, vals, context=context)
|
||||
if vals.has_key('alarm_id') or vals.has_key('base_calendar_alarm_id'):
|
||||
alarm_obj = self.pool.get('res.alarm')
|
||||
context.update({'alarm_id': vals.get('alarm_id')})
|
||||
alarm_obj.do_alarm_create(cr, uid, new_ids, self._name, 'date', context=context)
|
||||
alarm_obj.do_alarm_create(cr, uid, new_ids, self._name, 'date', \
|
||||
context=context)
|
||||
return res
|
||||
|
||||
def browse(self, cr, uid, ids, context=None, list_class=None, fields_process={}):
|
||||
@@ -1009,7 +1017,8 @@ rule or repeating pattern for anexception to a recurrence set"),
|
||||
else:
|
||||
select = ids
|
||||
select = map(lambda x: base_calendar_id2real_id(x), select)
|
||||
res = super(calendar_event, self).browse(cr, uid, select, context, list_class, fields_process)
|
||||
res = super(calendar_event, self).browse(cr, uid, select, context, \
|
||||
list_class, fields_process)
|
||||
if isinstance(ids, (str, int, long)):
|
||||
return res and res[0] or False
|
||||
return res
|
||||
@@ -1057,7 +1066,8 @@ rule or repeating pattern for anexception to a recurrence set"),
|
||||
res = self.write(cr, uid, [base_calendar_id2real_id(id)], {'exdate': exdate})
|
||||
else:
|
||||
ids = map(lambda x: base_calendar_id2real_id(x), ids)
|
||||
res = super(calendar_event, self).unlink(cr, uid, base_calendar_id2real_id(ids))
|
||||
res = super(calendar_event, self).unlink(cr, uid, \
|
||||
base_calendar_id2real_id(ids))
|
||||
alarm_obj = self.pool.get('res.alarm')
|
||||
alarm_obj.do_alarm_unlink(cr, uid, ids, self._name)
|
||||
else:
|
||||
@@ -1094,7 +1104,7 @@ class calendar_todo(osv.osv):
|
||||
|
||||
_columns = {
|
||||
'date': fields.function(_get_date, method=True, fnct_inv=_set_date, \
|
||||
string='Duration', store=True, type='datetime'),
|
||||
string='Duration', store=True, type='datetime'),
|
||||
'duration': fields.integer('Duration'),
|
||||
}
|
||||
|
||||
@@ -1216,3 +1226,4 @@ class res_users(osv.osv):
|
||||
res_users()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
||||
@@ -55,10 +55,10 @@ class event_edit_all(wizard.interface):
|
||||
})
|
||||
return event
|
||||
|
||||
def _modify_this(self, cr, uid, datas, context=None):
|
||||
def _modify_all(self, cr, uid, datas, context=None):
|
||||
model = datas.get('model')
|
||||
model_obj = pooler.get_pool(cr.dbname).get(model)
|
||||
model_obj.modify_all(cr, uid, [datas['id']], datas['form'], context)
|
||||
model_obj.modify_all(cr, uid, datas['id'], datas['form'], context)
|
||||
return {}
|
||||
|
||||
states = {
|
||||
@@ -69,7 +69,7 @@ class event_edit_all(wizard.interface):
|
||||
},
|
||||
'edit': {
|
||||
'actions': [],
|
||||
'result': {'type': 'action', 'action': _modify_this, 'state': 'end'}
|
||||
'result': {'type': 'action', 'action': _modify_all, 'state': 'end'}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ This module implements a dashboard for salesman that includes:
|
||||
* Graph of cases of the month
|
||||
""",
|
||||
'author': 'Tiny',
|
||||
'depends': ['board', 'sale', 'report_crm', 'report_sale'],
|
||||
'depends': ['board', 'sale'],
|
||||
'update_xml': ['board_sale_view.xml'],
|
||||
'demo_xml': ['board_sale_demo.xml'],
|
||||
'installable': True,
|
||||
|
||||
@@ -33,15 +33,11 @@
|
||||
<child1>
|
||||
<action colspan="4" height="200" name="%(sale.action_order_tree5)d" string="My quotations" width="510" domain="[('state','=','draft'),('user_id','=',uid)]"/>
|
||||
<action colspan="4" name="%(board_crm_case_categ_phone_incoming0)d" string="My planned calling calls (IN / OUT)" width="510"/>
|
||||
<!-- <action colspan="4" name="%(report_sale.action_order_sale_list)d" string="Top ten sales of the month"/>-->
|
||||
<!-- <action colspan="4" name="%(report_crm.action_report_crm_case_user_tree)d" string="Cases statistics"/>-->
|
||||
</child1>
|
||||
|
||||
<child2>
|
||||
<action colspan="4" name="%(crm.crm_case_category_act_oppor11)d" string="My Opportunities" width="510" domain="[('user_id','=',uid)]"/>
|
||||
<action colspan="4" name="%(board_crm_case_categ_meet)d" String="My Meetings" domain="[('state','=','open')]" width="510"/>
|
||||
<!-- <action colspan="4" name="%(report_sale.action_order_category_tree_all)d" string="Average Sales by Category of Products(this month)" view_mode="graph,tree"/>-->
|
||||
<!-- <action colspan="4" name="%(report_crm.action_report_crm_case_user_tree)d" string="Cases of the month" view_mode="graph,tree"/>-->
|
||||
</child2>
|
||||
</hpaned>
|
||||
</form>
|
||||
|
||||
@@ -27,8 +27,20 @@
|
||||
"base",
|
||||
],
|
||||
'description': """
|
||||
Contains basic functionality for caldav system like:
|
||||
- Availabilities of synchronisation using WebDAV
|
||||
This module Contains basic functionality for caldav system like:
|
||||
- Webdav server that provides remote access to calendar
|
||||
- Synchronisation of calendar using WebDAV
|
||||
- Customize calendar event and todo attribute with any of OpenERP model
|
||||
- Provides iCal Import/Export functionality
|
||||
|
||||
To access OpenERP Calendar using caldav to remote site use the URL like:
|
||||
http://HOSTNAME:PORT/calendar/DATABASE_NAME/CALENDAR_NAME.ics
|
||||
|
||||
Where,
|
||||
HOSTNAME: Host on which OpenERP server(With webdav) is running
|
||||
PORT : Port on which OpenERP server is running (By Default : 8069)
|
||||
DATABASE_NAME: Name of database on which OpenERP Calendar is created
|
||||
CALENDAR_NAME: Name of calendar to access
|
||||
""",
|
||||
"author" : "Tiny",
|
||||
'category': 'Generic Modules/Others',
|
||||
|
||||
@@ -124,7 +124,6 @@
|
||||
<field name="arch" type="xml">
|
||||
<tree string="CRM Cases">
|
||||
<field name="create_date" select="1"/>
|
||||
<field name="date" select="1"/>
|
||||
<field name="date_deadline"/>
|
||||
<field name="name" select="1"/>
|
||||
<field name="user_id" select="2"/>
|
||||
@@ -139,7 +138,6 @@
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="CRM Cases">
|
||||
<field name="date"/>
|
||||
<field name="name"/>
|
||||
<field name="user_id" select="2"/>
|
||||
<field name="state" />
|
||||
|
||||
@@ -29,24 +29,17 @@ import os
|
||||
import binascii
|
||||
import time, socket
|
||||
|
||||
email_re = re.compile(r"""
|
||||
([a-zA-Z][\w\.-]*[a-zA-Z0-9] # username part
|
||||
@ # mandatory @ sign
|
||||
[a-zA-Z0-9][\w\.-]* # domain must start with a letter ... Ged> why do we include a 0-9 then?
|
||||
\.
|
||||
[a-z]{2,3} # TLD
|
||||
)
|
||||
""", re.VERBOSE)
|
||||
email_re = re.compile(r"[a-zA-Z][\w\.-]*[a-zA-Z0-9]@[a-zA-Z0-9][\w\.-]*\.[a-z]{2,3}", re.VERBOSE)
|
||||
case_re = re.compile(r"\[([0-9]+)\]", re.UNICODE)
|
||||
command_re = re.compile("^Set-([a-z]+) *: *(.+)$", re.I + re.UNICODE)
|
||||
reference_re = re.compile("<.*-tinycrm-(\\d+)@(.*)>", re.UNICODE)
|
||||
|
||||
priorities = {
|
||||
'1': '1 (Highest)',
|
||||
'2': '2 (High)',
|
||||
'3': '3 (Normal)',
|
||||
'4': '4 (Low)',
|
||||
'5': '5 (Lowest)',
|
||||
'1': '1 (Highest)',
|
||||
'2': '2 (High)',
|
||||
'3': '3 (Normal)',
|
||||
'4': '4 (Low)',
|
||||
'5': '5 (Lowest)',
|
||||
}
|
||||
|
||||
def html2plaintext(html, body_id=None, encoding='utf-8'):
|
||||
@@ -88,18 +81,18 @@ def html2plaintext(html, body_id=None, encoding='utf-8'):
|
||||
html = html.replace(d['tag'], '%s [%s]' % (d['title'], i))
|
||||
url_index.append(d['url'])
|
||||
|
||||
html = html.replace('<strong>','*').replace('</strong>','*')
|
||||
html = html.replace('<b>','*').replace('</b>','*')
|
||||
html = html.replace('<h3>','*').replace('</h3>','*')
|
||||
html = html.replace('<h2>','**').replace('</h2>','**')
|
||||
html = html.replace('<h1>','**').replace('</h1>','**')
|
||||
html = html.replace('<em>','/').replace('</em>','/')
|
||||
html = html.replace('<strong>', '*').replace('</strong>', '*')
|
||||
html = html.replace('<b>', '*').replace('</b>', '*')
|
||||
html = html.replace('<h3>', '*').replace('</h3>', '*')
|
||||
html = html.replace('<h2>', '**').replace('</h2>', '**')
|
||||
html = html.replace('<h1>', '**').replace('</h1>', '**')
|
||||
html = html.replace('<em>', '/').replace('</em>', '/')
|
||||
|
||||
|
||||
# the only line breaks we respect is those of ending tags and
|
||||
# breaks
|
||||
|
||||
html = html.replace('\n',' ')
|
||||
html = html.replace('\n', ' ')
|
||||
html = html.replace('<br>', '\n')
|
||||
html = html.replace('<tr>', '\n')
|
||||
html = html.replace('</p>', '\n\n')
|
||||
@@ -135,12 +128,14 @@ class rpc_proxy(object):
|
||||
return self.rpc.execute(self.dbname, self.user_id, self.passwd, *request)
|
||||
|
||||
class email_parser(object):
|
||||
def __init__(self, uid, password, section, email, email_default, dbname, host, port):
|
||||
def __init__(self, uid, password, model, email, email_default, dbname, host, port):
|
||||
self.rpc = rpc_proxy(uid, password, host=host, port=port, dbname=dbname)
|
||||
try:
|
||||
self.section_id = int(section)
|
||||
self.model_id = int(model)
|
||||
self.model = str(model)
|
||||
except:
|
||||
self.section_id = self.rpc('crm.case.section', 'search', [('code','=',section)])[0]
|
||||
self.model_id = self.rpc('ir.model', 'search', [('model', '=', model)])[0]
|
||||
self.model = str(model)
|
||||
self.email = email
|
||||
self.email_default = email_default
|
||||
self.canal_id = False
|
||||
@@ -156,8 +151,8 @@ class email_parser(object):
|
||||
return {}
|
||||
adr = self.rpc('res.partner.address', 'read', adr_ids, ['partner_id'])
|
||||
return {
|
||||
'partner_address_id': adr[0]['id'],
|
||||
'partner_id': adr[0].get('partner_id',False) and adr[0]['partner_id'][0] or False
|
||||
'partner_address_id': adr[0]['id'],
|
||||
'partner_id': adr[0].get('partner_id', False) and adr[0]['partner_id'][0] or False
|
||||
}
|
||||
|
||||
def _decode_header(self, s):
|
||||
@@ -168,14 +163,13 @@ class email_parser(object):
|
||||
def msg_new(self, msg):
|
||||
message = self.msg_body_get(msg)
|
||||
data = {
|
||||
'name': self._decode_header(msg['Subject']),
|
||||
'section_id': self.section_id,
|
||||
'email_from': self._decode_header(msg['From']),
|
||||
'email_cc': self._decode_header(msg['Cc'] or ''),
|
||||
'canal_id': self.canal_id,
|
||||
'user_id': False,
|
||||
'description': message['body'],
|
||||
'history_line': [(0, 0, {'description': message['body'], 'email': msg['From'] })],
|
||||
'name': self._decode_header(msg['Subject']),
|
||||
'email_from': self._decode_header(msg['From']),
|
||||
'email_cc': self._decode_header(msg['Cc'] or ''),
|
||||
'canal_id': self.canal_id,
|
||||
'user_id': False,
|
||||
'description': message['body'],
|
||||
'history_line': [(0, 0, {'description': message['body'], 'email': msg['From'] })],
|
||||
}
|
||||
try:
|
||||
data.update(self.partner_get(self._decode_header(msg['From'])))
|
||||
@@ -184,21 +178,21 @@ class email_parser(object):
|
||||
netsvc.Logger().notifyChannel('mailgate', netsvc.LOG_ERROR, "%s" % e)
|
||||
|
||||
try:
|
||||
id = self.rpc('crm.case', 'create', data)
|
||||
self.rpc('crm.case','case_open', [id])
|
||||
except Exception,e:
|
||||
if getattr(e,'faultCode','') and 'AccessError' in e.faultCode:
|
||||
id = self.rpc(self.model, 'create', data)
|
||||
self.rpc(self.model, 'case_open', [id])
|
||||
except Exception, e:
|
||||
if getattr(e, 'faultCode', '') and 'AccessError' in e.faultCode:
|
||||
e = '\n\nThe Specified user does not have an access to the CRM case.'
|
||||
print e
|
||||
attachments = message['attachment']
|
||||
|
||||
for attach in attachments or []:
|
||||
data_attach = {
|
||||
'name': str(attach),
|
||||
'datas':binascii.b2a_base64(str(attachments[attach])),
|
||||
'datas_fname': str(attach),
|
||||
'description': 'Mail attachment',
|
||||
'res_model': 'crm.case',
|
||||
'name': str(attach),
|
||||
'datas': binascii.b2a_base64(str(attachments[attach])),
|
||||
'datas_fname': str(attach),
|
||||
'description': 'Mail attachment',
|
||||
'res_model': self.model,
|
||||
'res_id': id
|
||||
}
|
||||
self.rpc('ir.attachment', 'create', data_attach)
|
||||
@@ -273,22 +267,22 @@ class email_parser(object):
|
||||
body['body'] = body_data
|
||||
|
||||
data = {
|
||||
'description': body['body'],
|
||||
'history_line': [(0, 0, {'description': body['body'], 'email': msg['From']})],
|
||||
'description': body['body'],
|
||||
'history_line': [(0, 0, {'description': body['body'], 'email': msg['From']})],
|
||||
}
|
||||
act = 'case_pending'
|
||||
if 'state' in actions:
|
||||
if actions['state'] in ['draft','close','cancel','open','pending']:
|
||||
if actions['state'] in ['draft', 'close', 'cancel', 'open', 'pending']:
|
||||
act = 'case_' + actions['state']
|
||||
|
||||
for k1,k2 in [('cost','planned_cost'),('revenue','planned_revenue'),('probability','probability')]:
|
||||
for k1, k2 in [('cost', 'planned_cost'), ('revenue', 'planned_revenue'), ('probability', 'probability')]:
|
||||
try:
|
||||
data[k2] = float(actions[k1])
|
||||
except:
|
||||
pass
|
||||
|
||||
if 'priority' in actions:
|
||||
if actions['priority'] in ('1','2','3','4','5'):
|
||||
if actions['priority'] in ('1', '2', '3', '4', '5'):
|
||||
data['priority'] = actions['priority']
|
||||
|
||||
if 'partner' in actions:
|
||||
@@ -299,8 +293,8 @@ class email_parser(object):
|
||||
if uids:
|
||||
data['user_id'] = uids[0][0]
|
||||
|
||||
self.rpc('crm.case', act, [id])
|
||||
self.rpc('crm.case', 'write', [id], data)
|
||||
self.rpc(self.model, act, [id])
|
||||
self.rpc(self.model, 'write', [id], data)
|
||||
return id
|
||||
|
||||
def msg_send(self, msg, emails, priority=None):
|
||||
@@ -326,19 +320,19 @@ class email_parser(object):
|
||||
message = self.msg_body_get(msg)
|
||||
body = message['body']
|
||||
act = 'case_open'
|
||||
self.rpc('crm.case', act, [id])
|
||||
self.rpc(self.model, act, [id])
|
||||
body2 = '\n'.join(map(lambda l: '> '+l, (body or '').split('\n')))
|
||||
data = {
|
||||
'description':body,
|
||||
'history_line': [(0, 0, {'description': body, 'email': msg['From'][:84]})],
|
||||
'description':body,
|
||||
'history_line': [(0, 0, {'description': body, 'email': msg['From'][:84]})],
|
||||
}
|
||||
self.rpc('crm.case', 'write', [id], data)
|
||||
self.rpc(self.model, 'write', [id], data)
|
||||
return id
|
||||
|
||||
def msg_test(self, msg, case_str):
|
||||
if not case_str:
|
||||
return (False, False)
|
||||
emails = self.rpc('crm.case', 'emails_get', int(case_str))
|
||||
emails = self.rpc(self.model, 'emails_get', int(case_str))
|
||||
return (int(case_str), emails)
|
||||
|
||||
def parse(self, msg):
|
||||
@@ -363,12 +357,12 @@ class email_parser(object):
|
||||
msg['Subject'] = '['+str(case_id)+'] '+subject
|
||||
msg['Message-Id'] = '<'+str(time.time())+'-tinycrm-'+str(case_id)+'@'+socket.gethostname()+'>'
|
||||
|
||||
emails = self.rpc('crm.case', 'emails_get', case_id)
|
||||
emails = self.rpc(self.model, 'emails_get', case_id)
|
||||
priority = emails[3]
|
||||
em = [emails[0], emails[1]] + (emails[2] or '').split(',')
|
||||
emails = map(self.email_get, filter(None, em))
|
||||
|
||||
mm = [self._decode_header(msg['From']), self._decode_header(msg['To'])]+self._decode_header(msg.get('Cc','')).split(',')
|
||||
mm = [self._decode_header(msg['From']), self._decode_header(msg['To'])]+self._decode_header(msg.get('Cc', '')).split(',')
|
||||
msg_mails = map(self.email_get, filter(None, mm))
|
||||
|
||||
emails = filter(lambda m: m and m not in msg_mails, emails)
|
||||
@@ -385,10 +379,9 @@ class email_parser(object):
|
||||
if __name__ == '__main__':
|
||||
import sys, optparse
|
||||
parser = optparse.OptionParser(
|
||||
usage='usage: %prog [options]',
|
||||
usage='usage: %prog [options]',
|
||||
version='%prog v1.0')
|
||||
|
||||
group = optparse.OptionGroup(parser, "Note",
|
||||
group = optparse.OptionGroup(parser, "Note",
|
||||
"This program parse a mail from standard input and communicate "
|
||||
"with the Open ERP server for case management in the CRM module.")
|
||||
parser.add_option_group(group)
|
||||
@@ -396,7 +389,7 @@ if __name__ == '__main__':
|
||||
parser.add_option("-u", "--user", dest="userid", help="ID of the user in Open ERP", default=1, type='int')
|
||||
parser.add_option("-p", "--password", dest="password", help="Password of the user in Open ERP", default='admin')
|
||||
parser.add_option("-e", "--email", dest="email", help="Email address used in the From field of outgoing messages")
|
||||
parser.add_option("-s", "--section", dest="section", help="ID or code of the case section", default="support")
|
||||
parser.add_option("-o", "--model", dest="model", help="Name or ID of crm model", default="crm.lead")
|
||||
parser.add_option("-m", "--default", dest="default", help="Default eMail in case of any trouble.", default=None)
|
||||
parser.add_option("-d", "--dbname", dest="dbname", help="Database name (default: terp)", default='terp')
|
||||
parser.add_option("--host", dest="host", help="Hostname of the Open ERP Server", default="localhost")
|
||||
@@ -404,15 +397,14 @@ if __name__ == '__main__':
|
||||
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
parser = email_parser(options.userid, options.password, options.section, options.email, options.default, dbname=options.dbname, host=options.host, port=options.port)
|
||||
parser = email_parser(options.userid, options.password, options.model, options.email, options.default, dbname=options.dbname, host=options.host, port=options.port)
|
||||
|
||||
msg_txt = email.message_from_file(sys.stdin)
|
||||
|
||||
try :
|
||||
parser.parse(msg_txt)
|
||||
except Exception,e:
|
||||
if getattr(e,'faultCode','') and 'Connection unexpectedly closed' in e.faultCode:
|
||||
except Exception, e:
|
||||
if getattr(e, 'faultCode', '') and 'Connection unexpectedly closed' in e.faultCode:
|
||||
print e
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
||||
@@ -31,3 +31,5 @@
|
||||
"access_crm_lead_report_user","crm.lead.report","model_crm_lead_report","crm.group_crm_user",1,0,0,0
|
||||
"access_crm_phonecall_report_user","crm.phonecall.report","model_crm_phonecall_report","crm.group_crm_user",1,0,0,0
|
||||
"access_crm_opportunity_report_user","crm.opportunity.report","model_crm_opportunity_report","crm.group_crm_user",1,0,0,0
|
||||
"access_report_crm_case_service_dashboard","report.crm.case.service.dashboard","model_report_crm_case_service_dashboard","crm.group_crm_user",1,0,0,0
|
||||
|
||||
|
||||
|
@@ -23,7 +23,7 @@
|
||||
|
||||
<record model="document.directory.ics.fields" id="dir_field1">
|
||||
<field name="name">dtstart</field>
|
||||
<field name="field_id" ref="crm.field_crm_case_date"/>
|
||||
<field name="field_id" ref="crm.field_crm_case_create_date"/>
|
||||
<field name="content_id" ref="dir_content_calendar"/>
|
||||
</record>
|
||||
<record model="document.directory.ics.fields" id="dir_field6">
|
||||
|
||||
@@ -8,3 +8,5 @@
|
||||
"access_hr_contract_user","hr.contract user","model_hr_contract","hr.group_hr_user",1,0,0,0
|
||||
"access_hr_contract","hr.contract","model_hr_contract","group_hr_contract",1,1,1,1
|
||||
"access_hr_employee_contract","hr.employee contract","hr.model_hr_employee","group_hr_contract",1,0,0,0
|
||||
"access_hr_contract_type_user","hr.contract.type user","model_hr_contract_type","hr.group_hr_user",1,0,0,0
|
||||
"access_hr_contract_type","hr.contract.type","model_hr_contract_type","group_hr_contract",1,1,1,1
|
||||
|
||||
|
@@ -52,7 +52,7 @@
|
||||
'l10n_be_wizard.xml',
|
||||
'l10n_be_sequence.xml',
|
||||
'fiscal_templates.xml',
|
||||
#'security/ir.model.access.csv'
|
||||
'security/ir.model.access.csv'
|
||||
],
|
||||
'demo_xml': [
|
||||
'account.report.report.csv'
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
|
||||
"access_vat_listing_clients","vat.listing.clients","model_vat_listing_clients",,1,1,1,1
|
||||
|
@@ -48,8 +48,8 @@ class bvr_checkbox(osv.osv):
|
||||
""" Add function to generate function """
|
||||
_inherit = "res.partner.bank"
|
||||
_columns = {
|
||||
'printBank' : fields.boolean('Print Bank on BVR'),
|
||||
'printAccount' : fields.boolean('Print Account Number on BVR'),
|
||||
'print_bank' : fields.boolean('Print Bank on BVR'),
|
||||
'print_account' : fields.boolean('Print Account Number on BVR'),
|
||||
}
|
||||
bvr_checkbox()
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
<field name="inherit_id" ref="base.view_partner_bank_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="country_id" position="after">
|
||||
<field name="printBank" select="2"/>
|
||||
<field name="printAccount" select="2"/>
|
||||
<field name="print_bank" select="2"/>
|
||||
<field name="print_account" select="2"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
@@ -45,8 +45,8 @@
|
||||
<field name="arch" type="xml">
|
||||
<field name="bank" position="after">
|
||||
<newline />
|
||||
<field name="printBank" select="2"/>
|
||||
<field name="printAccount" select="2"/>
|
||||
<field name="print_bank" select="2"/>
|
||||
<field name="print_account" select="2"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -24,30 +24,36 @@
|
||||
<!-- Company -->
|
||||
<record id="base.main_company" model="res.company">
|
||||
<field name="name">OpenERP Corp.</field>
|
||||
<field name="currency_id" ref="base.EUR"/>
|
||||
</record>
|
||||
<record id="res_company_oerp_editor" model="res.company">
|
||||
<field name="partner_id" ref="res_partner_oerp_editor"/>
|
||||
<field name="parent_id" ref="base.main_company"/>
|
||||
<field name="currency_id" ref="base.EUR"/>
|
||||
<field name="name">OpenERP Editor</field>
|
||||
</record>
|
||||
<record id="res_company_oerp_us" model="res.company">
|
||||
<field name="partner_id" ref="res_partner_oerp_us"/>
|
||||
<field name="parent_id" ref="res_company_oerp_editor"/>
|
||||
<field name="currency_id" ref="base.EUR"/>
|
||||
<field name="name">OpenERP US</field>
|
||||
</record>
|
||||
<record id="res_company_oerp_be" model="res.company">
|
||||
<field name="partner_id" ref="res_partner_oerp_be"/>
|
||||
<field name="parent_id" ref="res_company_oerp_editor"/>
|
||||
<field name="currency_id" ref="base.EUR"/>
|
||||
<field name="name">OpenERP BE</field>
|
||||
</record>OpenERP IN
|
||||
</record>
|
||||
<record id="res_company_oerp_in" model="res.company">
|
||||
<field name="partner_id" ref="res_partner_oerp_in"/>
|
||||
<field name="parent_id" ref="res_company_oerp_editor"/>
|
||||
<field name="currency_id" ref="base.EUR"/>
|
||||
<field name="name">OpenERP IN</field>
|
||||
</record>
|
||||
<record id="res_company_odoo" model="res.company">
|
||||
<field name="partner_id" ref="res_partner_odoo"/>
|
||||
<field name="parent_id" ref="base.main_company"/>
|
||||
<field name="currency_id" ref="base.EUR"/>
|
||||
<field name="name">Odoo</field>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
"category" : "Generic Modules/Thunderbird interface",
|
||||
"init_xml" : [],
|
||||
"demo_xml" : [],
|
||||
"update_xml" : [],
|
||||
"update_xml" : ['security/ir.model.access.csv'],
|
||||
"active": False,
|
||||
"installable": True
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
|
||||
"access_tinythunderbird_partner","tinythunderbird.partner","model_tinythunderbird_partner",,1,1,1,1
|
||||
|
||||
|
Reference in New Issue
Block a user