bzr revid: sbh@tinyerp.com-20100109052755-n3ro01zfwclk94dd
This commit is contained in:
sbh (Open ERP) 2010-01-09 10:57:55 +05:30
commit 6daf68b56b
32 changed files with 1109 additions and 569 deletions

View File

@ -236,7 +236,7 @@ class account_invoice(osv.osv):
'reference': fields.char('Invoice Reference', size=64, help="The partner reference of this invoice."),
'reference_type': fields.selection(_get_reference_type, 'Reference Type',
required=True),
'comment': fields.text('Additional Information'),
'comment': fields.text('Additional Information', translate=True),
'state': fields.selection([
('draft','Draft'),
@ -1093,7 +1093,7 @@ class account_invoice_line(osv.osv):
'quantity': fields.float('Quantity', required=True),
'discount': fields.float('Discount (%)', digits=(16, int(config['price_accuracy']))),
'invoice_line_tax_id': fields.many2many('account.tax', 'account_invoice_line_tax', 'invoice_line_id', 'tax_id', 'Taxes', domain=[('parent_id','=',False)]),
'note': fields.text('Notes'),
'note': fields.text('Notes', translate=True),
'account_analytic_id': fields.many2one('account.analytic.account', 'Analytic Account'),
'company_id': fields.related('invoice_id','company_id',type='many2one',relation='res.company',string='Company',store=True)
}

View File

@ -9,17 +9,35 @@
<field name="model">caldav.invite.attendee</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Invite Attendees">
<separator string="Select User" colspan="4"/>
<newline/>
<field name="user_id" select="1" on_change="onchange_user_id(user_id)"/>
<field name="email" />
<field name="role" select="1" />
<field name="rsvp" />
<form string="Invite Attendees">
<separator string="Atendee details" colspan="4"/>
<field name="attendee_ids" mode="tree,form" nolabel="1" widget="one2many_list" colspan="4">
<form string="Attendee details">
<field name="user_id" on_change="onchange_user_id(user_id)" />
<field name="availability" />
<field name="email" select="1"/>
<newline />
<field name="role" select="1" />
<field name="cutype" select="1" />
<newline />
<field name="rsvp" />
</form>
<tree string="Attendee details" editable="bottom">
<field name="user_id" on_change="onchange_user_id(user_id)" />
<field name="availability" />
<field name="email" select="1"/>
<field name="role" select="1" />
<field name="cutype" select="1" />
<field name="language" />
<field name="rsvp" />
</tree>
</field>
<separator string="" colspan="6" />
<label string="" colspan="2"/>
<button icon='gtk-cancel' special="cancel" string="Cancel"/>
<button name="do_invite" string="Invite" type="object" icon="gtk-ok"/>
<button string="Invite"
name="do_invite"
icon="gtk-ok" type="object" />
</form>
</field>
</record>
@ -39,24 +57,32 @@
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Atendee details">
<field name="user_id" on_change="onchange_user_id(user_id)" />
<field name="email" select="1"/>
<field name="user_id"
on_change="onchange_user_id(user_id)" readonly="1" />
<field name="email" select="1" readonly="1" />
<newline />
<field name="role" select="1" />
<field name="cutype" select="1" />
<field name="role" select="1" readonly="1" string="Role" />
<field name="cutype" select="1" readonly="1" string="Invitation type" />
<newline />
<field name="rsvp" />
<field name="rsvp" readonly="1" />
<notebook colspan="4">
<page string="Details">
<field name="sent_by_uid" />
<field name="dir" widget='url' />
<field name="language" />
<field name="event_date" />
<field name="event_end_date" />
<newline />
<field name="sent_by_uid" readonly="1"/>
<field name="dir" widget='url' readonly="1"/>
<field name="language" readonly="1"/>
<newline />
<field name="ref" colspan="4" readonly="1"/>
</page>
<page string="Delegation Info">
<separator string="Delegated to" colspan="4" />
<field name="del_to_user_ids" nolabel="1" colspan="4" />
<field name="del_to_user_ids" nolabel="1"
colspan="4" readonly="1" />
<separator string="Delegated from" colspan="4" />
<field name="del_from_user_ids" nolabel="1" colspan="4" />
<field name="del_from_user_ids" nolabel="1"
colspan="4" readonly="1" />
</page>
</notebook>
<group col="6" colspan="4">
@ -77,7 +103,7 @@
name="%(caldav.action_view_calendar_invite_attendee_wizard)d"
states="needs-action" string="Delegate"
type="action" icon="gtk-sort-descending"
context="{'model' : 'calendar.attendee'}" />
context="{'model' : 'calendar.attendee', 'state' : 'delegated'}" />
</group>
</form>
</field>

View File

@ -44,7 +44,9 @@ def map_data(cr, uid, obj):
continue
mapping =obj.__attribute__[map_dict].get('mapping', False)
if mapping:
map_val = mapping[map_val]
map_val = mapping[map_val.lower()]
else:
map_val = map_val.lower()
if field_type == 'many2many':
ids = []
if not map_val:
@ -59,7 +61,7 @@ def map_data(cr, uid, obj):
continue
if field_type == 'many2one':
id = None
if not map_val:
if not map_val or not isinstance(map_val, dict):
vals[field] = id
continue
model = obj.__attribute__[map_dict].get('object', False)
@ -126,12 +128,16 @@ class CalDAV(object):
continue
uidval = common.openobjectid2uid(cr, data[map_field], model)
vevent.add('uid').value = uidval
elif field == 'attendee' and data[map_field]:
attendee_obj = self.pool.get('basic.calendar.attendee')
vevent = attendee_obj.export_ical(cr, uid, data[map_field], vevent, context=context)
elif field == 'valarm' and data[map_field]:
alarm_obj = self.pool.get('basic.calendar.alarm')
vevent = alarm_obj.export_ical(cr, uid, data[map_field][0], vevent, context=context)
elif field == 'attendee' and data[map_field]:
#vevent.add('attendee').value = data[map_field]
#TODO : To export attendee
pass
elif field == 'valarm' and data[map_field]:
# vevent.add('valarm').value = data[map_field]
#TODO : To export valarm
pass
elif data[map_field]:
if map_type == "text":
vevent.add(field).value = str(data[map_field])
@ -142,10 +148,12 @@ class CalDAV(object):
vevent.add(field).value = parser.parse(data[map_field])
elif map_type == "timedelta":
vevent.add(field).value = timedelta(hours=data[map_field])
elif map_type == "many2one":
vevent.add(field).value = [data.get(map_field)[1]]
if self.__attribute__.get(field).has_key('mapping'):
for key1, val1 in self.ical_get(field, 'mapping').items():
if val1 == data[map_field]:
vevent.add(field).value = key1
vevent.add(field).value = key1
return ical
def import_ical(self, cr, uid, ical_data):
@ -154,16 +162,16 @@ class CalDAV(object):
res = []
for child in parsedCal.getChildren():
for cal_data in child.getChildren():
if cal_data.name.lower() == 'attendee':
attendee = self.pool.get('basic.calendar.attendee')
att_data.append(attendee.import_ical(cr, uid, cal_data))
self.ical_set(cal_data.name.lower(), att_data, 'value')
continue
if cal_data.name.lower() == 'valarm':
alarm = self.pool.get('basic.calendar.alarm')
vals = alarm.import_ical(cr, uid, cal_data)
self.ical_set(cal_data.name.lower(), vals, 'value')
continue
#if cal_data.name.lower() == 'attendee':
# attendee = self.pool.get('basic.calendar.attendee')
# att_data.append(attendee.import_ical(cr, uid, cal_data))
# self.ical_set(cal_data.name.lower(), cal_data.value, 'value')
# continue
#if cal_data.name.lower() == 'valarm':
# alarm = self.pool.get('basic.calendar.alarm')
# vals = alarm.import_ical(cr, uid, cal_data)
# self.ical_set(cal_data.name.lower(), cal_data.value, 'value')
# continue
if cal_data.name.lower() in self.__attribute__:
self.ical_set(cal_data.name.lower(), cal_data.value, 'value')
if child.name.lower() in ('vevent', 'vtodo'):
@ -327,33 +335,37 @@ class Alarm(CalDAV, osv.osv_memory):
'x-prop': None,
}
def export_ical(self, cr, uid, alarm_id, vevent, context={}):
valarm = vevent.add('valarm')
alarm_object = self.pool.get('calendar.alarm')
alarm_data = alarm_object.read(cr, uid, alarm_id, [])
def export_ical(self, cr, uid, alarm_datas, context={}):
ical = vobject.iCalendar()
vevent = ical.add('vevent')
valarms = []
for alarm_data in alarm_datas:
valarm = vevent.add('valarm')
# Compute trigger data
interval = alarm_data['trigger_interval']
occurs = alarm_data['trigger_occurs']
duration = (occurs == 'after' and alarm_data['trigger_duration']) \
or -(alarm_data['trigger_duration'])
related = alarm_data['trigger_related']
trigger = valarm.add('trigger')
trigger.params['related'] = [related.upper()]
if interval == 'days':
delta = timedelta(days=duration)
if interval == 'hours':
delta = timedelta(hours=duration)
if interval == 'minutes':
delta = timedelta(minutes=duration)
trigger.value = delta
# Compute trigger data
interval = alarm_data['trigger_interval']
occurs = alarm_data['trigger_occurs']
duration = (occurs == 'after' and alarm_data['trigger_duration']) \
or -(alarm_data['trigger_duration'])
related = alarm_data['trigger_related']
trigger = valarm.add('trigger')
trigger.params['related'] = [related.upper()]
if interval == 'days':
delta = timedelta(days=duration)
if interval == 'hours':
delta = timedelta(hours=duration)
if interval == 'minutes':
delta = timedelta(minutes=duration)
trigger.value = delta
# Compute other details
valarm.add('description').value = alarm_data['name']
valarm.add('action').value = alarm_data['action']
return vevent
# Compute other details
valarm.add('description').value = alarm_data['name']
valarm.add('action').value = alarm_data['action']
valarms.append(valarm)
return valarms
def import_ical(self, cr, uid, ical_data):
def import_ical(self, cr, uid, ical_data):
for child in ical_data.getChildren():
if child.name.lower() == 'trigger':
seconds = child.value.seconds
@ -374,12 +386,12 @@ class Alarm(CalDAV, osv.osv_memory):
related = days>=0 and 'after' or 'before'
self.ical_set('trigger_interval', interval, 'value')
self.ical_set('trigger_duration', duration, 'value')
self.ical_set('trigger_occurs', related, 'value')
self.ical_set('trigger_occurs', related.lower(), 'value')
if child.params:
if child.params.get('related'):
self.ical_set('trigger_related', child.params.get('related')[0].lower(), 'value')
else:
self.ical_set(child.name.lower(), child.value, 'value')
self.ical_set(child.name.lower(), child.value.lower(), 'value')
vals = map_data(cr, uid, self)
return vals
@ -401,28 +413,31 @@ class Attendee(CalDAV, osv.osv_memory):
'language': None, # Use: 0-1 Specify the language for text values in a property or property parameter.
}
def import_ical(self, cr, uid, ical_data):
def import_ical(self, cr, uid, ical_data):
for para in ical_data.params:
if para.lower() == 'cn':
self.ical_set(para.lower(), ical_data.params[para][0]+':'+ ical_data.value, 'value')
else:
self.ical_set(para.lower(), ical_data.params[para][0], 'value')
self.ical_set(para.lower(), ical_data.params[para][0].lower(), 'value')
if not ical_data.params.get('CN'):
self.ical_set('cn', ical_data.value, 'value')
vals = map_data(cr, uid, self)
return vals
def export_ical(self, cr, uid, attendee_id, vevent, context={}):
attendee_object = self.pool.get('calendar.attendee')
for attendee in attendee_object.read(cr, uid, attendee_id, []):
def export_ical(self, cr, uid, attendee_data, context={}):
ical = vobject.iCalendar()
attendees = []
vevent = ical.add('vevent')
for attendee in attendee_data:
attendee_add = vevent.add('attendee')
for a_key, a_val in attendee_object.__attribute__.items():
for a_key, a_val in self.__attribute__.items():
if attendee[a_val['field']]:
if a_val['type'] == 'text':
attendee_add.params[a_key] = [str(attendee[a_val['field']])]
elif a_val['type'] == 'boolean':
attendee_add.params[a_key] = [str(attendee[a_val['field']])]
return vevent
attendees.append(attendee_add)
return attendees
Attendee()

View File

@ -43,7 +43,7 @@ def caldav_id2real_id(caldav_id = None, with_date=False):
return int(real_id)
return caldav_id and int(caldav_id) or caldav_id
def real_id2caldav_id(real_id, recurrent_date):
def real_id2caldav_id(real_id, recurrent_date):
if real_id and recurrent_date:
recurrent_date = time.strftime("%Y%m%d%H%M%S", \
time.strptime(recurrent_date, "%Y-%m-%d %H:%M:%S"))
@ -64,11 +64,17 @@ def uid2openobjectid(cr, uidval, oomodel):
if id in ids:
return id
return False
def openobjectid2uid(cr, uidval, oomodel):
value = 'OpenObject-%s_%s@%s' % (oomodel, uidval, cr.dbname)
return value
def _links_get(self, cr, uid, context={}):
obj = self.pool.get('res.request.link')
ids = obj.search(cr, uid, [])
res = obj.read(cr, uid, ids, ['object', 'name'], context)
return [(r['object'], r['name']) for r in res]
class calendar_attendee(osv.osv):
_name = 'calendar.attendee'
_description = 'Attendee information'
@ -87,12 +93,40 @@ class calendar_attendee(osv.osv):
'dir': {'field':'dir', 'type':'text'},
'language': {'field':'language', 'type':'text'},
}
def export_cal(self, cr, uid, ids, context={}):
basic_attendee_obj = self.pool.get('basic.calendar.attendee')
basic_attendee_obj.__attribute__.update(self.__attribute__)
data = self.read(cr, uid, ids)
attendees = basic_attendee_obj.export_ical(cr, uid, data, {'model': self._name})
cal_val = ''
for attendee in attendees:
cal_val += attendee.serialize()
return cal_val
def import_cal(self, cr, uid, data, context={}):
file_content = base64.decodestring(data)
basic_attendee_obj = self.pool.get('basic.calendar.attendee')
basic_attendee_obj.__attribute__.update(self.__attribute__)
vals = basic_attendee_obj.import_ical(cr, uid, file_content)
ids = []
for val in vals:
is_exists = uid2openobjectid(cr, val['id'], self._name)
if val.has_key('create_date'): val.pop('create_date')
val.pop('id')
if is_exists:
self.write(cr, uid, [is_exists], val)
ids.append(is_exists)
else:
attendee_id = self.create(cr, uid, val)
ids.append(attendee_id)
return ids
def _get_address(self, name=None, email=None):
if name and email:
name += ':'
return (name or '') + (email and ('MAILTO:' + email) or '')
def _compute_data(self, cr, uid, ids, name, arg, context):
name = name[0]
result = {}
@ -101,16 +135,16 @@ class calendar_attendee(osv.osv):
email = user.address_id and user.address_id.email or ''
return self._get_address(user.name, email)
for id in ids:
result[id] = {}
attdata = self.browse(cr, uid, id, context=context)
for attdata in self.browse(cr, uid, ids, context=context):
id = attdata.id
result[id] = {}
if name == 'sent_by':
if not attdata.sent_by_uid:
result[id][name] = ''
continue
else:
result[id][name] = self._get_address(attdata.sent_by_uid.name, \
attdata.sent_by_uid.address_id.email)
attdata.sent_by_uid.address_id.email)
if name == 'cn':
result[id][name] = self._get_address(attdata.user_id.name, attdata.email)
if name == 'delegated_to':
@ -122,31 +156,64 @@ class calendar_attendee(osv.osv):
user_obj = self.pool.get('res.users')
fromdata = map(get_delegate_data, attdata.del_from_user_ids)
result[id][name] = ', '.join(fromdata)
return result
if name == 'event_date':
if attdata.ref:
model, res_id = tuple(attdata.ref.split(','))
model_obj = self.pool.get(model)
obj = model_obj.read(cr, uid, res_id, ['date'])[0]
result[id][name] = obj['date']
if name == 'event_end_date':
if attdata.ref:
model, res_id = tuple(attdata.ref.split(','))
model_obj = self.pool.get(model)
obj = model_obj.read(cr, uid, res_id, ['date_deadline'])[0]
result[id][name] = obj['date_deadline']
if name == 'sent_by_uid':
if attdata.ref:
model, res_id = tuple(attdata.ref.split(','))
model_obj = self.pool.get(model)
obj = model_obj.read(cr, uid, res_id, ['user_id'])[0]
result[id][name] = obj['user_id']
return result
def _links_get(self, cr, uid, context={}):
obj = self.pool.get('res.request.link')
ids = obj.search(cr, uid, [])
res = obj.read(cr, uid, ids, ['object', 'name'], context)
return [(r['object'], r['name']) for r in res]
def _lang_get(self, cr, uid, context={}):
obj = self.pool.get('res.lang')
ids = obj.search(cr, uid, [])
res = obj.read(cr, uid, ids, ['code', 'name'], context)
res = [((r['code']).replace('_', '-'), r['name']) for r in res]
return res
_columns = {
'cutype': fields.selection([('individual', 'Individual'), \
('group', 'Group'), ('resource', 'Resource'), \
('room', 'Room'), ('unknown', 'Unknown') ], \
'User Type', help="Specify the type of calendar user"),
'member': fields.char('Member', size=124, help="Indicate the groups \
that the attendee belongs to"),
'role': fields.selection([ ('req-participant', 'req-participant'), \
('chair', 'chair'), ('opt-participant', 'opt-participant'), \
('non-participant', 'non-participant')], 'User\'s Role', \
help='Participation role for the calendar user'),
'member': fields.char('Member', size=124,
help="Indicate the groups that the attendee belongs to"),
'role': fields.selection([('req-participant', 'Participation required'), \
('chair', 'Chair Person'), \
('opt-participant', 'Optional Participation'), \
('non-participant', 'For information Purpose')], 'Role', \
help='Participation role for the calendar user'),
'state': fields.selection([('tentative', 'Tentative'),
('needs-action', 'Needs Action'),
('accepted', 'Accepted'),
('declined', 'Declined'),
('delegated', 'Delegated')], 'Status', readonly=True,
('delegated', 'Delegated')], 'State', readonly=True,
help="Status of the attendee's participation"),
'rsvp': fields.boolean('Required Reply?', help="Indicats whether the \
favor of a reply is requested"),
'rsvp': fields.boolean('Required Reply?',
help="Indicats whether the favor of a reply is requested"),
'delegated_to': fields.function(_compute_data, method=True, \
string='Delegated To', type="char", size=124, store=True, \
multi='delegated_to', help="The users that the original request \
was delegated to"),
was delegated to"),
'del_to_user_ids': fields.many2many('res.users', 'att_del_to_user_rel',
'attendee_id', 'user_id', 'Users'),
'delegated_from': fields.function(_compute_data, method=True, string=\
@ -154,22 +221,28 @@ was delegated to"),
'del_from_user_ids': fields.many2many('res.users', 'att_del_from_user_rel', \
'attendee_id', 'user_id', 'Users'),
'sent_by': fields.function(_compute_data, method=True, string='Sent By', type="char", multi='sent_by', store=True, size=124, help="Specify the user that is acting on behalf of the calendar user"),
'sent_by_uid': fields.many2one('res.users', 'Sent by User'),
'sent_by_uid': fields.function(_compute_data, method=True, string='Sent by', type="many2one", obj='res.users', multi='sent_by_uid'),
'cn': fields.function(_compute_data, method=True, string='Common name', type="char", size=124, multi='cn', store=True),
'dir': fields.char('URI Reference', size=124, help="Reference to the URI that points to the directory information corresponding to the attendee."),
'language': fields.char('Language', size=124, help="To specify the language for text values in a property or property parameter."),
'user_id': fields.many2one('res.users', 'User'),
'language': fields.selection(_lang_get, 'Language',
help="To specify the language for text values in a property or property parameter."),
'user_id': fields.many2one('res.users', 'User', required=True),
'email': fields.char('Email', size=124),
}
'event_date' : fields.function(_compute_data, method=True, string='Event Date', type="datetime", multi='event_date'),
'event_end_date' : fields.function(_compute_data, method=True, string='Event End Date', type="datetime", multi='event_end_date'),
'ref':fields.reference('Document Ref', selection=_links_get, size=128),
'availability': fields.selection([('free', 'Free'), ('busy', 'Busy')], 'Free/Busy', readonly="True"),
}
_defaults = {
'state': lambda *x: 'needs-action',
}
'state': lambda *x: 'needs-action',
}
def onchange_user_id(self, cr, uid, ids, user_id, *args, **argv):
if not user_id:
return {'value': {'email': ''}}
user = self.pool.get('res.users').browse(cr, uid, user_id, *args)
return {'value': {'email': user.address_id.email}}
usr_obj = self.pool.get('res.users')
user = usr_obj.browse(cr, uid, user_id, *args)
return {'value': {'email': user.address_id.email, 'availability':user.availability}}
def do_tentative(self, cr, uid, ids, context=None, *args):
self.write(cr, uid, ids, {'state': 'tentative'}, context)
@ -185,8 +258,8 @@ calendar_attendee()
class res_alarm(osv.osv):
_name = 'res.alarm'
_description = 'basic alarm information'
_columns = {
'name':fields.char('Name', size=256, required=True),
_columns = {
'name':fields.char('Name', size=256, required=True),
'trigger_occurs': fields.selection([('before', 'Before'), ('after', 'After')], \
'Trigger time', required=True),
'trigger_interval': fields.selection([('minutes', 'Minutes'), ('hours', 'Hours'), \
@ -196,12 +269,12 @@ class res_alarm(osv.osv):
'The event ends')], 'Trigger Occures at', required=True),
'duration': fields.integer('Duration', help="""Duration' and 'Repeat' \
are both optional, but if one occurs, so MUST the other"""),
'repeat': fields.integer('Repeat'),
'repeat': fields.integer('Repeat'),
'active': fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the event alarm information without removing it."),
}
_defaults = {
_defaults = {
'trigger_interval': lambda *x: 'minutes',
'trigger_duration': lambda *x: 5,
'trigger_occurs': lambda *x: 'before',
@ -227,10 +300,10 @@ class calendar_alarm(osv.osv):
'duration': {'field': 'duration', 'type': 'text'},
'repeat': {'field': 'repeat', 'type': 'text'},
'attach': {'field': 'attach', 'type': 'text'},
}
}
_columns = {
'alarm_id': fields.many2one('res.alarm', 'Basic Alarm', ondelete='cascade'),
_columns = {
'alarm_id': fields.many2one('res.alarm', 'Basic Alarm', ondelete='cascade'),
'name': fields.char('Summary', size=124, help="""Contains the text to be used as the message subject for email
or contains the text to be used for display"""),
'action': fields.selection([('audio', 'Audio'), ('display', 'Display'), \
@ -238,27 +311,57 @@ or contains the text to be used for display"""),
required=True, help="Defines the action to be invoked when an alarm is triggered"),
'description': fields.text('Description', help='Provides a more complete description of the calendar component, than that provided by the "SUMMARY" property'),
'attendee_ids': fields.many2many('calendar.attendee', 'alarm_attendee_rel', \
'alarm_id', 'attendee_id', 'Attendees', readonly=True),
'attach': fields.binary('Attachment', help="""* Points to a sound resource, which is rendered when the alarm is triggered for audio,
'alarm_id', 'attendee_id', 'Attendees', readonly=True),
'attach': fields.binary('Attachment', help="""* Points to a sound resource, which is rendered when the alarm is triggered for audio,
* File which is intended to be sent as message attachments for email,
* Points to a procedure resource, which is invoked when the alarm is triggered for procedure."""),
'res_id' : fields.integer('Resource ID'),
'model_id': fields.many2one('ir.model', 'Model'),
'user_id': fields.many2one('res.users', 'Owner'),
'event_date' : fields.datetime('Event Date'),
'event_end_date' : fields.datetime('Event End Date'),
'trigger_date' : fields.datetime('Trigger Date', readonly="True"),
'state':fields.selection([
('draft','Draft'),
('run','Run'),
('stop','Stop'),
('done','Done'),
],'State', select=True, readonly=True),
('draft', 'Draft'),
('run', 'Run'),
('stop', 'Stop'),
('done', 'Done'),
], 'State', select=True, readonly=True),
}
_defaults = {
'action': lambda *x: 'email',
'state' : lambda *x: 'run',
}
'state' : lambda *x: 'run',
}
def export_cal(self, cr, uid, ids, context={}):
basic_alarm_obj = self.pool.get('basic.calendar.alarm')
basic_alarm_obj.__attribute__.update(self.__attribute__)
data = self.read(cr, uid, ids)
alarms = basic_alarm_obj.export_ical(cr, uid, data, {'model': self._name})
cal_val = ''
for alarm in alarms:
cal_val += alarm.serialize()
return cal_val
def import_cal(self, cr, uid, data, context={}):
file_content = base64.decodestring(data)
basic_alarm_obj = self.pool.get('basic.calendar.alarm')
basic_alarm_obj.__attribute__.update(self.__attribute__)
vals = basic_alarm_obj.import_ical(cr, uid, file_content)
ids = []
for val in vals:
is_exists = uid2openobjectid(cr, val['id'], self._name)
if val.has_key('create_date'): val.pop('create_date')
val.pop('id')
if is_exists:
self.write(cr, uid, [is_exists], val)
ids.append(is_exists)
else:
alarm_id = self.create(cr, uid, val)
ids.append(alarm_id)
return ids
def create(self, cr, uid, vals, context={}):
event_date = vals.get('event_date', False)
@ -272,7 +375,7 @@ or contains the text to be used for display"""),
delta = datetime.timedelta(minutes=vals['trigger_duration'])
trigger_date = dtstart + (vals['trigger_occurs'] == 'after' and delta or -delta)
vals['trigger_date'] = trigger_date
res = super(calendar_alarm, self).create(cr, uid, vals, context)
res = super(calendar_alarm, self).create(cr, uid, vals, context)
return res
def do_run_scheduler(self, cr, uid, automatic=False, use_new_cursor=False, \
@ -283,31 +386,31 @@ or contains the text to be used for display"""),
cr.execute("select alarm.id as id \
from calendar_alarm alarm \
where alarm.state = %s and alarm.trigger_date <= %s", ('run', current_datetime))
res = cr.dictfetchall()
alarm_ids = map(lambda x: x['id'], res)
res = cr.dictfetchall()
alarm_ids = map(lambda x: x['id'], res)
attendee_obj = self.pool.get('calendar.attendee')
request_obj = self.pool.get('res.request')
mail_to = []
for alarm in self.browse(cr, uid, alarm_ids):
for alarm in self.browse(cr, uid, alarm_ids):
if alarm.action == 'display':
value = {
'name': alarm.name,
'act_from': alarm.user_id.id,
'act_to': alarm.user_id.id,
value = {
'name': alarm.name,
'act_from': alarm.user_id.id,
'act_to': alarm.user_id.id,
'body': alarm.description,
'trigger_date': alarm.trigger_date,
'ref_doc1' : '%s,%s' %(alarm.model_id.model, alarm.res_id)
'ref_doc1' : '%s,%s' %(alarm.model_id.model, alarm.res_id)
}
request_id = request_obj.create(cr, uid, value)
request_ids = [request_id]
for attendee in alarm.attendee_ids:
value['act_to'] = attendee.act_to.id
for attendee in alarm.attendee_ids:
value['act_to'] = attendee.user_id.id
request_id = request_obj.create(cr, uid, value)
request_ids.append(request_id)
request_obj.request_send(cr, uid, request_ids)
if alarm.action == 'email':
sub = '[Openobject Remainder] %s' %(alarm.name)
sub = '[Openobject Remainder] %s' %(alarm.name)
body = """
Name : %s
Date : %s
@ -316,12 +419,12 @@ or contains the text to be used for display"""),
From :
%s
%s
""" %(alarm.name, alarm.trigger_date, alarm.description, alarm.user_id.name, alarm.user_id.sign)
mail_to = [alarm.user_id.address_id.email]
for att in alarm.attendee_ids:
mail_to.append(att.act_to.address_id.email)
for att in alarm.attendee_ids:
mail_to.append(att.user_id.address_id.email)
tools.email_send(
tools.confirm['from_mail'],
mail_to,
@ -349,8 +452,8 @@ class ir_attachment(osv.osv):
for i, arg in enumerate(new_args):
if arg[0] == 'res_id':
new_args[i] = (arg[0], arg[1], caldav_id2real_id(arg[2]))
return super(ir_attachment, self).search(cr, uid, new_args, offset=offset,
limit=limit, order=order,
return super(ir_attachment, self).search(cr, uid, new_args, offset=offset,
limit=limit, order=order,
context=context, count=False)
ir_attachment()
@ -392,7 +495,7 @@ class ir_model(osv.osv):
for val in data:
val['id'] = caldav_id2real_id(val['id'])
return data
ir_model()
class virtual_report_spool(web_services.report_spool):
@ -466,7 +569,7 @@ class set_rrule_wizard(osv.osv_memory):
if freq == 'weekly':
byday = map(lambda x: x.upper(), filter(lambda x: datas.get(x) and x in weekdays, datas))
if byday:
if byday:
weekstring = ';BYDAY=' + ','.join(byday)
elif freq == 'monthly':
@ -497,14 +600,14 @@ class set_rrule_wizard(osv.osv_memory):
rrule_string = 'FREQ=' + freq + weekstring + ';INTERVAL=' + \
str(datas.get('interval')) + enddate + monthstring + yearstring
# End logic
# End logic
return rrule_string
def do_add(self, cr, uid, ids, context={}):
datas = self.read(cr, uid, ids)[0]
if datas.get('interval') <= 0:
raise osv.except_osv(_('Error!'), ("Please select proper Interval"))
if not context or not context.get('model'):
return {}
@ -512,48 +615,95 @@ class set_rrule_wizard(osv.osv_memory):
model = context.get('model')
obj = self.pool.get(model)
res_obj = obj.browse(cr, uid, context['active_id'])
rrule_string = self.compute_rule_string(cr, uid, datas)
obj.write(cr, uid, [res_obj.id], {'rrule' : rrule_string})
return {}
set_rrule_wizard()
class res_users(osv.osv):
_inherit = 'res.users'
def _get_user_avail(self, cr, uid, ids, context=None):
current_datetime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
res = {}
attendee_obj = self.pool.get('calendar.attendee')
attendee_ids = attendee_obj.search(cr, uid, [
('event_date','<=',current_datetime), ('event_end_date','<=',current_datetime),
('state','=','accepted'), ('user_id','in',ids)
])
result = cr.dictfetchall()
for attendee_data in attendee_obj.read(cr, uid, attendee_ids, ['user_id']):
user_id = attendee_data['user_id']
status = 'busy'
res.update({user_id:status})
#TOCHECK : Delegrated Event
#cr.execute("SELECT user_id,'busy' FROM att_del_to_user_rel where user_id = ANY(%s)", (ids,))
#res.update(cr.dictfetchall())
for user_id in ids:
if user_id not in res:
res[user_id] = 'free'
return res
def _get_user_avail_fun(self, cr, uid, ids, name, args, context=None):
return self._get_user_avail(cr, uid, ids, context=context)
_columns = {
'availability': fields.function(_get_user_avail_fun, type='selection', \
selection=[('free', 'Free'), ('busy', 'Busy')], \
string='Free/Busy', method=True),
}
res_users()
class invite_attendee_wizard(osv.osv_memory):
_name = "caldav.invite.attendee"
_description = "Invite Attendees"
_columns = {
'user_id': fields.many2one('res.users', 'User'),
'email': fields.char('Email', size=124),
'role': fields.selection([ ('REQ-PARTICIPANT', 'REQ-PARTICIPANT'), \
('CHAIR', 'CHAIR'), ('OPT-PARTICIPANT', 'OPT-PARTICIPANT'), \
('NON-PARTICIPANT', 'NON-PARTICIPANT')], 'User\'s Role', \
help='Participation role for the calendar user'),
'rsvp': fields.boolean('Required Reply?', help="Indicats whether the \
favor of a reply is requested"),
}
_columns = {
'attendee_ids': fields.many2many('calendar.attendee', 'invite_attendee_rel', 'invite_id', 'attendee_id', 'Attendees Detail'),
}
def do_invite(self, cr, uid, ids, context={}):
datas = self.read(cr, uid, ids)[0]
if not context or not context.get('model') or not datas.get('user_id'):
return {}
else:
model = context.get('model')
obj = self.pool.get(model)
res_obj = obj.browse(cr, uid, context['active_id'])
user_obj = self.pool.get('res.users')
def create(self, cr, uid, vals, context={}):
attendee_ids = vals.get('attendee_ids',False)
model = context.get('model', False)
res_id = context.get('active_id', False)
state = context.get('state', False)
attendee_obj = self.pool.get('calendar.attendee')
for user_id in datas.get('users', []):
user = user_obj.browse(cr, uid, user_id)
if not user.address_id.email:
raise osv.except_osv(_('Error!'), \
("User does not have an email Address"))
attendee_id = attendee_obj.create(cr, uid, {'user_id': user_id,\
'cn': user.name + ':MAILTO:' + user.address_id.email})
obj.write(cr, uid, res_obj.id, {'attendee_ids': [(6, 0, [attendee_id])]})
if attendee_ids and model and res_id:
attend = False
if model == 'calendar.attendee' and state == 'delegated':
attend = attendee_obj.read(cr, uid, res_id, ['ref','user_id','del_to_user_ids'])
for v1, v2, attendee in attendee_ids:
vals = {}
ref = '%s,%d'%(model, res_id)
if attend:
ref = attend['ref']
del_from_user_ids = [attend['user_id'][0]]
del_to_user_ids = attend['del_to_user_ids']
del_to_user_ids.append(attendee['user_id'])
vals.update({
'del_from_user_ids' : [(6, 0, del_from_user_ids)]
})
attendee_obj.write(cr, uid, [res_id], {'state':'delegated','del_to_user_ids' : [(6, 0, del_to_user_ids)]})
vals.update({
'ref': ref,
})
attendee.update(vals)
attendee_obj.create(cr, uid, attendee)
res = super(invite_attendee_wizard, self).create(cr, uid, {}, context=context)
return res
def do_invite(self, cr, uid, ids, context={}):
return {}
def onchange_user_id(self, cr, uid, ids, user_id, *args, **argv):
if not user_id:

View File

@ -73,7 +73,7 @@ class crm_case_section(osv.osv):
'user_id': fields.many2one('res.users', 'Responsible User'),
'reply_to': fields.char('Reply-To', size=64, help="The email address put in the 'Reply-To' of all emails sent by Open ERP about cases in this section"),
'parent_id': fields.many2one('crm.case.section', 'Parent Section'),
'child_ids': fields.one2many('crm.case.section', 'parent_id', 'Child Sections'),
'child_ids': fields.one2many('crm.case.section', 'parent_id', 'Child Sections'),
'calendar' : fields.boolean('Calendar', help='Allows to show calendar'),
}
_defaults = {
@ -408,6 +408,11 @@ class crm_case(osv.osv):
if context.get('portal', False):
return False
return uid
def _get_section(self, cr, uid, context):
user = self.pool.get('res.users').browse(cr, uid, uid)
return user.section_id.id
_defaults = {
'active': lambda *a: 1,
'user_id': _get_default_user,
@ -417,6 +422,7 @@ class crm_case(osv.osv):
'state': lambda *a: 'draft',
'priority': lambda *a: AVAILABLE_PRIORITIES[2][0],
'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
'section_id': _get_section,
}
_order = 'priority, date_deadline desc, date desc,id desc'
@ -818,8 +824,8 @@ class crm_case(osv.osv):
data['user_id'] = uid
self.write(cr, uid, ids, data)
self._action(cr,uid, cases, 'open')
return True
return True
def case_cancel(self, cr, uid, ids, *args):
cases = self.browse(cr, uid, ids)
@ -946,5 +952,15 @@ class crm_email_add_cc_wizard(osv.osv_memory):
return {}
crm_email_add_cc_wizard()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
class res_users(osv.osv):
_inherit = "res.users"
_description = "users"
_columns = {
'section_id': fields.many2one('crm.case.section', 'Sales Section', required=False)
}
res_users()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
@ -30,15 +30,15 @@ class crm_claim(osv.osv):
_name = "crm.claim"
_description = "Claim Cases"
_order = "id desc"
_inherits = {'crm.case':"inherit_case_id"}
_columns = {
_inherits = {'crm.case':"inherit_case_id"}
_columns = {
'inherit_case_id': fields.many2one('crm.case','Case',ondelete='cascade'),
}
def _map_ids(self, method, cr, uid, ids, *args, **argv):
if isinstance(ids, (str, int, long)):
select = [ids]
else:
select = ids
select = ids
case_data = self.browse(cr, uid, select)
new_ids = []
for case in case_data:
@ -61,25 +61,25 @@ class crm_claim(osv.osv):
def onchange_categ_id(self, cr, uid, ids, *args, **argv):
return self._map_ids('onchange_categ_id',cr,uid,ids,*args,**argv)
def case_close(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_close',cr,uid,ids,*args,**argv)
return self._map_ids('case_close',cr,uid,ids,*args,**argv)
def case_open(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_open',cr,uid,ids,*args,**argv)
def case_cancel(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_cancel',cr,uid,ids,*args,**argv)
def case_reset(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_reset',cr,uid,ids,*args,**argv)
def case_escalate(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_escalate',cr,uid,ids,*args,**argv)
def case_pending(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_pending',cr,uid,ids,*args,**argv)
return self._map_ids('case_reset',cr,uid,ids,*args,**argv)
def case_escalate(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_escalate',cr,uid,ids,*args,**argv)
def case_pending(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_pending',cr,uid,ids,*args,**argv)
def msg_new(self, cr, uid, msg):
def msg_new(self, cr, uid, msg):
mailgate_obj = self.pool.get('mail.gateway')
msg_body = mailgate_obj.msg_body_get(msg)
data = {
'name': msg['Subject'],
'name': msg['Subject'],
'email_from': msg['From'],
'email_cc': msg['Cc'],
'email_cc': msg['Cc'],
'user_id': False,
'description': msg_body['body'],
'history_line': [(0, 0, {'description': msg_body['body'], 'email': msg['From'] })],
@ -87,15 +87,15 @@ class crm_claim(osv.osv):
res = mailgate_obj.partner_get(cr, uid, msg['From'])
if res:
data.update(res)
res = self.create(cr, uid, data)
res = self.create(cr, uid, data)
return res
def msg_update(self, cr, uid, ids, *args, **argv):
return self._map_ids('msg_update',cr, uid, ids, *args, **argv)
def emails_get(self, cr, uid, ids, *args, **argv):
return self._map_ids('emails_get',cr, uid, ids, *args, **argv)
def msg_send(self, cr, uid, ids, *args, **argv):
return self._map_ids('msg_send',cr, uid, ids, *args, **argv)
def msg_send(self, cr, uid, ids, *args, **argv):
return self._map_ids('msg_send',cr, uid, ids, *args, **argv)
crm_claim()
@ -103,7 +103,7 @@ class crm_claim_assign_wizard(osv.osv_memory):
_name = 'crm.claim.assign_wizard'
_columns = {
'section_id': fields.many2one('crm.case.section', 'Section', required=True),
'section_id': fields.many2one('crm.case.section', 'Section', required=False),
'user_id': fields.many2one('res.users', 'Responsible'),
}
@ -133,18 +133,18 @@ class crm_claim_assign_wizard(osv.osv_memory):
'section_id':res.get('section_id',False),
'user_id':res.get('user_id',False),
'case_id' : case.inherit_case_id.id
}, context=context)
}, context=context)
case_obj.case_close(cr, uid, [case_id])
data_obj = self.pool.get('ir.model.data')
result = data_obj._get_id(cr, uid, 'crm', 'view_crm_case_claims_filter')
search_view = data_obj.read(cr, uid, result, ['res_id'])
value = {
value = {
'name': _('Claims'),
'view_type': 'form',
'view_mode': 'form,tree',
'res_model': 'crm.claim',
'res_id': int(new_case_id),
'res_id': int(new_case_id),
'type': 'ir.actions.act_window',
'search_view_id': search_view['res_id']
}

View File

@ -36,16 +36,16 @@ class crm_helpdesk(osv.osv):
_name = "crm.helpdesk"
_description = "Helpdesk Cases"
_order = "id desc"
_inherits = {'crm.case':"inherit_case_id"}
_columns = {
_inherits = {'crm.case':"inherit_case_id"}
_columns = {
'inherit_case_id':fields.many2one('crm.case','Case'),
}
def _map_ids(self, method, cr, uid, ids, *args, **argv):
if isinstance(ids, (str, int, long)):
select = [ids]
else:
select = ids
select = ids
case_data = self.browse(cr, uid, select)
new_ids = []
for case in case_data:
@ -66,21 +66,21 @@ class crm_helpdesk(osv.osv):
def onchange_categ_id(self, cr, uid, ids, *args, **argv):
return self._map_ids('onchange_categ_id',cr,uid,ids,*args,**argv)
def case_close(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_close',cr,uid,ids,*args,**argv)
return self._map_ids('case_close',cr,uid,ids,*args,**argv)
def case_open(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_open',cr,uid,ids,*args,**argv)
def case_cancel(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_cancel',cr,uid,ids,*args,**argv)
def case_reset(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_reset',cr,uid,ids,*args,**argv)
def msg_new(self, cr, uid, msg):
def msg_new(self, cr, uid, msg):
mailgate_obj = self.pool.get('mail.gateway')
msg_body = mailgate_obj.msg_body_get(msg)
data = {
'name': msg['Subject'],
'name': msg['Subject'],
'email_from': msg['From'],
'email_cc': msg['Cc'],
'email_cc': msg['Cc'],
'user_id': False,
'description': msg_body['body'],
'history_line': [(0, 0, {'description': msg_body['body'], 'email': msg['From'] })],
@ -88,15 +88,15 @@ class crm_helpdesk(osv.osv):
res = mailgate_obj.partner_get(cr, uid, msg['From'])
if res:
data.update(res)
res = self.create(cr, uid, data)
res = self.create(cr, uid, data)
return res
def msg_update(self, cr, uid, ids, *args, **argv):
return self._map_ids('msg_update',cr, uid, ids, *args, **argv)
def emails_get(self, cr, uid, ids, *args, **argv):
return self._map_ids('emails_get',cr, uid, ids, *args, **argv)
def msg_send(self, cr, uid, ids, *args, **argv):
return self._map_ids('msg_send',cr, uid, ids, *args, **argv)
def msg_send(self, cr, uid, ids, *args, **argv):
return self._map_ids('msg_send',cr, uid, ids, *args, **argv)
crm_helpdesk()
@ -104,7 +104,7 @@ class crm_helpdesk_assign_wizard(osv.osv_memory):
_name = 'crm.helpdesk.assign_wizard'
_columns = {
'section_id': fields.many2one('crm.case.section', 'Section', required=True),
'section_id': fields.many2one('crm.case.section', 'Section', required=False),
'user_id': fields.many2one('res.users', 'Responsible'),
}

View File

@ -33,7 +33,7 @@
<record model="ir.actions.act_window.view" id="action_crm_sec_graph_view_act_job">
<field name="sequence" eval="4"/>
<field name="view_mode">graph</field>
<field name="view_id" ref="crm_case_graph_view_stage_cost"/>
<field name="view_id" ref="crm_case_graph_view_job"/>
<field name="act_window_id" ref="crm_case_categ0_act_job"/>
</record>
<menuitem

View File

@ -163,6 +163,19 @@
</field>
</record>
<record model="ir.ui.view" id="crm_case_graph_view_job">
<field name="name">CRM - Jobs Requests Graph</field>
<field name="model">crm.job</field>
<field name="type">graph</field>
<field name="arch" type="xml">
<graph string="Cases By Stage and Estimates" type="bar" orientation="vertical">
<field name="categ_id"/>
<field name="planned_cost" operator="+"/>
<field name="state" group="True"/>
</graph>
</field>
</record>
<record id="view_crm_case_jobs_filter" model="ir.ui.view">
<field name="name">CRM - Jobs Requests Search</field>
<field name="model">crm.job</field>

View File

@ -35,112 +35,128 @@ class crm_meeting(osv.osv):
_order = "id desc"
_inherits = {'crm.case': "inherit_case_id"}
__attribute__ = {
'class': {'field': 'class', 'type': 'text'},
'class': {'field': 'class', 'type': 'selection'},
'created': {'field': 'create_date', 'type': 'datetime'}, # keep none for now
'description': {'field': 'description', 'type': 'text'},
'dtstart': {'field': 'date', 'type': 'datetime'},
'location': {'field': 'location', 'type': 'text'},
'description': {'field': 'description', 'type': 'text'},
'dtstart': {'field': 'date', 'type': 'datetime'},
'location': {'field': 'location', 'type': 'text'},
#'organizer': {'field': 'partner_id', 'sub-field': 'name', 'type': 'many2one'},
'priority': {'field': 'priority', 'type': 'int'},
'dtstamp' : {'field': 'date', 'type': 'datetime'},
'seq': None,
'status': {'field': 'state', 'type': 'selection', 'mapping': {'TENTATIVE': 'draft', \
'CONFIRMED': 'open' , 'CANCELLED': 'cancel'}},
'summary': {'field': 'name', 'type': 'text'},
'transp': {'field': 'transparent', 'type': 'text'},
'uid': {'field': 'id', 'type': 'text'},
'url': {'field': 'caldav_url', 'type': 'text'},
'recurid': None,
'priority': {'field': 'priority', 'type': 'int'},
'dtstamp' : {'field': 'date', 'type': 'datetime'},
'seq': None,
'status': {'field': 'state', 'type': 'selection', 'mapping': {'tentative': 'draft', \
'confirmed': 'open' , 'cancelled': 'cancel'}},
'summary': {'field': 'name', 'type': 'text'},
'transp': {'field': 'transparent', 'type': 'text'},
'uid': {'field': 'id', 'type': 'text'},
'url': {'field': 'caldav_url', 'type': 'text'},
'recurid': None,
# 'attach': {'field': 'attachment_ids', 'sub-field': 'datas', 'type': 'list'},
'attendee': {'field': 'attendee_ids', 'type': 'many2many', 'object': 'calendar.attendee'},
'attendee': {'field': 'attendees', 'type': 'text'},
# 'categories': {'field': 'categ_id', 'sub-field': 'name'},
# 'categories': {'field':None , 'sub-field': 'name', 'type': 'text'},
'comment': None,
'contact': None,
'exdate' : {'field': 'exdate', 'type': 'datetime'},
'exrule' : {'field': 'exrule', 'type': 'text'},
'rstatus': None,
'related': None,
'resources': None,
'rdate': None,
'rrule': {'field': 'rrule', 'type': 'text'},
'x-openobject-model': {'value': _name, 'type': 'text'},
'categories': {'field': 'categ_id', 'type': 'many2one', 'object': 'crm.case.categ'},
'comment': None,
'contact': None,
'exdate' : {'field': 'exdate', 'type': 'datetime'},
'exrule' : {'field': 'exrule', 'type': 'text'},
'rstatus': None,
'related': None,
'resources': None,
'rdate': None,
'rrule': {'field': 'rrule', 'type': 'text'},
'x-openobject-model': {'value': _name, 'type': 'text'},
# 'duration': {'field': 'duration'},
'dtend': {'field': 'date_closed', 'type': 'datetime'},
'valarm': {'field': 'caldav_alarm_id', 'type': 'many2one', 'object': 'calendar.alarm'},
'dtend': {'field': 'date_deadline', 'type': 'datetime'},
'valarm': {'field': 'alarms', 'type': 'text'},
}
def _get_attendee_data(self, cr, uid, ids, name, arg, context):
def _get_data(self, cr, uid, ids, name, arg, context):
result = {}
for id in ids:
eventdata = self.browse(cr, uid, id, context=context)
if not eventdata.attendee_ids:
return result
att_data = map(lambda x: x.cn or '', eventdata.attendee_ids)
result[id] = ', '.join(att_data)
attendee_obj = self.pool.get('calendar.attendee')
alarm_obj = self.pool.get('calendar.alarm')
model_obj = self.pool.get('ir.model')
model_id = model_obj.search(cr, uid, [('model','=',self._name)])[0]
for meeting_id in ids:
result[meeting_id] = {}
if "attendees" in name:
attendee_ids = attendee_obj.search(cr, uid, [('ref','=','%s,%d'%(self._name, meeting_id))])
result[meeting_id]["attendees"] = attendee_obj.export_cal(cr, uid, attendee_ids)
if "alarms" in name:
alarm_ids = alarm_obj.search(cr, uid, [('model_id','=',model_id), ('res_id','=',meeting_id)])
result[meeting_id]["alarms"] = alarm_obj.export_cal(cr, uid, alarm_ids)
return result
def _set_attendee_data(self, cr, uid, id, name, value, arg, context):
def _set_data(self, cr, uid, meeting_id, name, value, arg, context):
if not value:
return
eventdata = self.browse(cr, uid, id, context=context)
att_len = len(eventdata.attendee_ids)
if att_len == len(value.split(',')):
return
if att_len > len(value.split(',')):
for attendee in eventdata.attendee_ids[len(value.split(',')):]:
self.write(cr, uid, id, {'attendee_ids': [(3, attendee.id)]})
return
attendee_obj = self.pool.get('calendar.attendee')
for val in value.split(',')[att_len:]:
attendee_id = attendee_obj.create(cr, uid, {'cn': val.strip()})
self.write(cr, uid, id, {'attendee_ids': [(4, attendee_id)]})
return
return
attendee_obj = self.pool.get('calendar.attendee')
model_obj = self.pool.get('ir.model')
alarm_obj = self.pool.get('calendar.alarm')
eventdata = self.read(cr, uid, meeting_id, [name], context=context)
if name == "attendees":
attendee_ids = attendee_obj.import_cal(cr, uid, eventdata['attendees'])
vals = {
'ref':'%s,%d'%('crm.meeting', meeting_id)
}
attendee_obj.write(cr, uid, attendee_ids, vals)
if name == "alarms":
model_id = model_obj.search(cr, uid, [('model','=',self._name)])[0]
alarm_ids = alarm_obj.import_cal(cr, uid, eventdata['alarms'])
vals = {
'res_id' : meeting.id,
'model_id' : model_id,
}
alarm_obj.write(cr, uid, alarm_ids, vals)
alarm = alarm_obj.browse(cr, uid, alarm_ids)[0]
self.write(cr, uid, [meeting_id], {'alarm_id':alarm.alarm_id})
return True
_columns = {
'inherit_case_id': fields.many2one('crm.case', 'Case', ondelete='cascade'),
'date_deadline': fields.datetime('Deadline', help="Deadline Date is automatically computed from Start Date + Duration"),
'class': fields.selection([('public', 'Public'), ('private', 'Private'), \
('confidential', 'Confidential')], 'Privacy'),
'location': fields.char('Location', size=264, help="Gives Location of Meeting"),
'freebusy': fields.text('FreeBusy'),
('confidential', 'Confidential')], 'Privacy'),
'location': fields.char('Location', size=264, help="Gives Location of Meeting"),
'freebusy': fields.text('FreeBusy'),
'show_as': fields.selection([('free', 'Free'), \
('busy', 'Busy')],
'show_as'),
'caldav_url': fields.char('Caldav URL', size=264),
'show_as'),
'caldav_url': fields.char('Caldav URL', size=264),
'exdate': fields.text('Exception Date/Times', help="This property defines the list\
of date/time exceptions for arecurring calendar component."),
of date/time exceptions for arecurring calendar component."),
'exrule': fields.char('Exception Rule', size=352, help="defines a rule or repeating pattern\
for anexception to a recurrence set"),
'rrule': fields.char('Recurrent Rule', size=352, invisible="True"),
for anexception to a recurrence set"),
'rrule': fields.char('Recurrent Rule', size=352, invisible="True"),
'rrule_type' : fields.selection([('none', 'None'), ('daily', 'Daily'), \
('weekly', 'Weekly'), ('monthly', 'Monthly'), ('yearly', 'Yearly'), ('custom','Custom')], 'Recurrency'),
'attendees': fields.function(_get_attendee_data, method=True,\
fnct_inv=_set_attendee_data, string='Attendees', type="text"),
'alarm_id': fields.many2one('res.alarm', 'Alarm'),
'caldav_alarm_id': fields.many2one('calendar.alarm', 'Alarm'),
'attendee_ids': fields.many2many('calendar.attendee', 'crm_attendee_rel', 'case_id', \
'attendee_id', 'Attendees'),
'attendees': fields.function(_get_data, method=True,\
fnct_inv=_set_data, string='Attendees', type="text", multi='attendees'),
'alarms': fields.function(_get_data, method=True,\
fnct_inv=_set_data, string='Attendees', type="text", multi='alarms'),
'alarm_id': fields.many2one('res.alarm', 'Alarm'),
}
_defaults = {
'class': lambda *a: 'public',
'class': lambda *a: 'public',
'show_as' : lambda *a : 'busy',
}
def do_alarm_create(self, cr, uid, ids, context={}):
alarm_obj = self.pool.get('calendar.alarm')
model_obj = self.pool.get('ir.model')
attendee_obj = self.pool.get('calendar.attendee')
model_id = model_obj.search(cr, uid, [('model','=',self._name)])[0]
for meeting in self.browse(cr, uid, ids):
for meeting in self.browse(cr, uid, ids):
self.do_alarm_unlink(cr, uid, [meeting.id])
attendee_ids = attendee_obj.search(cr, uid, [('ref','=','%s,%d'%(self._name, meeting.id))])
basic_alarm = meeting.alarm_id
if basic_alarm and meeting.state in ('open'):
if basic_alarm:
vals = {
'action': 'display',
'description': meeting.description,
'name': meeting.name,
'attendee_ids': [(6,0, map(lambda x:x.id, meeting.attendee_ids))],
'attendee_ids': [(6,0, attendee_ids)],
'trigger_related': basic_alarm.trigger_related,
'trigger_duration': basic_alarm.trigger_duration,
'trigger_occurs': basic_alarm.trigger_occurs,
@ -148,16 +164,16 @@ class crm_meeting(osv.osv):
'duration': basic_alarm.duration,
'repeat': basic_alarm.repeat,
'state' : 'run',
'event_date' : meeting.date,
'event_date' : meeting.date,
'event_end_date' : meeting.date_deadline,
'res_id' : meeting.id,
'model_id' : model_id,
'user_id' : uid
}
alarm_id = alarm_obj.create(cr, uid, vals)
cr.execute('Update crm_meeting set caldav_alarm_id=%s where id=%s' % (alarm_id, meeting.id))
cr.commit()
return True
return True
def do_alarm_unlink(self, cr, uid, ids, context={}):
alarm_obj = self.pool.get('calendar.alarm')
model_obj = self.pool.get('ir.model')
@ -165,84 +181,64 @@ class crm_meeting(osv.osv):
for meeting in self.browse(cr, uid, ids):
alarm_ids = alarm_obj.search(cr, uid, [('model_id','=',model_id), ('res_id','=',meeting.id)])
if alarm_ids and len(alarm_ids):
alarm_obj.unlink(cr, uid, alarm_ids)
cr.execute('Update crm_meeting set caldav_alarm_id=NULL where id=%s' % (meeting.id))
alarm_obj.unlink(cr, uid, alarm_ids)
cr.commit()
return True
def on_change_duration(self, cr, uid, id, date, duration):
if not date:
return {}
start_date = datetime.datetime.fromtimestamp(time.mktime(time.strptime(date, "%Y-%m-%d %H:%M:%S")))
start_date = datetime.datetime.strptime(date, "%Y-%m-%d %H:%M:%S")
if duration >= 0 :
end = start_date + datetime.timedelta(hours=duration)
if duration < 0:
raise osv.except_osv(_('Warning !'),
_('You can not set negative Duration.'))
res = {'value' : {'date_deadline' : end.strftime('%Y-%m-%d %H:%M:%S')}}
return res
def export_cal(self, cr, uid, ids, context={}):
crm_data = self.read(cr, uid, ids, [], context ={'read':True})
crm_data = self.read(cr, uid, ids)
event_obj = self.pool.get('basic.calendar.event')
event_obj.__attribute__.update(self.__attribute__)
attendee_obj = self.pool.get('basic.calendar.attendee')
crm_attendee = self.pool.get('calendar.attendee')
attendee_obj.__attribute__.update(crm_attendee.__attribute__)
alarm_obj = self.pool.get('basic.calendar.alarm')
crm_alarm = self.pool.get('calendar.alarm')
alarm_obj.__attribute__.update(crm_alarm.__attribute__)
ical = event_obj.export_ical(cr, uid, crm_data, {'model': 'crm.meeting'})
caendar_val = ical.serialize()
caendar_val = caendar_val.replace('"', '').strip()
return caendar_val
ical = event_obj.export_ical(cr, uid, crm_data, {'model': self._name})
cal_val = ical.serialize()
cal_val = cal_val.replace('"', '').strip()
return cal_val
def import_cal(self, cr, uid, data, context={}):
file_content = base64.decodestring(data)
event_obj = self.pool.get('basic.calendar.event')
event_obj.__attribute__.update(self.__attribute__)
attendee_obj = self.pool.get('basic.calendar.attendee')
crm_attendee = self.pool.get('calendar.attendee')
attendee_obj.__attribute__.update(crm_attendee.__attribute__)
alarm_obj = self.pool.get('basic.calendar.alarm')
crm_alarm = self.pool.get('calendar.alarm')
alarm_obj.__attribute__.update(crm_alarm.__attribute__)
event_obj.__attribute__.update(self.__attribute__)
vals = event_obj.import_ical(cr, uid, file_content)
for val in vals:
ids = []
for val in vals:
is_exists = common.uid2openobjectid(cr, val['id'], self._name)
val.pop('id')
if val.has_key('create_date'): val.pop('create_date')
val['caldav_url'] = context.get('url') or ''
caldav_alarm_id = val['caldav_alarm_id']
if caldav_alarm_id:
caldav_alarm = self.browse(cr, uid, caldav_alarm_id)
val['alarm_id'] = caldav_alarm.alarm_id
if is_exists:
val.pop('id')
if is_exists:
self.write(cr, uid, [is_exists], val)
ids.append(is_exists)
else:
case_id = self.create(cr, uid, val)
return {'count': len(vals)}
case_id = self.create(cr, uid, val)
ids.append(case_id)
return ids
def get_recurrent_ids(self, cr, uid, ids, start_date, until_date, limit=100):
if not limit:
limit = 100
limit = 100
if ids and (start_date or until_date):
cr.execute("select m.id, m.rrule, c.date, m.exdate from crm_meeting m\
join crm_case c on (c.id=m.inherit_case_id) \
where m.id in ("+ ','.join(map(lambda x: str(x), ids))+")")
result = []
count = 0
count = 0
start_date = start_date and datetime.datetime.strptime(start_date, "%Y-%m-%d") or False
until_date = until_date and datetime.datetime.strptime(until_date, "%Y-%m-%d") or False
for data in cr.dictfetchall():
until_date = until_date and datetime.datetime.strptime(until_date, "%Y-%m-%d") or False
for data in cr.dictfetchall():
if count > limit:
break
event_date = datetime.datetime.strptime(data['date'], "%Y-%m-%d %H:%M:%S")
@ -268,18 +264,16 @@ class crm_meeting(osv.osv):
if until_date and until_date >= rrule_until_date:
until_date = rrule_until_date
if until_date:
until_date = until_date.strftime("%Y%m%d%H%M%S")
value = until_date
value = until_date.strftime("%Y%m%d%H%M%S")
new_rule = '%s=%s' % (name, value)
new_rrule_str.append(new_rule)
if not is_until and until_date:
until_date = until_date.strftime("%Y%m%d%H%M%S")
value = until_date
value = until_date.strftime("%Y%m%d%H%M%S")
name = "UNTIL"
new_rule = '%s=%s' % (name, value)
new_rrule_str.append(new_rule)
new_rrule_str = ';'.join(new_rrule_str)
start_date = datetime.datetime.strptime(data['date'], "%Y-%m-%d %H:%M:%S")
start_date = datetime.datetime.strptime(data['date'], "%Y-%m-%d %H:%M:%S")
rdates = event_obj.get_recurrent_dates(str(new_rrule_str), exdate, start_date)
for rdate in rdates:
idval = common.real_id2caldav_id(data['id'], rdate)
@ -288,7 +282,7 @@ class crm_meeting(osv.osv):
ids = result
return ids
def search(self, cr, uid, args, offset=0, limit=100, order=None,
def search(self, cr, uid, args, offset=0, limit=100, order=None,
context=None, count=False):
args_without_date = []
start_date = False
@ -302,7 +296,7 @@ class crm_meeting(osv.osv):
elif arg[1] in ('<', '<='):
until_date = arg[2]
res = super(crm_meeting, self).search(cr, uid, args_without_date, offset,
res = super(crm_meeting, self).search(cr, uid, args_without_date, offset,
limit, order, context, count)
return self.get_recurrent_ids(cr, uid, res, start_date, until_date, limit)
@ -320,7 +314,7 @@ class crm_meeting(osv.osv):
if 'case_id' in vals:
vals['case_id'] = common.caldav_id2real_id(vals['case_id'])
res = super(crm_meeting, self).write(cr, uid, new_ids, vals, context=context)
self.do_alarm_create(cr, uid, ids)
self.do_alarm_create(cr, uid, new_ids)
return res
def browse(self, cr, uid, ids, context=None, list_class=None, fields_process={}):
@ -406,18 +400,18 @@ class crm_meeting(osv.osv):
if isinstance(ids, (str, int, long)) and isinstance(res, list):
return res and res[0] or False
return res
def onchange_rrule_type(self, cr, uid, ids, type, *args, **argv):
if type == 'none':
return {'value': {'rrule': ''}}
return {'value': {'rrule': ''}}
if type == 'custom':
return {}
rrule = self.pool.get('caldav.set.rrule')
rrulestr = rrule.compute_rule_string(cr, uid, {'freq': type.upper(),\
'interval': 1})
return {'value': {'rrule': rrulestr}}
return {'value': {'rrule': rrulestr}}
def onchange_case_id(self, cr, uid, ids, *args, **argv):
return self._map_ids('onchange_case_id', cr, uid, ids, *args, **argv)
def onchange_partner_id(self, cr, uid, ids, *args, **argv):
@ -439,12 +433,12 @@ class crm_meeting(osv.osv):
mailgate_obj = self.pool.get('mail.gateway')
msg_body = mailgate_obj.msg_body_get(msg)
data = {
'name': msg['Subject'],
'email_from': msg['From'],
'email_cc': msg['Cc'],
'user_id': False,
'description': msg_body['body'],
'history_line': [(0, 0, {'description': msg_body['body'], 'email': msg['From'] })],
'name': msg['Subject'],
'email_from': msg['From'],
'email_cc': msg['Cc'],
'user_id': False,
'description': msg_body['body'],
'history_line': [(0, 0, {'description': msg_body['body'], 'email': msg['From'] })],
}
res = mailgate_obj.partner_get(cr, uid, msg['From'])
if res:
@ -466,8 +460,8 @@ class crm_meeting_generic_wizard(osv.osv_memory):
_name = 'crm.meeting.generic_wizard'
_columns = {
'section_id': fields.many2one('crm.case.section', 'Section', required=True),
'user_id': fields.many2one('res.users', 'Responsible'),
'section_id': fields.many2one('crm.case.section', 'Section', required=False),
'user_id': fields.many2one('res.users', 'Responsible'),
}
def _get_default_section(self, cr, uid, context):
@ -493,8 +487,8 @@ class crm_meeting_generic_wizard(osv.osv_memory):
raise osv.except_osv(_('Error !'), _('You can not assign Closed Case.'))
new_case_id = case_obj.copy(cr, uid, case_id, default=
{
'section_id': res.get('section_id', False),
'user_id': res.get('user_id', False),
'section_id': res.get('section_id', False),
'user_id': res.get('user_id', False),
'case_id': case.inherit_case_id.id
}, context=context)
case_obj.case_close(cr, uid, [case_id])
@ -503,11 +497,11 @@ class crm_meeting_generic_wizard(osv.osv_memory):
search_view = data_obj.read(cr, uid, result, ['res_id'])
new_case = case_obj.read(cr, uid, new_case_id, ['id'])
value = {
'name': _('Meetings'),
'view_type': 'form',
'view_mode': 'calendar, tree, form',
'res_model': 'crm.meeting',
'type': 'ir.actions.act_window',
'name': _('Meetings'),
'view_type': 'form',
'view_mode': 'calendar, tree, form',
'res_model': 'crm.meeting',
'type': 'ir.actions.act_window',
'search_view_id': search_view['res_id']
}
return value
@ -516,61 +510,19 @@ crm_meeting_generic_wizard()
class res_users(osv.osv):
_inherit = 'res.users'
def _get_user_avail(self, cr, uid, ids, name, args, context=None):
res={}
if not context or not context.get('model'):
return {}
else:
model = context.get('model')
obj = self.pool.get(model)
event_obj = obj.browse(cr, uid, context['active_id'])
event_start = event_obj.date
event_end = datetime.datetime.strptime(event_obj.date, "%Y-%m-%d %H:%M:%S") \
+ datetime.timedelta(hours=event_obj.duration)
for id in ids:
datas = self.browse(cr, uid, id)
cr.execute("""SELECT c.date as start, (c.date::timestamp \
+ c.duration * interval '1 hour') as end \
from crm_meeting m \
join crm_case c on (c.id=m.inherit_case_id)\
where c.user_id = %s
and m.id not in (""" % (datas['id']) + str(context['active_id']) +")")
dates = cr.dictfetchall()
overlaps = False
# check event time
for date in dates:
start = date['start']
end = date['end']
cr.execute("SELECT (timestamp '%s', timestamp '%s') OVERLAPS\
(timestamp '%s', timestamp '%s')" % (event_start, event_end, start, end))
over = cr.fetchone()[0]
if over:
overlaps = True
# check for attendee added already
cr.execute("""select att.user_id , c.id
from calendar_attendee att
inner join crm_attendee_rel rel on (rel.attendee_id=att.id)
join crm_meeting m on (rel.case_id=m.id)
join crm_case c on (m.inherit_case_id = c.id )
where (c.date, c.date::timestamp + c.duration * interval '1 hour') overlaps\
(timestamp '%s', timestamp '%s')""" % (event_start, event_end))
added_data = filter(lambda x: x.get('user_id')==id, cr.dictfetchall())
if added_data:
overlaps = True
if overlaps:
res[id] = 'busy'
else:
res[id] = 'free'
def _get_user_avail(self, cr, uid, ids, context=None):
current_datetime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
res = super(res_users, self)._get_user_avail(cr, uid, ids, context)
cr.execute("SELECT crm_case.user_id, 'busy' as status \
FROM crm_meeting meeting, crm_case \
WHERE meeting.inherit_case_id = crm_case.id \
and crm_case.date <= %s and crm_case.date_deadline >= %s and crm_case.user_id = ANY(%s) and meeting.show_as = %s",
(current_datetime, current_datetime , ids, 'busy'))
result = cr.dictfetchall()
for user_data in result:
user_id = user_data['user_id']
status = user_data['status']
res.update({user_id:status})
return res
_columns = {
'availability': fields.function(_get_user_avail, type='selection', \
selection=[('free', 'Free'), ('busy', 'Busy')], \
string='Free/Busy', method=True),
}
res_users()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -31,52 +31,27 @@
<field name="view_id" ref="crm_meeting_generic_wizard"/>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
<record model="ir.ui.view" id="view_users_form_crm">
<field name="name">caldav.res.users.form</field>
<field name="type">form</field>
<field name="priority">10</field>
<field name="model">res.users</field>
<field name="arch" type="xml">
<form string="User">
<field name="name" />
<field name="availability" />
</form>
</field>
</record>
</record>
<record model="ir.ui.view" id="view_users_tree_crm">
<field name="name">caldav.res.users.tree</field>
<field name="type">tree</field>
<field name="priority">10</field>
<field name="model">res.users</field>
<field name="arch" type="xml">
<tree string="Userss">
<field name="name" />
<field name="availability" />
</tree>
</field>
</record>
<record model="ir.ui.view" id="crm_case_form_view_meet">
<record model="ir.ui.view" id="crm_case_form_view_meet">
<field name="name">CRM - Meetings Form</field>
<field name="model">crm.meeting</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Meetings Form">
<field name="name" select="1" string="Title"/>
<field name="section_id" widget="selection"
string="Calendar" domain="[('calendar','=',True)]"/>
<field name="location" />
<field name="categ_id" select="2" on_change="onchange_categ_id(categ_id)"/>
<group colspan="4" col="6">
<field name="date" string="Start Date" on_change="on_change_duration(date, duration)" required="1"/>
<field name="duration" string="Duration(In Hour)" on_change="on_change_duration(date, duration)" widget="float_time"/>
<field name="date_deadline" string="End Date" required="1"/>
<group col="3" colspan="2">
<field name="section_id" widget="selection"
string="Calendar"/>
<button string="Invite Attendees"
name="%(caldav.action_view_calendar_invite_attendee_wizard)d"
icon="terp-partner" type="action"
context="{'model' : 'crm.meeting'}" />
</group>
<field name="location" />
<field name="categ_id" select="2" on_change="onchange_categ_id(categ_id)"/>
<field name="date" string="Start Date" required="1"/>
<field name="date_deadline" string="End Date" required="1"/>
<notebook colspan="4">
<page string="Meeting">
<field name="alarm_id" colspan="1" string="Alarm"/>
@ -91,9 +66,7 @@
/>
</group>
<separator string="Description" colspan="4"/>
<field name="description" nolabel="1" colspan="4"/>
<separator string="Attendees" colspan="4"/>
<field name="attendees" nolabel="1" colspan="4"/>
<field name="description" nolabel="1" colspan="4"/>
<field name="show_as" string="Show as"/>
<field name="class" string="Mark as"/>
<separator string="" colspan="4"/>
@ -103,15 +76,8 @@
<button name="case_cancel" string="Cancel Meeting" states="draft,open,pending" type="object" icon="gtk-cancel"/>
<button name="case_reset" string="Reset to Unconfirmed" states="done,open,cancel" type="object" icon="gtk-convert"/>
</group>
</page>
<page string="Attendee Detail">
<separator string="Attendees" colspan="4"/>
<field name="attendee_ids" colspan="4" nolabel="1"/>
<button string="Invite Attendees"
name="%(caldav.action_view_calendar_invite_attendee_wizard)d"
icon="terp-partner" type="action"
context="{'model' : 'crm.meeting'}" />
</page>
</page>
<page string="Partner Info">
<field name="partner_id" on_change="onchange_partner_id(partner_id, email_from)" />
<field name="partner_address_id" on_change="onchange_partner_address_id(partner_address_id, email_from)"/>
@ -123,6 +89,8 @@
<field name="case_id" on_change="onchange_case_id(case_id, name, partner_id)"/>
<button string="Assign" name="%(crm_meeting_generic_wizard_act)d" type="action" />
</group>
<separator string="Attendees" colspan="4"/>
<field name="attendees" nolabel="1" colspan="4"/>
<field name="rrule" string="Recurrent Rules" colspan="4"/>
<field name="exrule" string="Exception Rules" colspan="4"/>
<separator string="Exception Dates" colspan="4"/>

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
@ -34,16 +34,16 @@ class crm_phonecall(osv.osv):
_name = "crm.phonecall"
_description = "Phonecall Cases"
_order = "id desc"
_inherits = {'crm.case':"inherit_case_id"}
_columns = {
_inherits = {'crm.case':"inherit_case_id"}
_columns = {
'inherit_case_id': fields.many2one('crm.case','Case',ondelete='cascade'),
}
def _map_ids(self, method, cr, uid, ids, *args, **argv):
if isinstance(ids, (str, int, long)):
select = [ids]
else:
select = ids
select = ids
case_data = self.browse(cr, uid, select)
new_ids = []
for case in case_data:
@ -64,25 +64,25 @@ class crm_phonecall(osv.osv):
def onchange_categ_id(self, cr, uid, ids, *args, **argv):
return self._map_ids('onchange_categ_id',cr,uid,ids,*args,**argv)
def case_close(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_close',cr,uid,ids,*args,**argv)
return self._map_ids('case_close',cr,uid,ids,*args,**argv)
def case_open(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_open',cr,uid,ids,*args,**argv)
def case_cancel(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_cancel',cr,uid,ids,*args,**argv)
def case_reset(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_reset',cr,uid,ids,*args,**argv)
def case_escalate(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_escalate',cr,uid,ids,*args,**argv)
def case_pending(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_reset',cr,uid,ids,*args,**argv)
def case_escalate(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_escalate',cr,uid,ids,*args,**argv)
def case_pending(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_pending',cr,uid,ids,*args,**argv)
def msg_new(self, cr, uid, msg):
def msg_new(self, cr, uid, msg):
mailgate_obj = self.pool.get('mail.gateway')
msg_body = mailgate_obj.msg_body_get(msg)
data = {
'name': msg['Subject'],
'name': msg['Subject'],
'email_from': msg['From'],
'email_cc': msg['Cc'],
'email_cc': msg['Cc'],
'user_id': False,
'description': msg_body['body'],
'history_line': [(0, 0, {'description': msg_body['body'], 'email': msg['From'] })],
@ -90,16 +90,16 @@ class crm_phonecall(osv.osv):
res = mailgate_obj.partner_get(cr, uid, msg['From'])
if res:
data.update(res)
res = self.create(cr, uid, data)
res = self.create(cr, uid, data)
return res
def msg_update(self, cr, uid, ids, *args, **argv):
return self._map_ids('msg_update',cr, uid, ids, *args, **argv)
def emails_get(self, cr, uid, ids, *args, **argv):
return self._map_ids('emails_get',cr, uid, ids, *args, **argv)
def msg_send(self, cr, uid, ids, *args, **argv):
return self._map_ids('msg_send',cr, uid, ids, *args, **argv)
def msg_send(self, cr, uid, ids, *args, **argv):
return self._map_ids('msg_send',cr, uid, ids, *args, **argv)
crm_phonecall()
@ -107,7 +107,7 @@ class crm_phonecall_assign_wizard(osv.osv_memory):
_name = 'crm.phonecall.assign_wizard'
_columns = {
'section_id': fields.many2one('crm.case.section', 'Section', required=True),
'section_id': fields.many2one('crm.case.section', 'Section', required=False),
'user_id': fields.many2one('res.users', 'Responsible'),
}
@ -137,17 +137,17 @@ class crm_phonecall_assign_wizard(osv.osv_memory):
'section_id':res.get('section_id',False),
'user_id':res.get('user_id',False),
'case_id' : case.inherit_case_id.id
}, context=context)
}, context=context)
case_obj.case_close(cr, uid, [case_id])
data_obj = self.pool.get('ir.model.data')
result = data_obj._get_id(cr, uid, 'crm', 'view_crm_case_phonecalls_filter')
search_view = data_obj.read(cr, uid, result, ['res_id'])
value = {
value = {
'name': _('Phone Calls'),
'view_type': 'form',
'view_mode': 'form,tree',
'res_model': 'crm.phonecall',
'res_id': int(new_case_id),
'res_id': int(new_case_id),
'type': 'ir.actions.act_window',
'search_view_id': search_view['res_id']
}

View File

@ -3,7 +3,7 @@
<data>
<menuitem icon="terp-crm" id="menu_crm" name="CRM &amp; SRM"/>
<menuitem id="menu_crm_configuration" name="Configuration" parent="crm.menu_crm" sequence="0"/>
<wizard id="wizard_crm_send_mail" model="crm.case.history" name="crm.send.mail" string="Send Mail" menu="False"/>
<wizard id="wizard_crm_new_send_mail" model="crm.case" name="crm.new.send.mail" string="Send New Mail" menu="False"/>
@ -42,7 +42,7 @@
<field name="allow_unlink" select="2"/>
<field name="calendar" select="2"/>
</group>
<field name="reply_to" select="2"/>
<field name="reply_to" select="2"/>
</page>
</notebook>
</form>
@ -78,7 +78,7 @@
<field name="view_type">tree</field>
<field name="view_id" ref="crm_case_section_view_tree"/>
</record>
<menuitem action="crm_case_section_act_tree" id="menu_crm_case_section_act_tree" parent="next_id_52"/>
<menuitem action="crm_case_section_act_tree" id="menu_crm_case_section_act_tree" parent="next_id_52"/>
<!-- Case Categories -->
<record id="crm_case_categ-view" model="ir.ui.view">
@ -624,5 +624,31 @@
<act_window domain="[('user_id', '=', active_id),('state','&lt;&gt;','done'),('state','&lt;&gt;','cancel'),('state','&lt;&gt;','pending')]" id="act_res_users_2_crm_case_opened" name="Open cases" res_model="crm.case" src_model="res.users" view_mode="tree,form,calendar" view_type="form"/>
<record model="ir.ui.view" id="view_users_form_simple_modif_inherited1">
<field name="name">view.users.form.crm.modif.inherited1</field>
<field name="model">res.users</field>
<field name="inherit_id" ref="base.view_users_form_simple_modif" />
<field name="type">form</field>
<field name="arch" type="xml">
<page string="Current Activity" position="inside">
<field name="section_id" widget="selection"/>
</page>
</field>
</record>
<record id="view_users_form_simple_modif_inherited2" model="ir.ui.view">
<field name="name">view.users.form.crm.modif.inherited2</field>
<field name="model">res.users</field>
<field name="type">form</field>
<field name="inherit_id" ref="base.view_users_form"/>
<field eval="18" name="priority"/>
<field name="arch" type="xml">
<field name="password" position="after">
<field name="section_id" widget="selection" />
</field>
</field>
</record>
</data>
</openerp>

View File

@ -18,5 +18,130 @@
<field name="groups_id" eval="[(6,0,[ref('group_crm_manager')])]"/>
</record>
<!--rule for meeting-->
<record model="ir.rule.group" id="crm_meeting_rule_group">
<field name="name">crm.meeting.rule</field>
<field name="model_id" search="[('model','=','crm.meeting')]" model="ir.model"/>
<field name="global" eval="True"/>
</record>
<record id="crm_meeting_rule" model="ir.rule">
<field model="ir.model.fields" name="field_id" search="[('model','=','crm.case'),('name','=','section_id')]"/>
<field name="operator">=</field>
<field name="operand">user.section_id.id</field>
<field name="domain_force">['|',('section_id','=',False),('section_id','=',[user.section_id.id])]</field>
<field name="rule_group" ref="crm_meeting_rule_group"/>
</record>
<!--rule for Claims-->
<record model="ir.rule.group" id="crm_claim_rule_group">
<field name="name">crm.claim.rule</field>
<field name="model_id" search="[('model','=','crm.claim')]" model="ir.model"/>
<field name="global" eval="True"/>
</record>
<record id="crm_claim_rule" model="ir.rule">
<field model="ir.model.fields" name="field_id" search="[('model','=','crm.case'),('name','=','section_id')]"/>
<field name="operator">=</field>
<field name="operand">user.section_id.id</field>
<field name="domain_force">['|',('section_id','=',False),('section_id','=',[user.section_id.id])]</field>
<field name="rule_group" ref="crm_claim_rule_group"/>
</record>
<!--rule for Fund Raising-->
<record model="ir.rule.group" id="crm_fundraising_rule_group">
<field name="name">crm.fundraising.rule</field>
<field name="model_id" search="[('model','=','crm.fundraising')]" model="ir.model"/>
<field name="global" eval="True"/>
</record>
<record id="crm_fundraising_rule" model="ir.rule">
<field model="ir.model.fields" name="field_id" search="[('model','=','crm.case'),('name','=','section_id')]"/>
<field name="operator">=</field>
<field name="operand">user.section_id.id</field>
<field name="domain_force">['|',('section_id','=',False),('section_id','=',[user.section_id.id])]</field>
<field name="rule_group" ref="crm_fundraising_rule_group"/>
</record>
<!--rule for HelpDesk-->
<record model="ir.rule.group" id="crm_helpdesk_rule_group">
<field name="name">crm.helpdesk.rule</field>
<field name="model_id" search="[('model','=','crm.helpdesk')]" model="ir.model"/>
<field name="global" eval="True"/>
</record>
<record id="crm_helpdesk_rule" model="ir.rule">
<field model="ir.model.fields" name="field_id" search="[('model','=','crm.case'),('name','=','section_id')]"/>
<field name="operator">=</field>
<field name="operand">user.section_id.id</field>
<field name="domain_force">['|',('section_id','=',False),('section_id','=',[user.section_id.id])]</field>
<field name="rule_group" ref="crm_helpdesk_rule_group"/>
</record>
<!--rule for Jobs-->
<record model="ir.rule.group" id="crm_job_rule_group">
<field name="name">crm.meeting.rule</field>
<field name="model_id" search="[('model','=','crm.job')]" model="ir.model"/>
<field name="global" eval="True"/>
</record>
<record id="crm_job_rule" model="ir.rule">
<field model="ir.model.fields" name="field_id" search="[('model','=','crm.case'),('name','=','section_id')]"/>
<field name="operator">=</field>
<field name="operand">user.section_id.id</field>
<field name="domain_force">['|',('section_id','=',False),('section_id','=',[user.section_id.id])]</field>
<field name="rule_group" ref="crm_job_rule_group"/>
</record>
<!--rule for leads-->
<record model="ir.rule.group" id="crm_leads_rule_group">
<field name="name">crm.leads.rule</field>
<field name="model_id" search="[('model','=','crm.lead')]" model="ir.model"/>
<field name="global" eval="True"/>
</record>
<record id="crm_leads_rule" model="ir.rule">
<field model="ir.model.fields" name="field_id" search="[('model','=','crm.case'),('name','=','section_id')]"/>
<field name="operator">=</field>
<field name="operand">user.section_id.id</field>
<field name="domain_force">['|',('section_id','=',False),('section_id','=',[user.section_id.id])]</field>
<field name="rule_group" ref="crm_leads_rule_group"/>
</record>
<!--rule for business opportunities-->
<record model="ir.rule.group" id="crm_opportunities_rule_group">
<field name="name">crm.opportunities.rule</field>
<field name="model_id" search="[('model','=','crm.opportunity')]" model="ir.model"/>
<field name="global" eval="True"/>
</record>
<record id="crm_opportunities_rule" model="ir.rule">
<field model="ir.model.fields" name="field_id" search="[('model','=','crm.case'),('name','=','section_id')]"/>
<field name="operator">=</field>
<field name="operand">user.section_id.id</field>
<field name="domain_force">['|',('section_id','=',False),('section_id','=',[user.section_id.id])]</field>
<field name="rule_group" ref="crm_opportunities_rule_group"/>
</record>
<!--rule for phone calls-->
<record model="ir.rule.group" id="crm_phone_calls_rule_group">
<field name="name">crm.phone.calls.rule</field>
<field name="model_id" search="[('model','=','crm.phonecall')]" model="ir.model"/>
<field name="global" eval="True"/>
</record>
<record id="crm_phone_calls_rule" model="ir.rule">
<field model="ir.model.fields" name="field_id" search="[('model','=','crm.case'),('name','=','section_id')]"/>
<field name="operator">=</field>
<field name="operand">user.section_id.id</field>
<field name="domain_force">['|',('section_id','=',False),('section_id','=',[user.section_id.id])]</field>
<field name="rule_group" ref="crm_phone_calls_rule_group"/>
</record>
<!--rule for cases-->
<record model="ir.rule.group" id="crm_case_rule_group">
<field name="name">crm.case.rule</field>
<field name="model_id" search="[('model','=','crm.case')]" model="ir.model"/>
<field name="global" eval="True"/>
</record>
<record id="crm_case_rule" model="ir.rule">
<field model="ir.model.fields" name="field_id" search="[('model','=','crm.case'),('name','=','section_id')]"/>
<field name="operator">=</field>
<field name="operand">user.section_id.id</field>
<field name="domain_force">['|',('section_id','=',False),('section_id','=',[user.section_id.id])]</field>
<field name="rule_group" ref="crm_case_rule_group"/>
</record>
</data>
</openerp>

View File

@ -57,7 +57,7 @@ class crm_cal_import_wizard(wizard.interface):
global cnt
cnt = 0
if vals:
cnt = vals['count']
cnt = len(vals)
return {}
def _result_set(self, cr, uid, data, context=None):

View File

@ -39,6 +39,7 @@
'crm_bugs_menu.xml',
'crm_feature_view.xml',
'crm_feature_menu.xml',
'security/crm_project_security.xml'
],
'demo_xml': ['crm_bugs_demo.xml'],
'installable': True,

View File

@ -36,17 +36,24 @@ class crm_project_bug(osv.osv):
_name = "crm.project.bug"
_description = "Project Bug Cases"
_order = "id desc"
_inherits = {'crm.case':"inherit_case_id"}
_columns = {
_inherits = {'crm.case':"inherit_case_id"}
_columns = {
'inherit_case_id':fields.many2one('crm.case','Case'),
'project_id':fields.many2one('project.project', 'Project'),
}
def _get_project(self, cr, uid, context):
user = self.pool.get('res.users').browse(cr, uid, uid)
return user.project_id.id
_defaults = {
'project_id':_get_project
}
def _map_ids(self, method, cr, uid, ids, *args, **argv):
if isinstance(ids, (str, int, long)):
select = [ids]
else:
select = ids
select = ids
case_data = self.browse(cr, uid, select)
new_ids = []
for case in case_data:
@ -69,25 +76,25 @@ class crm_project_bug(osv.osv):
def onchange_categ_id(self, cr, uid, ids, *args, **argv):
return self._map_ids('onchange_categ_id',cr,uid,ids,*args,**argv)
def case_close(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_close',cr,uid,ids,*args,**argv)
return self._map_ids('case_close',cr,uid,ids,*args,**argv)
def case_open(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_open',cr,uid,ids,*args,**argv)
def case_cancel(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_cancel',cr,uid,ids,*args,**argv)
def case_reset(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_reset',cr,uid,ids,*args,**argv)
def case_escalate(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_escalate',cr,uid,ids,*args,**argv)
def case_pending(self,cr, uid, ids, *args, **argv):
def case_escalate(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_escalate',cr,uid,ids,*args,**argv)
def case_pending(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_pending',cr,uid,ids,*args,**argv)
def msg_new(self, cr, uid, msg):
def msg_new(self, cr, uid, msg):
mailgate_obj = self.pool.get('mail.gateway')
msg_body = mailgate_obj.msg_body_get(msg)
data = {
'name': msg['Subject'],
'name': msg['Subject'],
'email_from': msg['From'],
'email_cc': msg['Cc'],
'email_cc': msg['Cc'],
'user_id': False,
'description': msg_body['body'],
'history_line': [(0, 0, {'description': msg_body['body'], 'email': msg['From'] })],
@ -95,16 +102,16 @@ class crm_project_bug(osv.osv):
res = mailgate_obj.partner_get(cr, uid, msg['From'])
if res:
data.update(res)
res = self.create(cr, uid, data)
res = self.create(cr, uid, data)
return res
def msg_update(self, cr, uid, ids, *args, **argv):
return self._map_ids('msg_update',cr, uid, ids, *args, **argv)
def emails_get(self, cr, uid, ids, *args, **argv):
return self._map_ids('emails_get',cr, uid, ids, *args, **argv)
def msg_send(self, cr, uid, ids, *args, **argv):
return self._map_ids('msg_send',cr, uid, ids, *args, **argv)
def msg_send(self, cr, uid, ids, *args, **argv):
return self._map_ids('msg_send',cr, uid, ids, *args, **argv)
crm_project_bug()
@ -143,20 +150,20 @@ class crm_bug_assign_wizard(osv.osv_memory):
'section_id':res.get('section_id',False),
'user_id':res.get('user_id',False),
'case_id' : case.inherit_case_id.id
}, context=context)
}, context=context)
case_obj.case_close(cr, uid, [case_id])
data_obj = self.pool.get('ir.model.data')
result = data_obj._get_id(cr, uid, 'crm_project', 'view_crm_case_bugs_filter')
search_view = data_obj.read(cr, uid, result, ['res_id'])
value = {
value = {
'name': _('Bugs'),
'view_type': 'form',
'view_mode': 'form,tree',
'res_model': 'crm.project.bug',
'res_id': int(new_case_id),
'type': 'ir.actions.act_window',
'search_view_id': search_view['res_id']
'res_id': int(new_case_id),
'type': 'ir.actions.act_window',
'search_view_id': search_view['res_id']
}
return value

View File

@ -36,17 +36,22 @@ class crm_project_future_request(osv.osv):
_name = "crm.project.future"
_description = "Project Future Request"
_order = "id desc"
_inherits = {'crm.case':"inherit_case_id"}
_columns = {
_inherits = {'crm.case':"inherit_case_id"}
_columns = {
'inherit_case_id':fields.many2one('crm.case','Case'),
'project_id':fields.many2one('project.project', 'Project'),
}
def _get_project(self, cr, uid, context):
user = self.pool.get('res.users').browse(cr,uid,uid)
return user.project_id.id
_defaults = {
'project_id':_get_project
}
def _map_ids(self, method, cr, uid, ids, *args, **argv):
if isinstance(ids, (str, int, long)):
select = [ids]
else:
select = ids
select = ids
case_data = self.browse(cr, uid, select)
new_ids = []
for case in case_data:
@ -69,25 +74,25 @@ class crm_project_future_request(osv.osv):
def onchange_categ_id(self, cr, uid, ids, *args, **argv):
return self._map_ids('onchange_categ_id',cr,uid,ids,*args,**argv)
def case_close(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_close',cr,uid,ids,*args,**argv)
return self._map_ids('case_close',cr,uid,ids,*args,**argv)
def case_open(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_open',cr,uid,ids,*args,**argv)
def case_cancel(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_cancel',cr,uid,ids,*args,**argv)
def case_reset(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_reset',cr,uid,ids,*args,**argv)
def case_escalate(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_escalate',cr,uid,ids,*args,**argv)
def case_pending(self,cr, uid, ids, *args, **argv):
def case_escalate(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_escalate',cr,uid,ids,*args,**argv)
def case_pending(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_pending',cr,uid,ids,*args,**argv)
def msg_new(self, cr, uid, msg):
def msg_new(self, cr, uid, msg):
mailgate_obj = self.pool.get('mail.gateway')
msg_body = mailgate_obj.msg_body_get(msg)
data = {
'name': msg['Subject'],
'name': msg['Subject'],
'email_from': msg['From'],
'email_cc': msg['Cc'],
'email_cc': msg['Cc'],
'user_id': False,
'description': msg_body['body'],
'history_line': [(0, 0, {'description': msg_body['body'], 'email': msg['From'] })],
@ -95,15 +100,15 @@ class crm_project_future_request(osv.osv):
res = mailgate_obj.partner_get(cr, uid, msg['From'])
if res:
data.update(res)
res = self.create(cr, uid, data)
res = self.create(cr, uid, data)
return res
def msg_update(self, cr, uid, ids, *args, **argv):
return self._map_ids('msg_update',cr, uid, ids, *args, **argv)
def emails_get(self, cr, uid, ids, *args, **argv):
return self._map_ids('emails_get',cr, uid, ids, *args, **argv)
def msg_send(self, cr, uid, ids, *args, **argv):
return self._map_ids('msg_send',cr, uid, ids, *args, **argv)
def msg_send(self, cr, uid, ids, *args, **argv):
return self._map_ids('msg_send',cr, uid, ids, *args, **argv)
crm_project_future_request()
@ -142,20 +147,20 @@ class crm_future_request_assign_wizard(osv.osv_memory):
'section_id':res.get('section_id',False),
'user_id':res.get('user_id',False),
'case_id' : case.inherit_case_id.id
}, context=context)
}, context=context)
case_obj.case_close(cr, uid, [case_id])
data_obj = self.pool.get('ir.model.data')
result = data_obj._get_id(cr, uid, 'crm_project', 'view_crm_case_future_filter')
search_view = data_obj.read(cr, uid, result, ['res_id'])
value = {
value = {
'name': _('Future Requests'),
'view_type': 'form',
'view_mode': 'form,tree',
'res_model': 'crm.project.future',
'res_id': int(new_case_id),
'type': 'ir.actions.act_window',
'search_view_id': search_view['res_id']
'res_id': int(new_case_id),
'type': 'ir.actions.act_window',
'search_view_id': search_view['res_id']
}
return value

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<record model="ir.rule.group" id="crm_project_bug_rule_group">
<field name="name">crm.project.bug.rule.group</field>
<field name="model_id" search="[('model','=','crm.project.bug')]" model="ir.model"/>
<field name="global" eval="True"/>
</record>
<record id="crm_project_bug_rule" model="ir.rule">
<field model="ir.model.fields" name="field_id" search="[('model','=','crm.project.bug'),('name','=','project_id')]"/>
<field name="operator">=</field>
<field name="operand">user.project_id.id</field>
<field name="domain_force">['|',('project_id','=',False),('project_id','=',[user.project_id.id])]</field>
<field name="rule_group" ref="crm_project_bug_rule_group"/>
</record>
<record model="ir.rule.group" id="crm_project_feature_rule_group">
<field name="name">crm.project.feature.rule.group</field>
<field name="model_id" search="[('model','=','crm.project.future')]" model="ir.model"/>
<field name="global" eval="True"/>
</record>
<record id="crm_project_feature_rule" model="ir.rule">
<field model="ir.model.fields" name="field_id" search="[('model','=','crm.project.future'),('name','=','project_id')]"/>
<field name="operator">=</field>
<field name="operand">user.project_id.id</field>
<field name="domain_force">['|',('project_id','=',False),('project_id','=',[user.project_id.id])]</field>
<field name="rule_group" ref="crm_project_feature_rule_group"/>
</record>
</data>
</openerp>

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
@ -33,6 +33,5 @@
'demo_xml': ['document_demo.xml'],
'installable': True,
'active': False,
'certificate': False,
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -19,12 +19,12 @@
#
##############################################################################
from document.nodes import node_content
from osv import osv, fields
from osv.orm import except_orm
import base64
import os
from document.nodes import node_content
class document_directory_content(osv.osv):
_inherit = 'document.directory.content'
_columns = {
@ -36,7 +36,7 @@ class document_directory_content(osv.osv):
return super(document_directory_content, self).process_write(cr, uid, node, data, context)
content = self.browse(cr, uid, node.cnt_id, context)
fobj = self.pool.get(content.object_id.model)
fobj.import_cal(cr, uid, base64.encodestring(data), context=ctx)
fobj.import_cal(cr, uid, base64.encodestring(data), context=context)
return True

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
@ -61,7 +61,7 @@ class project(osv.osv):
cr.execute('''SELECT
project_id, sum(planned_hours), sum(total_hours), sum(effective_hours)
FROM
project_task
project_task
WHERE
project_id in ('''+','.join(map(str,ids2))+''') AND
state<>'cancelled'
@ -137,7 +137,7 @@ class project(osv.osv):
# toggle activity of projects, their sub projects and their tasks
def set_template(self, cr, uid, ids, context={}):
res = self.setActive(cr, uid, ids, value=False, context=context)
res = self.setActive(cr, uid, ids, value=False, context=context)
return res
def set_done(self, cr, uid, ids, context={}):
@ -192,17 +192,17 @@ class project(osv.osv):
raise osv.except_osv(_('Operation Done'), _('A new project has been created !\nWe suggest you to close this one and work on this new project.'))
# set active value for a project, its sub projects and its tasks
def setActive(self, cr, uid, ids, value=True, context={}):
for proj in self.browse(cr, uid, ids, context):
def setActive(self, cr, uid, ids, value=True, context={}):
for proj in self.browse(cr, uid, ids, context):
self.write(cr, uid, [proj.id], {'state': value and 'open' or 'template'}, context)
cr.execute('select id from project_task where project_id=%s', (proj.id,))
tasks_id = [x[0] for x in cr.fetchall()]
if tasks_id:
self.pool.get('project.task').write(cr, uid, tasks_id, {'active': value}, context)
cr.execute('select id from project_project where parent_id=%s', (proj.id,))
project_ids = [x[0] for x in cr.fetchall()]
cr.execute('select id from project_project where parent_id=%s', (proj.id,))
project_ids = [x[0] for x in cr.fetchall()]
for child in project_ids:
self.setActive(cr, uid, [child], value, context)
self.setActive(cr, uid, [child], value, context)
return True
project()
@ -269,7 +269,7 @@ class task(osv.osv):
#_sql_constraints = [
# ('remaining_hours', 'CHECK (remaining_hours>=0)', 'Please increase and review remaining hours ! It can not be smaller than 0.'),
#]
def copy_data(self, cr, uid, id, default={},context={}):
default = default or {}
default['work_ids'] = []
@ -318,7 +318,7 @@ class task(osv.osv):
'active': lambda *a: True,
'date_start': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
'project_id': _default_project,
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'project.task', context=c)
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'project.task', context=c)
}
_order = "sequence, priority, date_deadline, id"
@ -335,22 +335,22 @@ class task(osv.osv):
return res
eview = etree.fromstring(res['arch'])
def _check_rec(eview):
if eview.attrib.get('widget','') == 'float_time':
eview.set('widget','float')
for child in eview:
_check_rec(child)
return True
_check_rec(eview)
res['arch'] = etree.tostring(eview)
for f in res['fields']:
if 'Hours' in res['fields'][f]['string']:
res['fields'][f]['string'] = res['fields'][f]['string'].replace('Hours',tm)
return res
def do_close(self, cr, uid, ids, *args):
@ -485,7 +485,7 @@ class config_compute_remaining(osv.osv_memory):
_defaults = {
'remaining_hours': _get_remaining
}
def compute_hours(self, cr, uid, ids, context=None):
if 'active_id' in context:
remaining_hrs=self.browse(cr,uid,ids)[0].remaining_hours
@ -495,5 +495,24 @@ class config_compute_remaining(osv.osv_memory):
}
config_compute_remaining()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
class message(osv.osv):
_name = "project.message"
_description = "Message"
_columns = {
'subject': fields.char('Subject', size=128),
'description': fields.char('Description', size =128),
'project_id': fields.many2one('project.project', 'Project', ondelete='cascade'),
'date': fields.date('Date'),
'user_id': fields.many2one('res.users', 'User'),
}
message()
class users(osv.osv):
_inherit = 'res.users'
_description ="User"
_columns = {
'project_id': fields.many2one('project.project', 'Project'),
}
users()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -484,7 +484,6 @@
<field name="view_mode">tree,form,calendar,gantt,graph</field>
<field eval="False" name="view_id"/>
<field eval="True" name="filter"/>
<field name="search_view_id" ref="view_task_search_form"/>
</record>
<menuitem action="action_view_task" id="menu_action_view_task" parent="project.menu_tasks"/>
@ -560,7 +559,7 @@
<field name="search_view_id" ref="view_task_search_form"/>
<field name="domain">[('state','=','open')]</field>
</record>
menu_main
<record id="action_view_task7" model="ir.actions.act_window">
<field name="name">Unassigned Tasks</field>
<field name="res_model">project.task</field>
@ -661,9 +660,80 @@
</field>
</record>
<!-- User Form-->
<record id="view_project_users_form_simple" model="ir.ui.view">
<field name="name">res.users.project.form1</field>
<field name="model">res.users</field>
<field name="type">form</field>
<field name="inherit_id" ref="base.view_users_form"/>
<field eval="18" name="priority"/>
<field name="arch" type="xml">
<field name="password" position="after">
<field name="project_id" widget="selection" />
</field>
</field>
</record>
<record model="ir.ui.view" id="view_users_form_project_modif_inherited1">
<field name="name">view.users.form.project.modif.inherited1</field>
<field name="model">res.users</field>
<field name="inherit_id" ref="base.view_users_form_simple_modif" />
<field name="type">form</field>
<field name="arch" type="xml">
<page string="Current Activity" position="inside">
<field name="project_id" widget="selection"/>
</page>
</field>
</record>
<!--- Messages-->
<record id="view_project_message_form" model="ir.ui.view">
<field name="name">project.message.form</field>
<field name="model">project.message</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Messages">
<group colspan="6">
<field name="subject" select="1"/>
<field name="description"/>
<field name="project_id" />
<field name="date" select="2"/>
<field name="user_id" select="1"/>
</group>
</form>
</field>
</record>
<record id="view_project_message_tree" model="ir.ui.view">
<field name="name">project.message.form</field>
<field name="model">project.message</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Messages">
<field name="subject" select="1"/>
<field name="description" select="1"/>
<field name="project_id" select="1"/>
<field name="date" select="1"/>
<field name="user_id" select="1"/>
</tree>
</field>
</record>
<record id="action_view_project_messages_tree" model="ir.actions.act_window">
<field name="name">Messages</field>
<field name="res_model">project.message</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="view_project_message_tree"/>
</record>
<menuitem id="menu_message_main" name="Message" parent="menu_main"/>
<menuitem action="action_view_project_messages_tree" id="menu_message_tree" parent="menu_message_main"/>
<act_window domain="[('user_id', '=', active_id),('state', '&lt;&gt;', 'cancelled'),('state', '&lt;&gt;', 'done')]" id="act_res_users_2_project_task_opened" name="Assigned tasks" res_model="project.task" src_model="res.users" view_mode="tree,form,gantt,calendar,graph" view_type="form"/>
<act_window domain="[('user_id', '=', active_id),('date', '&gt;=', time.strftime('%Y-%m-01'))]" id="act_res_users_2_project_task_work_month" name="Month works" res_model="project.task.work" src_model="res.users" view_mode="tree,form" view_type="form"/>
</data>
</openerp>
</openerp>

View File

@ -36,5 +36,60 @@
<field name="rule_group" ref="task_comp_rule_group"/>
</record>
<!--rule for Tasks-->
<record model="ir.rule.group" id="project_task_rule_group">
<field name="name">project.task.rule.group</field>
<field name="model_id" search="[('model','=','project.task')]" model="ir.model"/>
<field name="global" eval="True"/>
</record>
<record id="project_task_rule" model="ir.rule">
<field model="ir.model.fields" name="field_id" search="[('model','=','project.task'),('name','=','project_id')]"/>
<field name="operator">=</field>
<field name="operand">user.project_id.id</field>
<field name="domain_force">['|',('project_id','=',False),('project_id','=',[user.project_id.id])]</field>
<field name="rule_group" ref="project_task_rule_group"/>
</record>
<record model="ir.rule.group" id="project_task_work_rule_group">
<field name="name">project.task.work.rule.group</field>
<field name="model_id" search="[('model','=','project.task.work')]" model="ir.model"/>
<field name="global" eval="True"/>
</record>
<record id="project_task_work_rule" model="ir.rule">
<field model="ir.model.fields" name="field_id" search="[('model','=','project.task.work'),('name','=','task_id.project_id')]"/>
<field name="operator">=</field>
<field name="operand">user.project_id.id</field>
<field name="domain_force">['|',('task_id.project_id','=',False),('task_id.project_id','=',[user.project_id.id])]</field>
<field name="rule_group" ref="project_task_work_rule_group"/>
</record>
<record model="ir.rule.group" id="project_project_rule_group">
<field name="name">project.project.work.rule.group</field>
<field name="model_id" search="[('model','=','project.project')]" model="ir.model"/>
<field name="global" eval="True"/>
</record>
<record id="project_project_rule" model="ir.rule">
<field model="ir.model.fields" name="field_id" search="[('model','=','project.project'),('name','=','id')]"/>
<field name="operator">=</field>
<field name="operand">user.project_id.id</field>
<field name="domain_force">['|',('id','=',False),('id','=',[user.project_id.id])]</field>
<field name="rule_group" ref="project_project_rule_group"/>
</record>
<record model="ir.rule.group" id="project_message_rule_group">
<field name="name">project.project.work.rule.group</field>
<field name="model_id" search="[('model','=','project.message')]" model="ir.model"/>
<field name="global" eval="True"/>
</record>
<record id="project_message_rule" model="ir.rule">
<field model="ir.model.fields" name="field_id" search="[('model','=','project.message'),('name','=','project_id')]"/>
<field name="operator">=</field>
<field name="operand">user.project_id.id</field>
<field name="domain_force">['|',('project_id','=',False),('project_id','=',[user.project_id.id])]</field>
<field name="rule_group" ref="project_message_rule_group"/>
</record>
</data>
</openerp>

View File

@ -166,7 +166,7 @@ class purchase_order(osv.osv):
'state': fields.selection([('draft', 'Request for Quotation'), ('wait', 'Waiting'), ('confirmed', 'Waiting Supplier Ack'), ('approved', 'Approved'),('except_picking', 'Shipping Exception'), ('except_invoice', 'Invoice Exception'), ('done', 'Done'), ('cancel', 'Cancelled')], 'State', readonly=True, help="The state of the purchase order or the quotation request. A quotation is a purchase order in a 'Draft' state. Then the order has to be confirmed by the user, the state switch to 'Confirmed'. Then the supplier must confirm the order to change the state to 'Approved'. When the purchase order is paid and received, the state becomes 'Done'. If a cancel action occurs in the invoice or in the reception of goods, the state becomes in exception.", select=True),
'order_line': fields.one2many('purchase.order.line', 'order_id', 'Order Lines', states={'approved':[('readonly',True)]}),
'validator' : fields.many2one('res.users', 'Validated by', readonly=True),
'notes': fields.text('Notes'),
'notes': fields.text('Notes', translate=True),
'invoice_id': fields.many2one('account.invoice', 'Invoice', readonly=True),
'picking_ids': fields.one2many('stock.picking', 'purchase_id', 'Picking List', readonly=True, help="This is the list of picking list that have been generated for this purchase"),
'shipped':fields.boolean('Received', readonly=True, select=True),
@ -453,7 +453,7 @@ class purchase_order_line(osv.osv):
'move_dest_id': fields.many2one('stock.move', 'Reservation Destination', ondelete='set null'),
'price_unit': fields.float('Unit Price', required=True, digits=(16, int(config['price_accuracy']))),
'price_subtotal': fields.function(_amount_line, method=True, string='Subtotal', digits=(16, int(config['price_accuracy']))),
'notes': fields.text('Notes'),
'notes': fields.text('Notes', translate=True),
'order_id': fields.many2one('purchase.order', 'Order Reference', select=True, required=True, ondelete='cascade'),
'account_analytic_id':fields.many2one('account.analytic.account', 'Analytic Account',),
'company_id': fields.related('order_id','company_id',type='many2one',relation='res.company',string='Company')

View File

@ -230,7 +230,7 @@ class sale_order(osv.osv):
'invoiced_rate': fields.function(_invoiced_rate, method=True, string='Invoiced', type='float'),
'invoiced': fields.function(_invoiced, method=True, string='Paid',
fnct_search=_invoiced_search, type='boolean'),
'note': fields.text('Notes'),
'note': fields.text('Notes', translate=True),
'amount_untaxed': fields.function(_amount_all, method=True, digits=(16, int(config['price_accuracy'])), string='Untaxed Amount',
store = {
@ -773,7 +773,7 @@ class sale_order_line(osv.osv):
'move_ids': fields.one2many('stock.move', 'sale_line_id', 'Inventory Moves', readonly=True),
'discount': fields.float('Discount (%)', digits=(16, 2)),
'number_packages': fields.function(_number_packages, method=True, type='integer', string='Number Packages'),
'notes': fields.text('Notes'),
'notes': fields.text('Notes', translate=True),
'th_weight': fields.float('Weight'),
'state': fields.selection([('draft', 'Draft'),('confirmed', 'Confirmed'),('done', 'Done'),('cancel', 'Cancelled'),('exception', 'Exception')], 'State', required=True, readonly=True,
help=' * The \'Draft\' state is set automatically when sale order in draft state. \

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
@ -38,7 +38,11 @@ crm modules.
'website': 'http://www.openerp.com',
'depends': ['sale', 'crm'],
'init_xml': [],
'update_xml': ['sale_crm_wizard.xml', 'sale_crm_view.xml', 'process/sale_crm_process.xml'],
'update_xml': ['sale_crm_wizard.xml',
'sale_crm_view.xml',
'process/sale_crm_process.xml',
'security/sale_crm_security.xml',
],
'demo_xml': [],
'installable': True,
'active': False,

View File

@ -23,10 +23,19 @@ from osv import osv,fields
class sale_order(osv.osv):
_inherit = 'sale.order'
_description = 'Sale orders'
_columns = {
'section_id': fields.many2one('crm.case.section', 'Section'),
}
}
def _get_section(self, cr, uid, context):
user = self.pool.get('res.users').browse(cr,uid,uid)
return user.section_id.id
_defaults = {
'section_id':_get_section
}
sale_order()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -25,7 +25,7 @@
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
<xpath expr="/form/notebook/page[@string='Other data']/field[@name='company_id']" position="after">
<field name="section_id"/>
<field name="section_id" widget='selection'/>
</xpath>
</field>
</record>

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="0">
<record model="ir.rule.group" id="sale_order_crm_rule_group">
<field name="name">Sale Order sale_crm</field>
<field name="model_id" search="[('model','=','sale.order')]" model="ir.model"/>
<field name="global" eval="True"/>
</record>
<record model="ir.rule" id="sale_order_comp_rule">
<field name="field_id" search="[('model','=','sale.order'),('name','=','section_id')]" model="ir.model.fields"/>
<field name="operator">=</field>
<field name="operand">user.section_id.id</field>
<field name="rule_group" ref="sale_order_crm_rule_group"/>
<field name="domain_force">['|',('section_id','=',False),('section_id','=',[user.section_id.id])]</field>
</record>
<record model="ir.rule.group" id="sale_order_line_crm_rule_group">
<field name="name">Sale Order Line sale_crm</field>
<field name="model_id" search="[('model','=','sale.order.line')]" model="ir.model"/>
<field name="global" eval="True"/>
</record>
<record model="ir.rule" id="sale_order_line_comp_rule">
<field name="field_id" search="[('model','=','sale.order.line'),('name','=','order_id.section_id')]" model="ir.model.fields"/>
<field name="operator">=</field>
<field name="operand">user.section_id.id</field>
<field name="rule_group" ref="sale_order_line_crm_rule_group"/>
<field name="domain_force">['|',('order_id.section_id','=',False),('order_id.section_id','=',[user.section_id.id])]</field>
</record>
</data>
</openerp>

View File

@ -121,13 +121,13 @@ def _create_invoice(obj, cr, uid, data, context):
raise wizard.except_wizard(_('Error'), _('Invoice is not created'))
if type == 'out_invoice':
xml_id = 'action_invoice_tree5'
xml_id = 'action_invoice_tree1'
elif type == 'in_invoice':
xml_id = 'action_invoice_tree8'
xml_id = 'action_invoice_tree2'
elif type == 'out_refund':
xml_id = 'action_invoice_tree10'
xml_id = 'action_invoice_tree3'
else:
xml_id = 'action_invoice_tree12'
xml_id = 'action_invoice_tree4'
result = mod_obj._get_id(cr, uid, 'account', xml_id)
id = mod_obj.read(cr, uid, result, ['res_id'])

View File

@ -83,6 +83,7 @@ def _create_returns(self, cr, uid, data, context):
new_picking=None
date_cur=time.strftime('%Y-%m-%d %H:%M:%S')
set_invoice_state_to_none = True
for move in move_obj.browse(cr, uid, data['form'].get('returns',[])):
if not new_picking:
if pick.type=='out':
@ -95,15 +96,28 @@ def _create_returns(self, cr, uid, data, context):
'move_lines':[], 'state':'draft', 'type':new_type,
'date':date_cur, 'invoice_state':data['form']['invoice_state'],})
new_location=move.location_dest_id.id
new_qty = data['form']['return%s' % move.id]
returned_qty = move.product_qty
for rec in move.move_stock_return_history:
returned_qty -= rec.product_qty
if returned_qty != new_qty:
set_invoice_state_to_none = False
new_move=move_obj.copy(cr, uid, move.id, {
'product_qty': data['form']['return%s' % move.id],
'product_qty': new_qty,
'product_uos_qty': uom_obj._compute_qty(cr, uid, move.product_uom.id,
data['form']['return%s' % move.id], move.product_uos.id),
new_qty, move.product_uos.id),
'picking_id':new_picking, 'state':'draft',
'location_id':new_location, 'location_dest_id':move.location_id.id,
'date':date_cur, 'date_planned':date_cur,})
move_obj.write(cr, uid, [move.id], {'move_stock_return_history':[(4,new_move)]})
if set_invoice_state_to_none:
pick_obj.write(cr, uid, [pick.id], {'invoice_state':'none'})
if new_picking:
wf_service = netsvc.LocalService("workflow")
if new_picking: