Merge with lp:~openerp-dev/openobject-addons/trunk-dev-addons3
bzr revid: sbh@tinyerp.com-20100624101452-uklaltn5iwgi4t0n
This commit is contained in:
@@ -72,8 +72,8 @@
|
||||
<field name="priority">2</field>
|
||||
<field name="inherit_id" ref="base.view_partner_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<notebook>
|
||||
<page string="Accounting" position="inside">
|
||||
<page string="Notes" position="before">
|
||||
<page string="Accounting">
|
||||
<group col="2" colspan="2">
|
||||
<separator string="Customer Accounting Properties" colspan="2"/>
|
||||
<field name="property_account_receivable" groups="account.group_account_user" />
|
||||
@@ -121,7 +121,7 @@
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
</notebook>
|
||||
</page>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
+335
-230
@@ -25,6 +25,7 @@ from tools.translate import _
|
||||
import ir
|
||||
import pooler
|
||||
import time
|
||||
import tools
|
||||
|
||||
class audittrail_rule(osv.osv):
|
||||
"""
|
||||
@@ -33,25 +34,28 @@ class audittrail_rule(osv.osv):
|
||||
_name = 'audittrail.rule'
|
||||
_description = "Audittrail Rule"
|
||||
_columns = {
|
||||
"name": fields.char("Rule Name", size=32, required=True),
|
||||
"object_id": fields.many2one('ir.model', 'Object', required=True),
|
||||
"user_id": fields.many2many('res.users', 'audittail_rules_users',
|
||||
'user_id', 'rule_id', 'Users'),
|
||||
"log_read": fields.boolean("Log reads"),
|
||||
"log_write": fields.boolean("Log writes"),
|
||||
"log_unlink": fields.boolean("Log deletes"),
|
||||
"log_create": fields.boolean("Log creates"),
|
||||
"state": fields.selection((("draft", "Draft"),
|
||||
("subscribed", "Subscribed")),
|
||||
"State", required=True),
|
||||
"action_id": fields.many2one('ir.actions.act_window', "Action ID"),
|
||||
"name": fields.char("Rule Name", size=32, required=True),
|
||||
"object_id": fields.many2one('ir.model', 'Object', required=True),
|
||||
"user_id": fields.many2many('res.users', 'audittail_rules_users',
|
||||
'user_id', 'rule_id', 'Users', help="if User is not added then it will applicable for all users"),
|
||||
"log_read": fields.boolean("Log Reads"),
|
||||
"log_write": fields.boolean("Log Writes"),
|
||||
"log_unlink": fields.boolean("Log Deletes"),
|
||||
"log_create": fields.boolean("Log Creates"),
|
||||
"log_action": fields.boolean("Log Action"),
|
||||
"log_workflow": fields.boolean("Log Workflow"),
|
||||
"state": fields.selection((("draft", "Draft"),
|
||||
("subscribed", "Subscribed")),
|
||||
"State", required=True),
|
||||
"action_id": fields.many2one('ir.actions.act_window', "Action ID"),
|
||||
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'state': lambda *a: 'draft',
|
||||
'log_create': lambda *a: 1,
|
||||
'log_unlink': lambda *a: 1,
|
||||
'log_write': lambda *a: 1,
|
||||
'state': lambda *a: 'draft',
|
||||
'log_create': lambda *a: 1,
|
||||
'log_unlink': lambda *a: 1,
|
||||
'log_write': lambda *a: 1,
|
||||
}
|
||||
|
||||
_sql_constraints = [
|
||||
@@ -65,7 +69,7 @@ class audittrail_rule(osv.osv):
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ids: List of Auddittrail Rule’s IDs.
|
||||
@return: True
|
||||
@return: True
|
||||
"""
|
||||
obj_action = self.pool.get('ir.actions.act_window')
|
||||
obj_model = self.pool.get('ir.model.data')
|
||||
@@ -74,20 +78,20 @@ class audittrail_rule(osv.osv):
|
||||
obj = self.pool.get(thisrule.object_id.model)
|
||||
if not obj:
|
||||
raise osv.except_osv(
|
||||
_('WARNING: audittrail is not part of the pool'),
|
||||
_('WARNING: audittrail is not part of the pool'),
|
||||
_('Change audittrail depends -- Setting rule as DRAFT'))
|
||||
self.write(cr, uid, [thisrule.id], {"state": "draft"})
|
||||
val = {
|
||||
"name": 'View Log',
|
||||
"res_model": 'audittrail.log',
|
||||
"src_model": thisrule.object_id.model,
|
||||
"name": 'View Log',
|
||||
"res_model": 'audittrail.log',
|
||||
"src_model": thisrule.object_id.model,
|
||||
"domain": "[('object_id','=', " + str(thisrule.object_id.id) + "), ('res_id', '=', active_id)]"
|
||||
|
||||
}
|
||||
id = obj_action.create(cr, uid, val)
|
||||
self.write(cr, uid, [thisrule.id], {"state": "subscribed", "action_id": id})
|
||||
action_id = obj_action.create(cr, uid, val)
|
||||
self.write(cr, uid, [thisrule.id], {"state": "subscribed", "action_id": action_id})
|
||||
keyword = 'client_action_relate'
|
||||
value = 'ir.actions.act_window,' + str(id)
|
||||
value = 'ir.actions.act_window,' + str(action_id)
|
||||
res = obj_model.ir_set(cr, uid, 'action', keyword, 'View_log_' + thisrule.object_id.model, [thisrule.object_id.model], value, replace=True, isobject=True, xml_id=False)
|
||||
#End Loop
|
||||
return True
|
||||
@@ -98,7 +102,7 @@ class audittrail_rule(osv.osv):
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ids: List of Auddittrail Rule’s IDs.
|
||||
@return: True
|
||||
@return: True
|
||||
"""
|
||||
obj_action = self.pool.get('ir.actions.act_window')
|
||||
val_obj = self.pool.get('ir.values')
|
||||
@@ -127,17 +131,28 @@ class audittrail_log(osv.osv):
|
||||
_name = 'audittrail.log'
|
||||
_description = "Audittrail Log"
|
||||
|
||||
def _name_get_resname(self, cr, uid, ids, *args):
|
||||
data = {}
|
||||
for resname in self.browse(cr, uid, ids,[]):
|
||||
model_object = resname.object_id
|
||||
res_id = resname.res_id
|
||||
if model_object and res_id:
|
||||
model_pool = self.pool.get(model_object.model)
|
||||
res = model_pool.read(cr, uid, res_id, ['name'])
|
||||
data[resname.id] = res['name']
|
||||
else:
|
||||
data[resname.id] = False
|
||||
return data
|
||||
|
||||
_columns = {
|
||||
"name": fields.char("Name", size=32),
|
||||
"object_id": fields.many2one('ir.model', 'Object'),
|
||||
"user_id": fields.many2one('res.users', 'User'),
|
||||
"method": fields.selection((('read', 'Read'),
|
||||
('write', 'Write'),
|
||||
('unlink', 'Delete'),
|
||||
('create', 'Create')), "Method"),
|
||||
"timestamp": fields.datetime("Date"),
|
||||
"res_id": fields.integer('Resource Id'),
|
||||
"line_ids": fields.one2many('audittrail.log.line', 'log_id', 'Log lines'),
|
||||
"name": fields.char("Resource Name",size=64),
|
||||
# "name": fields.function(_name_get_resname, type='char', string='Resource Name', method=True),
|
||||
"object_id": fields.many2one('ir.model', 'Object'),
|
||||
"user_id": fields.many2one('res.users', 'User'),
|
||||
"method": fields.char("Method", size=64),
|
||||
"timestamp": fields.datetime("Date"),
|
||||
"res_id": fields.integer('Resource Id'),
|
||||
"line_ids": fields.one2many('audittrail.log.line', 'log_id', 'Log lines'),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
@@ -155,14 +170,14 @@ class audittrail_log_line(osv.osv):
|
||||
_name = 'audittrail.log.line'
|
||||
_description = "Log Line"
|
||||
_columns = {
|
||||
'field_id': fields.many2one('ir.model.fields', 'Fields', required=True),
|
||||
'log_id': fields.many2one('audittrail.log', 'Log'),
|
||||
'log': fields.integer("Log ID"),
|
||||
'old_value': fields.text("Old Value"),
|
||||
'new_value': fields.text("New Value"),
|
||||
'old_value_text': fields.text('Old value Text'),
|
||||
'new_value_text': fields.text('New value Text'),
|
||||
'field_description': fields.char('Field Description', size=64),
|
||||
'field_id': fields.many2one('ir.model.fields', 'Fields', required=True),
|
||||
'log_id': fields.many2one('audittrail.log', 'Log'),
|
||||
'log': fields.integer("Log ID"),
|
||||
'old_value': fields.text("Old Value"),
|
||||
'new_value': fields.text("New Value"),
|
||||
'old_value_text': fields.text('Old value Text'),
|
||||
'new_value_text': fields.text('New value Text'),
|
||||
'field_description': fields.char('Field Description', size=64),
|
||||
}
|
||||
|
||||
audittrail_log_line()
|
||||
@@ -170,276 +185,366 @@ audittrail_log_line()
|
||||
|
||||
class audittrail_objects_proxy(osv_pool):
|
||||
""" Uses Object proxy for auditing changes on object of subscribed Rules"""
|
||||
|
||||
def get_value_text(self, cr, uid, field_name, values, object, context=None):
|
||||
|
||||
def get_value_text(self, cr, uid, field_name, values, model, context=None):
|
||||
"""
|
||||
Gets textual values for the fields
|
||||
e.g.: For field of type many2one it gives its name value instead of id
|
||||
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param field_name: List of fields for text values
|
||||
@param values: Values for field to be converted into textual values
|
||||
@return: values: List of textual values for given fields
|
||||
@param field_name: List of fields for text values
|
||||
@param values: Values for field to be converted into textual values
|
||||
@return: values: List of textual values for given fields
|
||||
"""
|
||||
if not context:
|
||||
context = {}
|
||||
pool = pooler.get_pool(cr.dbname)
|
||||
f_id = pool.get('ir.model.fields').search(cr, uid, [('name', '=', field_name), ('model_id', '=', object.id)])
|
||||
if f_id:
|
||||
field = pool.get('ir.model.fields').read(cr, uid, f_id)[0]
|
||||
model = field['relation']
|
||||
field_pool = pool.get('ir.model.fields')
|
||||
model_pool = pool.get('ir.model')
|
||||
obj_pool = pool.get(model.model)
|
||||
if obj_pool._inherits:
|
||||
inherits_ids = model_pool.search(cr, uid, [('model', '=', obj_pool._inherits.keys()[0])])
|
||||
field_ids = field_pool.search(cr, uid, [('name', '=', field_name), ('model_id', 'in', (model.id, inherits_ids[0]))])
|
||||
else:
|
||||
field_ids = field_pool.search(cr, uid, [('name', '=', field_name), ('model_id', '=', model.id)])
|
||||
field_id = field_ids and field_ids[0] or False
|
||||
assert field_id, _("'%s' field is not exits in '%s' model" %(field_name, model.model))
|
||||
|
||||
if field['ttype'] == 'many2one':
|
||||
if values:
|
||||
if type(values) == tuple:
|
||||
values = values[0]
|
||||
val = pool.get(model).read(cr, uid, [values], [pool.get(model)._rec_name])
|
||||
if val:
|
||||
return val[0][pool.get(model)._rec_name]
|
||||
elif field['ttype'] == 'many2many':
|
||||
value = []
|
||||
if values:
|
||||
for id in values:
|
||||
val = pool.get(model).read(cr, uid, [id], [pool.get(model)._rec_name])
|
||||
if val:
|
||||
value.append(val[0][pool.get(model)._rec_name])
|
||||
return value
|
||||
field = field_pool.read(cr, uid, field_id)
|
||||
relation_model = field['relation']
|
||||
relation_model_pool = relation_model and pool.get(relation_model) or False
|
||||
|
||||
elif field['ttype'] == 'one2many':
|
||||
if values:
|
||||
value = []
|
||||
for id in values:
|
||||
val = pool.get(model).read(cr, uid, [id], [pool.get(model)._rec_name])
|
||||
if field['ttype'] == 'many2one':
|
||||
res = False
|
||||
relation_id = False
|
||||
if values and type(values) == tuple:
|
||||
relation_id = values[0]
|
||||
if relation_id and relation_model_pool:
|
||||
relation_model_object = relation_model_pool.read(cr, uid, relation_id, [relation_model_pool._rec_name])
|
||||
res = relation_model_object[relation_model_pool._rec_name]
|
||||
return res
|
||||
|
||||
if val:
|
||||
value.append(val[0][pool.get(model)._rec_name])
|
||||
return value
|
||||
return values
|
||||
elif field['ttype'] in ('many2many','one2many'):
|
||||
res = []
|
||||
for relation_model_object in relation_model_pool.read(cr, uid, values, [relation_model_pool._rec_name]):
|
||||
res.append(relation_model_object[relation_model_pool._rec_name])
|
||||
return res
|
||||
|
||||
def create_log_line(self, cr, uid, id, object, lines=[]):
|
||||
return values
|
||||
|
||||
def create_log_line(self, cr, uid, log_id, model, lines=[]):
|
||||
"""
|
||||
Creates lines for changed fields with its old and new values
|
||||
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param object: Object who's values are being changed
|
||||
@param model: Object who's values are being changed
|
||||
@param lines: List of values for line is to be created
|
||||
"""
|
||||
|
||||
pool = pooler.get_pool(cr.dbname)
|
||||
obj = pool.get(object.model)
|
||||
obj_pool = pool.get(model.model)
|
||||
model_pool = pool.get('ir.model')
|
||||
field_pool = pool.get('ir.model.fields')
|
||||
log_line_pool = pool.get('audittrail.log.line')
|
||||
#start Loop
|
||||
for line in lines:
|
||||
if obj._inherits:
|
||||
inherits_ids = pool.get('ir.model').search(cr, uid, [('model', '=', obj._inherits.keys()[0])])
|
||||
f_id = pool.get('ir.model.fields').search(cr, uid, [('name', '=', line['name']), ('model_id', 'in', (object.id, inherits_ids[0]))])
|
||||
if obj_pool._inherits:
|
||||
inherits_ids = model_pool.search(cr, uid, [('model', '=', obj_pool._inherits.keys()[0])])
|
||||
field_ids = field_pool.search(cr, uid, [('name', '=', line['name']), ('model_id', 'in', (model.id, inherits_ids[0]))])
|
||||
else:
|
||||
f_id = pool.get('ir.model.fields').search(cr, uid, [('name', '=', line['name']), ('model_id', '=', object.id)])
|
||||
if f_id:
|
||||
fields = pool.get('ir.model.fields').read(cr, uid, f_id)
|
||||
old_value = 'old_value' in line and line['old_value'] or ''
|
||||
new_value = 'new_value' in line and line['new_value'] or ''
|
||||
old_value_text = 'old_value_text' in line and line['old_value_text'] or ''
|
||||
new_value_text = 'new_value_text' in line and line['new_value_text'] or ''
|
||||
|
||||
if old_value_text == new_value_text:
|
||||
continue
|
||||
if fields[0]['ttype'] == 'many2one':
|
||||
if type(old_value) == tuple:
|
||||
old_value = old_value[0]
|
||||
if type(new_value) == tuple:
|
||||
new_value = new_value[0]
|
||||
vals = {
|
||||
"log_id": id,
|
||||
"field_id": f_id[0],
|
||||
"old_value": old_value,
|
||||
"new_value": new_value,
|
||||
"old_value_text": old_value_text,
|
||||
"new_value_text": new_value_text,
|
||||
"field_description": fields[0]['field_description']
|
||||
}
|
||||
line_id = pool.get('audittrail.log.line').create(cr, uid, vals)
|
||||
cr.commit()
|
||||
#End Loop
|
||||
field_ids = field_pool.search(cr, uid, [('name', '=', line['name']), ('model_id', '=', model.id)])
|
||||
field_id = field_ids and field_ids[0] or False
|
||||
assert field_id, _("'%s' field is not exits in '%s' model" %(line['name'], model.model))
|
||||
|
||||
field = field_pool.read(cr, uid, field_id)
|
||||
old_value = 'old_value' in line and line['old_value'] or ''
|
||||
new_value = 'new_value' in line and line['new_value'] or ''
|
||||
old_value_text = 'old_value_text' in line and line['old_value_text'] or ''
|
||||
new_value_text = 'new_value_text' in line and line['new_value_text'] or ''
|
||||
|
||||
if old_value_text == new_value_text:
|
||||
continue
|
||||
if field['ttype'] == 'many2one':
|
||||
if type(old_value) == tuple:
|
||||
old_value = old_value[0]
|
||||
if type(new_value) == tuple:
|
||||
new_value = new_value[0]
|
||||
vals = {
|
||||
"log_id": log_id,
|
||||
"field_id": field_id,
|
||||
"old_value": old_value,
|
||||
"new_value": new_value,
|
||||
"old_value_text": old_value_text,
|
||||
"new_value_text": new_value_text,
|
||||
"field_description": field['field_description']
|
||||
}
|
||||
line_id = log_line_pool.create(cr, uid, vals)
|
||||
#End Loop
|
||||
return True
|
||||
|
||||
def log_fct(self, db, uid, object, method, fct_src, *args):
|
||||
|
||||
def log_fct(self, db, uid, model, method, fct_src, *args):
|
||||
"""
|
||||
Logging function: This function is performs logging oprations according to method
|
||||
@param db: the current database
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param object: Object who's values are being changed
|
||||
@param method: method to log: create, read, write, unlink
|
||||
@param method: method to log: create, read, write, unlink
|
||||
@param fct_src: execute method of Object proxy
|
||||
|
||||
@return: Returns result as per method of Object proxy
|
||||
|
||||
@return: Returns result as per method of Object proxy
|
||||
"""
|
||||
logged_uids = []
|
||||
res2 = args
|
||||
pool = pooler.get_pool(db)
|
||||
cr = pooler.get_db(db).cursor()
|
||||
obj_ids = pool.get('ir.model').search(cr, uid, [('model', '=', object)])
|
||||
model_object = pool.get('ir.model').browse(cr, uid, obj_ids)[0]
|
||||
resource_pool = pool.get(model)
|
||||
log_pool = pool.get('audittrail.log')
|
||||
model_pool = pool.get('ir.model')
|
||||
|
||||
model_ids = model_pool.search(cr, uid, [('model', '=', model)])
|
||||
model_id = model_ids and model_ids[0] or False
|
||||
assert model_id, _("'%s' Model is not exits..." %(model))
|
||||
model = model_pool.browse(cr, uid, model_id)
|
||||
|
||||
if method in ('create'):
|
||||
res_id = fct_src(db, uid, object, method, *args)
|
||||
res_id = fct_src(db, uid, model.model, method, *args)
|
||||
cr.commit()
|
||||
new_value = pool.get(model_object.model).read(cr, uid, [res_id], args[0].keys())[0]
|
||||
if 'id' in new_value:
|
||||
del new_value['id']
|
||||
if not logged_uids or uid in logged_uids:
|
||||
resource_name = pool.get(model_object.model).name_get(cr, uid, [res_id])
|
||||
resource_name = resource_name and resource_name[0][1] or ''
|
||||
vals = {
|
||||
"method": method,
|
||||
"object_id": model_object.id,
|
||||
"user_id": uid, "res_id": res_id,
|
||||
"name": resource_name
|
||||
}
|
||||
id = pool.get('audittrail.log').create(cr, uid, vals)
|
||||
lines = []
|
||||
for field in new_value:
|
||||
if new_value[field]:
|
||||
line = {
|
||||
'name': field,
|
||||
'new_value': new_value[field],
|
||||
'new_value_text': self.get_value_text(cr, uid, field, new_value[field], model_object)
|
||||
}
|
||||
lines.append(line)
|
||||
self.create_log_line(cr, uid, id, model_object, lines)
|
||||
resource = resource_pool.read(cr, uid, res_id, args[0].keys())
|
||||
vals = {
|
||||
"method": method,
|
||||
"object_id": model.id,
|
||||
"user_id": uid,
|
||||
"res_id": resource['id'],
|
||||
}
|
||||
if 'id' in resource:
|
||||
del resource['id']
|
||||
log_id = log_pool.create(cr, uid, vals)
|
||||
lines = []
|
||||
for field in resource:
|
||||
line = {
|
||||
'name': field,
|
||||
'new_value': resource[field],
|
||||
'new_value_text': self.get_value_text(cr, uid, field, resource[field], model)
|
||||
}
|
||||
lines.append(line)
|
||||
self.create_log_line(cr, uid, log_id, model, lines)
|
||||
|
||||
cr.commit()
|
||||
cr.close()
|
||||
return res_id
|
||||
|
||||
if method in ('write'):
|
||||
res_ids = args[0]
|
||||
for res_id in res_ids:
|
||||
old_values = pool.get(model_object.model).read(cr, uid, res_id, args[1].keys())
|
||||
old_values_text = {}
|
||||
for field in args[1].keys():
|
||||
old_values_text[field] = self.get_value_text(cr, uid, field, old_values[field], model_object)
|
||||
res = fct_src(db, uid, object, method, *args)
|
||||
cr.commit()
|
||||
if res:
|
||||
new_values = pool.get(model_object.model).read(cr, uid, res_ids, args[1].keys())[0]
|
||||
if not logged_uids or uid in logged_uids:
|
||||
resource_name = pool.get(model_object.model).name_get(cr, uid, [res_id])
|
||||
resource_name = resource_name and resource_name[0][1] or ''
|
||||
id = pool.get('audittrail.log').create(cr, uid, {"method": method, "object_id": model_object.id, "user_id": uid, "res_id": res_id, "name": resource_name})
|
||||
lines = []
|
||||
for field in args[1].keys():
|
||||
if args[1].keys():
|
||||
line = {
|
||||
'name': field,
|
||||
'new_value': field in new_values and new_values[field] or '',
|
||||
'old_value': field in old_values and old_values[field] or '',
|
||||
'new_value_text': self.get_value_text(cr, uid, field, new_values[field], model_object),
|
||||
'old_value_text': old_values_text[field]
|
||||
}
|
||||
lines.append(line)
|
||||
cr.commit()
|
||||
self.create_log_line(cr, uid, id, model_object, lines)
|
||||
cr.close()
|
||||
return res
|
||||
|
||||
if method in ('read'):
|
||||
elif method in ('read'):
|
||||
res_ids = args[0]
|
||||
old_values = {}
|
||||
res = fct_src(db, uid, object, method, *args)
|
||||
res = fct_src(db, uid, model.model, method, *args)
|
||||
if type(res) == list:
|
||||
|
||||
for v in res:
|
||||
old_values[v['id']] = v
|
||||
else:
|
||||
old_values[res['id']] = res
|
||||
for res_id in old_values:
|
||||
if not logged_uids or uid in logged_uids:
|
||||
resource_name = pool.get(model_object.model).name_get(cr, uid, [res_id])
|
||||
resource_name = resource_name and resource_name[0][1] or ''
|
||||
id = pool.get('audittrail.log').create(cr, uid, {"method": method, "object_id": model_object.id, "user_id": uid, "res_id": res_id, "name": resource_name})
|
||||
lines = []
|
||||
for field in old_values[res_id]:
|
||||
if old_values[res_id][field]:
|
||||
line = {
|
||||
'name': field,
|
||||
'old_value': old_values[res_id][field],
|
||||
'old_value_text': self.get_value_text(cr, uid, field, old_values[res_id][field], model_object)
|
||||
}
|
||||
lines.append(line)
|
||||
cr.commit()
|
||||
self.create_log_line(cr, uid, id, model_object, lines)
|
||||
vals = {
|
||||
"method": method,
|
||||
"object_id": model.id,
|
||||
"user_id": uid,
|
||||
"res_id": res_id,
|
||||
|
||||
}
|
||||
log_id = log_pool.create(cr, uid, vals)
|
||||
lines = []
|
||||
for field in old_values[res_id]:
|
||||
line = {
|
||||
'name': field,
|
||||
'old_value': old_values[res_id][field],
|
||||
'old_value_text': self.get_value_text(cr, uid, field, old_values[res_id][field], model)
|
||||
}
|
||||
lines.append(line)
|
||||
|
||||
self.create_log_line(cr, uid, log_id, model, lines)
|
||||
|
||||
cr.close()
|
||||
return res
|
||||
|
||||
if method in ('unlink'):
|
||||
elif method in ('unlink'):
|
||||
res_ids = args[0]
|
||||
old_values = {}
|
||||
for res_id in res_ids:
|
||||
old_values[res_id] = pool.get(model_object.model).read(cr, uid, res_id, [])
|
||||
old_values[res_id] = resource_pool.read(cr, uid, res_id)
|
||||
|
||||
for res_id in res_ids:
|
||||
if not logged_uids or uid in logged_uids:
|
||||
resource_name = pool.get(model_object.model).name_get(cr, uid, [res_id])
|
||||
resource_name = resource_name and resource_name[0][1] or ''
|
||||
id = pool.get('audittrail.log').create(cr, uid, {"method": method, "object_id": model_object.id, "user_id": uid, "res_id": res_id, "name": resource_name})
|
||||
lines = []
|
||||
for field in old_values[res_id]:
|
||||
if old_values[res_id][field]:
|
||||
line = {
|
||||
'name': field,
|
||||
'old_value': old_values[res_id][field],
|
||||
'old_value_text': self.get_value_text(cr, uid, field, old_values[res_id][field], model_object)
|
||||
}
|
||||
lines.append(line)
|
||||
cr.commit()
|
||||
self.create_log_line(cr, uid, id, model_object, lines)
|
||||
res = fct_src(db, uid, object, method, *args)
|
||||
vals = {
|
||||
"method": method,
|
||||
"object_id": model.id,
|
||||
"user_id": uid,
|
||||
"res_id": res_id,
|
||||
|
||||
}
|
||||
log_id = log_pool.create(cr, uid, vals)
|
||||
lines = []
|
||||
for field in old_values[res_id]:
|
||||
if field in ('id'):
|
||||
continue
|
||||
line = {
|
||||
'name': field,
|
||||
'old_value': old_values[res_id][field],
|
||||
'old_value_text': self.get_value_text(cr, uid, field, old_values[res_id][field], model)
|
||||
}
|
||||
lines.append(line)
|
||||
|
||||
self.create_log_line(cr, uid, log_id, model, lines)
|
||||
res = fct_src(db, uid, model.model, method, *args)
|
||||
cr.commit()
|
||||
cr.close()
|
||||
return res
|
||||
cr.close()
|
||||
else:
|
||||
res_ids = args[0]
|
||||
old_values = {}
|
||||
fields = []
|
||||
if len(args)>1 and type(args[1]) == dict:
|
||||
fields = args[1].keys()
|
||||
if type(res_ids) in (long, int):
|
||||
res_ids = [res_ids]
|
||||
if res_ids:
|
||||
for resource in resource_pool.read(cr, uid, res_ids):
|
||||
resource_id = resource['id']
|
||||
if 'id' in resource:
|
||||
del resource['id']
|
||||
old_values_text = {}
|
||||
old_value = {}
|
||||
for field in resource.keys():
|
||||
old_value[field] = resource[field]
|
||||
old_values_text[field] = self.get_value_text(cr, uid, field, resource[field], model)
|
||||
old_values[resource_id] = {'text':old_values_text, 'value': old_value}
|
||||
|
||||
def execute(self, db, uid, object, method, *args, **kw):
|
||||
res = fct_src(db, uid, model.model, method, *args)
|
||||
cr.commit()
|
||||
|
||||
if res_ids:
|
||||
for resource in resource_pool.read(cr, uid, res_ids):
|
||||
resource_id = resource['id']
|
||||
if 'id' in resource:
|
||||
del resource['id']
|
||||
vals = {
|
||||
"method": method,
|
||||
"object_id": model.id,
|
||||
"user_id": uid,
|
||||
"res_id": resource_id,
|
||||
}
|
||||
|
||||
|
||||
log_id = log_pool.create(cr, uid, vals)
|
||||
lines = []
|
||||
for field in resource.keys():
|
||||
line = {
|
||||
'name': field,
|
||||
'new_value': resource[field],
|
||||
'old_value': old_values[resource_id]['value'][field],
|
||||
'new_value_text': self.get_value_text(cr, uid, field, resource[field], model),
|
||||
'old_value_text': old_values[resource_id]['text'][field]
|
||||
}
|
||||
lines.append(line)
|
||||
|
||||
self.create_log_line(cr, uid, log_id, model, lines)
|
||||
cr.commit()
|
||||
cr.close()
|
||||
return res
|
||||
return True
|
||||
|
||||
|
||||
|
||||
def execute(self, db, uid, model, method, *args, **kw):
|
||||
"""
|
||||
Overrides Object Proxy execute method
|
||||
@param db: the current database
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param object: Object who's values are being changed
|
||||
@param method: method to log: create, read, write, unlink
|
||||
|
||||
@return: Returns result as per method of Object proxy
|
||||
@param method: get any method and create log
|
||||
|
||||
@return: Returns result as per method of Object proxy
|
||||
"""
|
||||
pool = pooler.get_pool(db)
|
||||
model_pool = pool.get('ir.model')
|
||||
rule_pool = pool.get('audittrail.rule')
|
||||
cr = pooler.get_db(db).cursor()
|
||||
cr.autocommit(True)
|
||||
logged_uids = []
|
||||
fct_src = super(audittrail_objects_proxy, self).execute
|
||||
|
||||
def my_fct(db, uid, object, method, *args):
|
||||
field = method
|
||||
def my_fct(db, uid, model, method, *args):
|
||||
rule = False
|
||||
obj_ids = pool.get('ir.model').search(cr, uid, [('model', '=', object)])
|
||||
for obj_name in pool.obj_list():
|
||||
if obj_name == 'audittrail.rule':
|
||||
model_ids = model_pool.search(cr, uid, [('model', '=', model)])
|
||||
model_id = model_ids and model_ids[0] or False
|
||||
|
||||
for model_name in pool.obj_list():
|
||||
if model_name == 'audittrail.rule':
|
||||
rule = True
|
||||
if not rule:
|
||||
return fct_src(db, uid, object, method, *args)
|
||||
if not obj_ids:
|
||||
return fct_src(db, uid, object, method, *args)
|
||||
rule_ids = pool.get('audittrail.rule').search(cr, uid, [('object_id', '=', obj_ids[0]), ('state', '=', 'subscribed')])
|
||||
if not rule_ids:
|
||||
return fct_src(db, uid, object, method, *args)
|
||||
return fct_src(db, uid, model, method, *args)
|
||||
if not model_id:
|
||||
return fct_src(db, uid, model, method, *args)
|
||||
|
||||
for thisrule in pool.get('audittrail.rule').browse(cr, uid, rule_ids):
|
||||
rule_ids = rule_pool.search(cr, uid, [('object_id', '=', model_id), ('state', '=', 'subscribed')])
|
||||
if not rule_ids:
|
||||
return fct_src(db, uid, model, method, *args)
|
||||
|
||||
for thisrule in rule_pool.browse(cr, uid, rule_ids):
|
||||
for user in thisrule.user_id:
|
||||
logged_uids.append(user.id)
|
||||
if not logged_uids or uid in logged_uids:
|
||||
if field in ('read', 'write', 'create', 'unlink'):
|
||||
if getattr(thisrule, 'log_' + field):
|
||||
return self.log_fct(db, uid, object, method, fct_src, *args)
|
||||
return fct_src(db, uid, object, method, *args)
|
||||
res = my_fct(db, uid, object, method, *args)
|
||||
if method in ('read', 'write', 'create', 'unlink'):
|
||||
if getattr(thisrule, 'log_' + method):
|
||||
return self.log_fct(db, uid, model, method, fct_src, *args)
|
||||
|
||||
elif method not in ('default_get','read','fields_view_get','fields_get','search','search_count','name_search','name_get','get','request_get', 'get_sc', 'unlink', 'write', 'create'):
|
||||
if thisrule.log_action:
|
||||
return self.log_fct(db, uid, model, method, fct_src, *args)
|
||||
|
||||
return fct_src(db, uid, model, method, *args)
|
||||
res = my_fct(db, uid, model, method, *args)
|
||||
cr.close()
|
||||
return res
|
||||
|
||||
|
||||
def exec_workflow(self, db, uid, model, method, *args, **argv):
|
||||
pool = pooler.get_pool(db)
|
||||
cr = pooler.get_db(db).cursor()
|
||||
cr.autocommit(True)
|
||||
logged_uids = []
|
||||
fct_src = super(audittrail_objects_proxy, self).exec_workflow
|
||||
field = method
|
||||
rule = False
|
||||
model_pool = pool.get('ir.model')
|
||||
rule_pool = pool.get('audittrail.rule')
|
||||
model_ids = model_pool.search(cr, uid, [('model', '=', model)])
|
||||
for obj_name in pool.obj_list():
|
||||
if obj_name == 'audittrail.rule':
|
||||
rule = True
|
||||
if not rule:
|
||||
cr.close()
|
||||
return super(audittrail_objects_proxy, self).exec_workflow(db, uid, model, method, *args, **argv)
|
||||
if not model_ids:
|
||||
cr.close()
|
||||
return super(audittrail_objects_proxy, self).exec_workflow(db, uid, model, method, *args, **argv)
|
||||
|
||||
rule_ids = rule_pool.search(cr, uid, [('object_id', 'in', model_ids), ('state', '=', 'subscribed')])
|
||||
if not rule_ids:
|
||||
cr.close()
|
||||
return super(audittrail_objects_proxy, self).exec_workflow(db, uid, model, method, *args, **argv)
|
||||
|
||||
for thisrule in rule_pool.browse(cr, uid, rule_ids):
|
||||
for user in thisrule.user_id:
|
||||
logged_uids.append(user.id)
|
||||
if not logged_uids or uid in logged_uids:
|
||||
if thisrule.log_workflow:
|
||||
cr.close()
|
||||
return self.log_fct(db, uid, model, method, fct_src, *args)
|
||||
cr.close()
|
||||
return super(audittrail_objects_proxy, self).exec_workflow(db, uid, model, method, *args, **argv)
|
||||
|
||||
cr.close()
|
||||
return True
|
||||
|
||||
audittrail_objects_proxy()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -12,12 +12,15 @@
|
||||
<form string="AuditTrail Rule">
|
||||
<field name="name" select="1" required="1"/>
|
||||
<field name="object_id" select="1"/>
|
||||
<field name="log_read" />
|
||||
<field name="log_write" />
|
||||
<field name="log_unlink" />
|
||||
<field name="log_create" />
|
||||
<field name="action_id" colspan="4" readonly="1"/>
|
||||
<field name="user_id" select="1" colspan="4"/>
|
||||
<field name="log_read"/>
|
||||
<field name="log_write"/>
|
||||
<field name="log_unlink"/>
|
||||
<field name="log_create"/>
|
||||
<field name="log_action"/>
|
||||
<field name="log_workflow"/>
|
||||
<separator string="Users (if User is not added then it will applicable for all users)" colspan="4" />
|
||||
<field name="user_id" select="1" colspan="4" nolabel="1" />
|
||||
<field name="action_id" colspan="4" readonly="1" groups="base.group_extended"/>
|
||||
<field name="state" select="1" readonly="1" />
|
||||
<group colspan="2" col="2">
|
||||
<button string="Subscribe" name="subscribe"
|
||||
@@ -42,6 +45,8 @@
|
||||
<field name="log_write" />
|
||||
<field name="log_unlink" />
|
||||
<field name="log_create" />
|
||||
<field name="log_action"/>
|
||||
<field name="log_workflow"/>
|
||||
<field name="state" />
|
||||
</tree>
|
||||
</field>
|
||||
@@ -58,9 +63,10 @@
|
||||
<!--<field name="view_id" ref="view_audittrail_rule_form" />-->
|
||||
</record>
|
||||
|
||||
<menuitem name="Audittrails" id="menu_action_audittrail"
|
||||
<menuitem name="Audittrail" id="menu_action_audittrail"
|
||||
groups="base.group_extended"
|
||||
parent="base.menu_administration" />
|
||||
|
||||
<menuitem name="Rules" id="menu_action_audittrail_rule_tree"
|
||||
action="action_audittrail_rule_tree" parent="menu_action_audittrail" />
|
||||
|
||||
@@ -83,13 +89,13 @@
|
||||
<field name="arch" type="xml">
|
||||
<form string="AuditTrail Logs">
|
||||
<field name="timestamp" select="1" required="1" readonly="1"/>
|
||||
<field name="object_id" select="1" readonly="1"/>
|
||||
<field name="method" select="1" readonly="1"/>
|
||||
<field name="user_id" select="1" readonly="1"/>
|
||||
<field name="res_id" readonly="1"/>
|
||||
<field name="method" select="1" readonly="1"/>
|
||||
<field name="name" readonly="1" select="1"/>
|
||||
<field name="res_id" readonly="1"/>
|
||||
<field name="object_id" select="1" readonly="1"/>
|
||||
<field name="line_ids" colspan="4" mode="tree,form"
|
||||
widget="one2many_list" readonly="1">
|
||||
widget="one2many_list" readonly="1" nolabel="1">
|
||||
<form string="Log Lines">
|
||||
<field name="field_id" colspan="4"
|
||||
readonly="1" />
|
||||
@@ -151,11 +157,7 @@
|
||||
<field name="view_type">form</field>
|
||||
</record>
|
||||
<menuitem name="Logs" id="menu_action_audittrail_log_tree"
|
||||
action="action_audittrail_log_tree" parent="menu_action_audittrail" />
|
||||
|
||||
<!-- <wizard string="View log" menu="False" model="audittrail.log" name="audittrail.view.log" id="wizard_audittrail_log"/>-->
|
||||
<menuitem name="View Logs" id="menu_action_log_tree2"
|
||||
action="action_audittrail_view_log" parent="menu_action_audittrail" />
|
||||
action="action_audittrail_log_tree" parent="menu_action_audittrail" />
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -27,7 +27,9 @@
|
||||
'author': 'Tiny',
|
||||
'website': 'http://www.openerp.com',
|
||||
'depends': ['base'],
|
||||
'init_xml': [],
|
||||
'init_xml': [
|
||||
'base_action_rule_data.xml'
|
||||
],
|
||||
'update_xml': [
|
||||
'base_action_rule_view.xml',
|
||||
'security/ir.model.access.csv',
|
||||
|
||||
@@ -19,14 +19,16 @@
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import time
|
||||
import mx.DateTime
|
||||
import re
|
||||
|
||||
import tools
|
||||
from datetime import datetime
|
||||
from osv import fields, osv, orm
|
||||
from osv.orm import except_orm
|
||||
from osv.osv import osv_pool
|
||||
from tools.translate import _
|
||||
import mx.DateTime
|
||||
import pooler
|
||||
import re
|
||||
import time
|
||||
import tools
|
||||
|
||||
class base_action_rule(osv.osv):
|
||||
""" Base Action Rules """
|
||||
@@ -132,6 +134,71 @@ the rule to mark CC(mail to any other person defined in actions)."),
|
||||
|
||||
_order = 'sequence'
|
||||
|
||||
def pre_action(self, cr, uid, ids, model, context=None):
|
||||
# Searching for action rules
|
||||
cr.execute("SELECT model.model, rule.id FROM base_action_rule rule LEFT JOIN ir_model model on (model.id = rule.name)")
|
||||
res = cr.fetchall()
|
||||
# Check if any rule matching with current object
|
||||
for obj_name, rule_id in res:
|
||||
if not (model == obj_name):
|
||||
continue
|
||||
else:
|
||||
obj = self.pool.get(obj_name)
|
||||
self._action(cr, uid, [rule_id], obj.browse(cr, uid, ids, context=context))
|
||||
return True
|
||||
|
||||
def _create(self, old_create, model, context=None):
|
||||
if not context:
|
||||
context = {}
|
||||
def make_call_old(cr, uid, vals, context=context):
|
||||
new_id = old_create(cr, uid, vals, context=context)
|
||||
if not context.get('action'):
|
||||
self.pre_action(cr, uid, [new_id], model, context=context)
|
||||
return new_id
|
||||
return make_call_old
|
||||
|
||||
def _write(self, old_write, model, context=None):
|
||||
if not context:
|
||||
context = {}
|
||||
def make_call_old(cr, uid, ids, vals, context=context):
|
||||
if isinstance(ids, (str, int, long)):
|
||||
ids = [ids]
|
||||
if not context.get('action'):
|
||||
self.pre_action(cr, uid, ids, model, context=context)
|
||||
return old_write(cr, uid, ids, vals, context=context)
|
||||
return make_call_old
|
||||
|
||||
def _register_hook(self, cr, uid, ids, context=None):
|
||||
if not context:
|
||||
context = {}
|
||||
model_pool = self.pool.get('ir.model')
|
||||
for action_rule in self.browse(cr, uid, ids, context=context):
|
||||
model = action_rule.name.model
|
||||
obj_pool = self.pool.get(model)
|
||||
obj_pool.__setattr__('create', self._create(obj_pool.create, model, context=context))
|
||||
obj_pool.__setattr__('write', self._write(obj_pool.write, model, context=context))
|
||||
return True
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
res_id = super(base_action_rule, self).create(cr, uid, vals, context)
|
||||
self._register_hook(cr, uid, [res_id], context=context)
|
||||
return res_id
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
res = super(base_action_rule, self).write(cr, uid, ids, vals, context)
|
||||
self._register_hook(cr, uid, ids, context=context)
|
||||
return res
|
||||
|
||||
def _check(self, cr, uid, automatic=False, use_new_cursor=False, \
|
||||
context=None):
|
||||
"""
|
||||
This Function is call by scheduler.
|
||||
"""
|
||||
rule_pool= self.pool.get('base.action.rule')
|
||||
rule_ids = rule_pool.search(cr, uid, [], context=context)
|
||||
return self._register_hook(cr, uid, rule_ids, context=context)
|
||||
|
||||
|
||||
def format_body(self, body):
|
||||
""" Foramat Action rule's body
|
||||
@param self: The object pointer """
|
||||
@@ -235,6 +302,7 @@ the rule to mark CC(mail to any other person defined in actions)."),
|
||||
context.update({'active_id':obj.id, 'active_ids':[obj.id]})
|
||||
self.pool.get('ir.actions.server').run(cr, uid, [action.server_action_id.id], context)
|
||||
write = {}
|
||||
|
||||
if hasattr(obj, 'user_id') and action.act_user_id:
|
||||
obj.user_id = action.act_user_id
|
||||
write['user_id'] = action.act_user_id.id
|
||||
@@ -279,12 +347,10 @@ the rule to mark CC(mail to any other person defined in actions)."),
|
||||
@param ids: List of Basic Action Rule’s IDs,
|
||||
@param objects: pass objects
|
||||
@param context: A standard dictionary for contextual values """
|
||||
|
||||
context.update({'action': True})
|
||||
if not scrit:
|
||||
scrit = []
|
||||
cr.execute("select id from base_action_rule order by sequence")
|
||||
rule_ids = map(lambda x: x[0], cr.fetchall())
|
||||
for action in self.browse(cr, uid, rule_ids):
|
||||
for action in self.browse(cr, uid, ids):
|
||||
level = action.max_level
|
||||
if not level:
|
||||
break
|
||||
@@ -333,6 +399,7 @@ the rule to mark CC(mail to any other person defined in actions)."),
|
||||
self.do_action(cr, uid, action, model_obj, obj, context)
|
||||
break
|
||||
level -= 1
|
||||
context.update({'action': False})
|
||||
return True
|
||||
|
||||
def _check_mail(self, cr, uid, ids, context=None):
|
||||
@@ -359,4 +426,27 @@ the rule to mark CC(mail to any other person defined in actions)."),
|
||||
|
||||
base_action_rule()
|
||||
|
||||
|
||||
class ir_cron(osv.osv):
|
||||
_inherit = 'ir.cron'
|
||||
|
||||
def _poolJobs(self, db_name, check=False):
|
||||
try:
|
||||
db, pool = pooler.get_db_and_pool(db_name)
|
||||
except:
|
||||
return False
|
||||
cr = db.cursor()
|
||||
try:
|
||||
next = datetime.now().strftime('%Y-%m-%d %H:00:00')
|
||||
# Putting nextcall always less than current time in order to call it every time
|
||||
cr.execute('UPDATE ir_cron set nextcall = \'%s\' where numbercall<>0 and active and model=\'base.action.rule\' ' % (next))
|
||||
cr.commit()
|
||||
res = super(ir_cron, self)._poolJobs(db_name, check=check)
|
||||
finally:
|
||||
cr.commit()
|
||||
cr.close()
|
||||
|
||||
ir_cron()
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
<record id="ir_cron_crm_action" model="ir.cron">
|
||||
<field name="name">Check Action Rules</field>
|
||||
<field name="interval_number">4</field>
|
||||
<field name="interval_type">hours</field>
|
||||
<field name="numbercall">-1</field>
|
||||
<field eval="False" name="doall"/>
|
||||
<field eval="'base.action.rule'" name="model"/>
|
||||
<field eval="'_check'" name="function"/>
|
||||
<field eval="'()'" name="args"/>
|
||||
</record>
|
||||
|
||||
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -20,5 +20,7 @@
|
||||
##############################################################################
|
||||
|
||||
import base_contact
|
||||
import base_contact_installer
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
'update_xml': [
|
||||
'security/ir.model.access.csv',
|
||||
'base_contact_view.xml',
|
||||
'base_contact_installer_view.xml',
|
||||
'process/base_contact_process.xml'
|
||||
],
|
||||
'demo_xml': ['base_contact_demo.xml'],
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from lxml import etree
|
||||
from osv import fields, osv
|
||||
|
||||
class base_contact_installer(osv.osv_memory):
|
||||
_name = 'base.contact.installer'
|
||||
_inherit = 'res.config.installer'
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Name', size=64),
|
||||
'migrate': fields.boolean('Migrate', help="If you select this, all addresses will be migrated."),
|
||||
}
|
||||
|
||||
def execute(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
This function is used to create contact and address from existing partner address
|
||||
"""
|
||||
cr.execute("""DROP TRIGGER IF EXISTS contactjob on res_partner_contact;
|
||||
DROP LANGUAGE IF EXISTS plpgsql CASCADE;
|
||||
CREATE LANGUAGE plpgsql ;
|
||||
CREATE OR REPLACE FUNCTION add_to_job() RETURNS TRIGGER AS $contactjob$
|
||||
DECLARE
|
||||
new_name varchar;
|
||||
new_phonenum varchar;
|
||||
BEGIN
|
||||
IF(TG_OP='INSERT') THEN
|
||||
INSERT INTO res_partner_job(contact_id, address_id, function, state) VALUES(NEW.id, NEW.website::integer,NEW.first_name, 'current');
|
||||
UPDATE res_partner_contact set first_name=Null, website=Null, active=True where id=NEW.id;
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$contactjob$ LANGUAGE plpgsql;
|
||||
CREATE TRIGGER contactjob AFTER INSERT ON res_partner_contact FOR EACH ROW EXECUTE PROCEDURE add_to_job();""")
|
||||
cr.commit()
|
||||
|
||||
cr.execute("INSERT into res_partner_contact (name, title, email, first_name, website) (SELECT coalesce(name, 'Noname'), title, email, function , to_char(id, '99999999') from res_partner_address)")
|
||||
cr.commit()
|
||||
|
||||
cr.execute("DROP TRIGGER IF EXISTS contactjob on res_partner_contact")
|
||||
cr.execute("DROP LANGUAGE IF EXISTS plpgsql CASCADE;")
|
||||
cr.execute("DROP FUNCTION IF EXISTS add_to_job()")
|
||||
cr.commit()
|
||||
|
||||
base_contact_installer()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
@@ -0,0 +1,56 @@
|
||||
<openerp>
|
||||
<data>
|
||||
<record id="view_base_contact_installer" model="ir.ui.view">
|
||||
<field name="name">base.contact.installer.view</field>
|
||||
<field name="model">base.contact.installer</field>
|
||||
<field name="type">form</field>
|
||||
<field name="inherit_id" ref="base.res_config_installer"/>
|
||||
<field name="arch" type="xml">
|
||||
<data>
|
||||
<form position="attributes">
|
||||
<attribute name="string">Address's Migration to Contacts</attribute>
|
||||
</form>
|
||||
|
||||
<separator string="title" position="attributes">
|
||||
<attribute name="string">Select the Option for Addresses Migration</attribute>
|
||||
</separator>
|
||||
<xpath expr="//label[@string='description']"
|
||||
position="attributes">
|
||||
<attribute name="string">You can migrate Partner's current addresses to the contact.</attribute>
|
||||
</xpath>
|
||||
<xpath expr='//separator[@string="vsep"]' position='attributes'>
|
||||
<attribute name='rowspan'>13</attribute>
|
||||
<attribute name='string'></attribute>
|
||||
</xpath>
|
||||
<xpath expr="//button[@string='Install Modules']" position="attributes">
|
||||
<attribute name="string">Migrate</attribute>
|
||||
</xpath>
|
||||
<group colspan="8">
|
||||
<group colspan="2" col="2">
|
||||
<label string="Due to changes in Address and Partner's relation, some of the details from address are needed to migrated into contact information." colspan="4"/>
|
||||
<label string="Otherwise these details will not be visible from address/contact." colspan="4"/>
|
||||
<label string="Do you want to migrate your Address data in Contact Data?" colspan="4" />
|
||||
<field name="migrate" string="Yes/No" />
|
||||
</group>
|
||||
</group>
|
||||
</data>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_base_contact_installer" model="ir.actions.act_window">
|
||||
<field name="name">Address Migration</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">base.contact.installer</field>
|
||||
<field name="view_id" ref="view_base_contact_installer"/>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
<record id="base_contact_installer_todo" model="ir.actions.todo">
|
||||
<field name="action_id" ref="action_base_contact_installer"/>
|
||||
<field name="sequence">3</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 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/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
@@ -48,7 +48,7 @@ PEP-8 Test , copyright of py files check, method can not call from loops
|
||||
list_files.append(os.path.join(i, j))
|
||||
py_list = []
|
||||
for file_py in list_files:
|
||||
if file_py.split('.')[-1] == 'py' and not file_py.endswith('__init__.py') and not file_py.endswith('__terp__.py'):
|
||||
if file_py.split('.')[-1] == 'py' and not file_py.endswith('__init__.py') and not file_py.endswith('__openerp__.py'):
|
||||
file_path = os.path.join(module_path, file_py)
|
||||
py_list.append(file_path)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 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/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
@@ -50,7 +50,7 @@ class quality_test(base_module_quality.abstract_quality_check):
|
||||
flag = False
|
||||
self.result_details += '''<html><body><head>%s</head>'''%(self.get_style())
|
||||
for file_py in list_files:
|
||||
if file_py.split('.')[-1] == 'py' and not file_py.endswith('__init__.py') and not file_py.endswith('__terp__.py'):
|
||||
if file_py.split('.')[-1] == 'py' and not file_py.endswith('__init__.py') and not file_py.endswith('__openerp__.py'):
|
||||
if not flag:
|
||||
flag = True
|
||||
file_path = os.path.join(module_path, file_py)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 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/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
@@ -82,7 +82,7 @@ This test checks if the module satisfy tiny structure
|
||||
# module files calculation (module.py,module_view.xml,etc..)
|
||||
com_list = ['_unit_test.xml', '.py', '_view.xml', '_workflow.xml' , '_wizard.xml', '_report.xml', '_data.xml', '_demo.xml', '_security.xml', '_sequence.xml', '_graph.xml']
|
||||
com_list = map(lambda x: module_name + x, com_list)
|
||||
main_file = ['__init__.py', '__terp__.py']
|
||||
main_file = ['__init__.py', '__openerp__.py']
|
||||
com_list.extend(main_file)
|
||||
module_dict['module'] = filter(lambda x: len(x.split(".")) > 1, module_dict['module'])
|
||||
score = self.get_score(module_dict['module'], com_list)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 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/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
@@ -49,13 +49,13 @@ class quality_test(base_module_quality.abstract_quality_check):
|
||||
score = 1.0
|
||||
feel_good_factor = 0
|
||||
feel_bad_factor = 0
|
||||
if '__terp__.py' not in list_files:
|
||||
if '__openerp__.py' not in list_files:
|
||||
self.no_terp = True
|
||||
self.result += _("The module does not contain the __terp__.py file")
|
||||
self.result += _("The module does not contain the __openerp__.py file")
|
||||
return None
|
||||
result_dict = {}
|
||||
result_dict1 = {}
|
||||
terp_file = os.path.join(module_path,'__terp__.py')
|
||||
terp_file = os.path.join(module_path,'__openerp__.py')
|
||||
res = eval(tools.file_open(terp_file).read())
|
||||
terp_keys = ['category', 'name', 'description', 'author', 'website', 'update_xml', 'init_xml', 'depends', 'version', 'active', 'installable', 'demo_xml']
|
||||
for key in terp_keys:
|
||||
@@ -117,7 +117,7 @@ class quality_test(base_module_quality.abstract_quality_check):
|
||||
|
||||
self.result_details += self.get_result_details(result_dict)
|
||||
self.result_details += self.get_result_details(result_dict1)
|
||||
return [_('__terp__.py file'), score]
|
||||
return [_('__openerp__.py file'), score]
|
||||
|
||||
def run_test(self, cr, uid, module_path):
|
||||
terp_score = self.run_test_terp(cr, uid, module_path)
|
||||
@@ -125,7 +125,7 @@ class quality_test(base_module_quality.abstract_quality_check):
|
||||
if self.score*100 < self.min_score:
|
||||
self.message = 'Score is below than minimal score(%s%%)' % self.min_score
|
||||
if terp_score:
|
||||
self.result = self.get_result({'__terp__.py': terp_score})
|
||||
self.result = self.get_result({'__openerp__.py': terp_score})
|
||||
return None
|
||||
|
||||
def get_result(self, dict_terp):
|
||||
@@ -144,4 +144,4 @@ class quality_test(base_module_quality.abstract_quality_check):
|
||||
return res
|
||||
return ""
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -32,16 +32,6 @@ class calendar_event_export(osv.osv_memory):
|
||||
"""
|
||||
Export Calendar Event.
|
||||
"""
|
||||
def process_export_ics(self, cr, uid, ids, context):
|
||||
"""
|
||||
Get Default value for file_path field.
|
||||
"""
|
||||
model = context.get('model', 'basic.calendar')
|
||||
model_obj = self.pool.get(model)
|
||||
|
||||
calendar = model_obj.export_cal(cr, uid, context['active_ids'], context)
|
||||
self.write(cr, uid, ids, {'file_path': base64.encodestring(calendar)})
|
||||
return False
|
||||
|
||||
def default_get(self, cr, uid, fields, context):
|
||||
"""
|
||||
@@ -54,6 +44,9 @@ class calendar_event_export(osv.osv_memory):
|
||||
name = 'OpenERP %s.ics' % (model_obj._description)
|
||||
if 'name' in fields:
|
||||
res.update({'name': name})
|
||||
if 'file_path' in fields:
|
||||
calendar = model_obj.export_cal(cr, uid, context['active_ids'], context)
|
||||
res.update({'file_path': base64.encodestring(calendar)})
|
||||
return res
|
||||
|
||||
_name = "calendar.event.export"
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
</group>
|
||||
<separator string="" colspan="4" />
|
||||
<group colspan="4" col="6">
|
||||
<button name="process_export_ics" icon="gtk-execute" string="Genetate ics" type="object"/>
|
||||
<button icon="gtk-cancel" special="cancel" string="_Cancel"/>
|
||||
<label string=""/>
|
||||
<button icon="gtk-close" special="cancel" string="_Close"/>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
|
||||
@@ -69,7 +69,6 @@ Create dashboard for CRM that includes:
|
||||
'crm_opportunity_data.xml',
|
||||
'crm_phonecall_data.xml',
|
||||
],
|
||||
|
||||
'update_xml': [
|
||||
'wizard/crm_lead_to_partner_view.xml',
|
||||
'wizard/crm_lead_to_opportunity_view.xml',
|
||||
|
||||
@@ -5,18 +5,5 @@
|
||||
<field name="name">Sales Department</field>
|
||||
<field name="code">Sales</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="ir_cron_crm_action" model="ir.cron">
|
||||
<field name="name">Check cases rules</field>
|
||||
<field name="interval_number">4</field>
|
||||
<field name="interval_type">hours</field>
|
||||
<field name="numbercall">-1</field>
|
||||
<field eval="False" name="doall"/>
|
||||
<field eval="'crm.case'" name="model"/>
|
||||
<field eval="'_check'" name="function"/>
|
||||
<field eval="'()'" name="args"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -30,12 +30,10 @@ from crm import crm_case
|
||||
|
||||
class crm_lead(osv.osv, crm_case):
|
||||
""" CRM Lead Case """
|
||||
|
||||
_name = "crm.lead"
|
||||
_description = "Lead"
|
||||
_order = "priority, id desc"
|
||||
_inherit = ['res.partner.address']
|
||||
_inherits = {'mailgate.thread': 'thread_id'}
|
||||
_inherit = ['mailgate.thread','res.partner.address']
|
||||
|
||||
def _compute_day(self, cr, uid, ids, fields, args, context={}):
|
||||
"""
|
||||
@@ -112,7 +110,6 @@ and users by email"),
|
||||
'write_date': fields.datetime('Update Date' , readonly=True),
|
||||
|
||||
# Lead fields
|
||||
'thread_id': fields.many2one('mailgate.thread', 'Thread', required=False),
|
||||
'categ_id': fields.many2one('crm.case.categ', 'Lead Source', \
|
||||
domain="[('section_id','=',section_id),\
|
||||
('object_id.model', '=', 'crm.lead')]"),
|
||||
@@ -142,6 +139,8 @@ and users by email"),
|
||||
\nIf the case is in progress the state is set to \'Open\'.\
|
||||
\nWhen the case is over, the state is set to \'Done\'.\
|
||||
\nIf the case needs to be reviewed then the state is set to \'Pending\'.'),
|
||||
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('history', '=', True),('res_model','=',_name)]),
|
||||
'log_ids': fields.one2many('mailgate.message', 'res_id', 'Logs', domain=[('history', '=', False),('res_model','=',_name)]),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
|
||||
@@ -38,9 +38,8 @@ from tools import command_re
|
||||
|
||||
class mailgate_thread(osv.osv):
|
||||
""" mailgate_thread """
|
||||
|
||||
_name = "mailgate.thread"
|
||||
_inherit = "mailgate.thread"
|
||||
_inherit = "mailgate.thread"
|
||||
|
||||
def message_new(self, cr, uid, msg, context):
|
||||
"""
|
||||
|
||||
@@ -43,9 +43,7 @@ class crm_meeting(osv.osv, crm_case):
|
||||
_name = 'crm.meeting'
|
||||
_description = "Meeting"
|
||||
_order = "id desc"
|
||||
_inherit = ["calendar.event"]
|
||||
_inherits = {'mailgate.thread': 'thread_id'}
|
||||
|
||||
_inherit = ['mailgate.thread',"calendar.event"]
|
||||
_columns = {
|
||||
# From crm.case
|
||||
'name': fields.char('Summary', size=124, required=True),
|
||||
@@ -59,7 +57,6 @@ class crm_meeting(osv.osv, crm_case):
|
||||
'id': fields.integer('ID'),
|
||||
|
||||
# Meeting fields
|
||||
'thread_id': fields.many2one('mailgate.thread', 'Thread', required=False),
|
||||
'categ_id': fields.many2one('crm.case.categ', 'Meeting Type', \
|
||||
domain="[('object_id.model', '=', 'crm.meeting')]", \
|
||||
),
|
||||
@@ -69,6 +66,8 @@ class crm_meeting(osv.osv, crm_case):
|
||||
'event_id', 'attendee_id', 'Attendees'),
|
||||
'date_closed': fields.datetime('Closed', readonly=True),
|
||||
'date_deadline': fields.datetime('Deadline'),
|
||||
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('history', '=', True),('res_model','=',_name)]),
|
||||
'log_ids': fields.one2many('mailgate.message', 'res_id', 'Logs', domain=[('history', '=', False),('res_model','=',_name)]),
|
||||
'state': fields.selection([('open', 'Confirmed'),
|
||||
('draft', 'Unconfirmed'),
|
||||
('cancel', 'Cancelled'),
|
||||
|
||||
@@ -31,13 +31,11 @@ class crm_phonecall(osv.osv, crm_case):
|
||||
_name = "crm.phonecall"
|
||||
_description = "Phonecall"
|
||||
_order = "id desc"
|
||||
_inherits = {'mailgate.thread': 'thread_id'}
|
||||
|
||||
_inherit = ['mailgate.thread']
|
||||
_columns = {
|
||||
# From crm.case
|
||||
'name': fields.char('Name', size=64),
|
||||
'active': fields.boolean('Active', required=False),
|
||||
'thread_id': fields.many2one('mailgate.thread', 'Thread', required=False),
|
||||
'date_action_last': fields.datetime('Last Action', readonly=1),
|
||||
'date_action_next': fields.datetime('Next Action', readonly=1),
|
||||
'create_date': fields.datetime('Creation Date' , readonly=True),
|
||||
@@ -84,6 +82,8 @@ class crm_phonecall(osv.osv, crm_case):
|
||||
'date_closed': fields.datetime('Closed', readonly=True),
|
||||
'date': fields.datetime('Date'),
|
||||
'opportunity_id': fields.many2one ('crm.lead', 'Opportunity'),
|
||||
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('history', '=', True),('res_model','=',_name)]),
|
||||
'log_ids': fields.one2many('mailgate.message', 'res_id', 'Logs', domain=[('history', '=', False),('res_model','=',_name)]),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
|
||||
@@ -1,91 +1,87 @@
|
||||
<?xml version="1.0" ?>
|
||||
<openerp>
|
||||
<data>
|
||||
<data>
|
||||
|
||||
<!--
|
||||
Process
|
||||
-->
|
||||
<!--
|
||||
Process
|
||||
-->
|
||||
|
||||
<record id="process_process_contractprocess0" model="process.process">
|
||||
<field eval="1" name="active"/>
|
||||
<field name="model_id" ref="mail_gateway.model_mailgate_thread"/>
|
||||
<field eval=""""Contract"""" name="name"/>
|
||||
</record>
|
||||
<field eval="1" name="active"/>
|
||||
<field eval=""""Contract"""" name="name"/>
|
||||
</record>
|
||||
|
||||
<!--
|
||||
Process Node
|
||||
-->
|
||||
<!--
|
||||
Process Node
|
||||
-->
|
||||
|
||||
<record id="process_node_leads0" model="process.node">
|
||||
<field name="model_id" ref="mail_gateway.model_mailgate_thread"/>
|
||||
<field eval=""""state"""" name="kind"/>
|
||||
<field eval=""""Leads"""" name="name"/>
|
||||
<field eval=""""Very first contact with new prospect"""" name="note"/>
|
||||
<field name="process_id" ref="process_process_contractprocess0"/>
|
||||
<field eval=""""object.state in ('draft', 'open', 'pending', 'done', 'cancel')"""" name="model_states"/>
|
||||
<field eval="1" name="flow_start"/>
|
||||
</record>
|
||||
<record id="process_node_leads0" model="process.node">
|
||||
<field eval=""""state"""" name="kind"/>
|
||||
<field eval=""""Leads"""" name="name"/>
|
||||
<field eval=""""Very first contact with new prospect"""" name="note"/>
|
||||
<field name="process_id" ref="process_process_contractprocess0"/>
|
||||
<field eval=""""object.state in ('draft', 'open', 'pending', 'done', 'cancel')"""" name="model_states"/>
|
||||
<field eval="1" name="flow_start"/>
|
||||
</record>
|
||||
|
||||
<record id="process_node_partner0" model="process.node">
|
||||
<field name="menu_id" ref="base.menu_partner_form"/>
|
||||
<field name="model_id" ref="base.model_res_partner"/>
|
||||
<field eval=""""state"""" name="kind"/>
|
||||
<field eval=""""Partner"""" name="name"/>
|
||||
<field eval=""""Convert to prospect to business partner"""" name="note"/>
|
||||
<field name="process_id" ref="process_process_contractprocess0"/>
|
||||
<field eval="0" name="flow_start"/>
|
||||
</record>
|
||||
<record id="process_node_partner0" model="process.node">
|
||||
<field name="menu_id" ref="base.menu_partner_form"/>
|
||||
<field name="model_id" ref="base.model_res_partner"/>
|
||||
<field eval=""""state"""" name="kind"/>
|
||||
<field eval=""""Partner"""" name="name"/>
|
||||
<field eval=""""Convert to prospect to business partner"""" name="note"/>
|
||||
<field name="process_id" ref="process_process_contractprocess0"/>
|
||||
<field eval="0" name="flow_start"/>
|
||||
</record>
|
||||
|
||||
<record id="process_node_opportunities0" model="process.node">
|
||||
<field name="model_id" ref="mail_gateway.model_mailgate_thread"/>
|
||||
<field eval=""""state"""" name="kind"/>
|
||||
<field eval=""""Opportunities"""" name="name"/>
|
||||
<field eval=""""When a real project/opportunity is detected"""" name="note"/>
|
||||
<field name="process_id" ref="process_process_contractprocess0"/>
|
||||
<field eval=""""object.state in ('draft', 'open', 'pending', 'done', 'cancel')"""" name="model_states"/>
|
||||
<field eval="0" name="flow_start"/>
|
||||
</record>
|
||||
<record id="process_node_opportunities0" model="process.node">
|
||||
<field eval=""""state"""" name="kind"/>
|
||||
<field eval=""""Opportunities"""" name="name"/>
|
||||
<field eval=""""When a real project/opportunity is detected"""" name="note"/>
|
||||
<field name="process_id" ref="process_process_contractprocess0"/>
|
||||
<field eval=""""object.state in ('draft', 'open', 'pending', 'done', 'cancel')"""" name="model_states"/>
|
||||
<field eval="0" name="flow_start"/>
|
||||
</record>
|
||||
|
||||
<record id="process_node_meeting0" model="process.node">
|
||||
<field name="model_id" ref="mail_gateway.model_mailgate_thread"/>
|
||||
<field eval=""""state"""" name="kind"/>
|
||||
<field eval=""""Meeting"""" name="name"/>
|
||||
<field eval=""""Schedule a normal or phone meeting"""" name="note"/>
|
||||
<field name="process_id" ref="process_process_contractprocess0"/>
|
||||
<field eval=""""object.state in ('draft', 'open', 'pending', 'done', 'cancel')"""" name="model_states"/>
|
||||
<field eval="0" name="flow_start"/>
|
||||
</record>
|
||||
<record id="process_node_meeting0" model="process.node">
|
||||
<field eval=""""state"""" name="kind"/>
|
||||
<field eval=""""Meeting"""" name="name"/>
|
||||
<field eval=""""Schedule a normal or phone meeting"""" name="note"/>
|
||||
<field name="process_id" ref="process_process_contractprocess0"/>
|
||||
<field eval=""""object.state in ('draft', 'open', 'pending', 'done', 'cancel')"""" name="model_states"/>
|
||||
<field eval="0" name="flow_start"/>
|
||||
</record>
|
||||
|
||||
<!--
|
||||
Process Transition
|
||||
-->
|
||||
<!--
|
||||
Process Transition
|
||||
-->
|
||||
|
||||
<record id="process_transition_leadopportunity0" model="process.transition">
|
||||
<field eval="[(6,0,[])]" name="role_ids"/>
|
||||
<field eval="[(6,0,[])]" name="transition_ids"/>
|
||||
<field eval=""""Prospect Opportunity"""" name="name"/>
|
||||
<field eval=""""Creating business opportunities from Leads"""" name="note"/>
|
||||
<field model="process.node" name="target_node_id" ref="process_node_opportunities0"/>
|
||||
<field model="process.node" name="source_node_id" ref="process_node_leads0"/>
|
||||
</record>
|
||||
<record id="process_transition_leadopportunity0" model="process.transition">
|
||||
<field eval="[(6,0,[])]" name="role_ids"/>
|
||||
<field eval="[(6,0,[])]" name="transition_ids"/>
|
||||
<field eval=""""Prospect Opportunity"""" name="name"/>
|
||||
<field eval=""""Creating business opportunities from Leads"""" name="note"/>
|
||||
<field model="process.node" name="target_node_id" ref="process_node_opportunities0"/>
|
||||
<field model="process.node" name="source_node_id" ref="process_node_leads0"/>
|
||||
</record>
|
||||
|
||||
<record id="process_transition_leadpartner0" model="process.transition">
|
||||
<field eval="[(6,0,[])]" name="role_ids"/>
|
||||
<field eval="[(6,0,[])]" name="transition_ids"/>
|
||||
<field eval=""""Prospect Partner"""" name="name"/>
|
||||
<field eval=""""Prospect is converting to business partner"""" name="note"/>
|
||||
<field model="process.node" name="target_node_id" ref="process_node_partner0"/>
|
||||
<field model="process.node" name="source_node_id" ref="process_node_leads0"/>
|
||||
</record>
|
||||
<record id="process_transition_leadpartner0" model="process.transition">
|
||||
<field eval="[(6,0,[])]" name="role_ids"/>
|
||||
<field eval="[(6,0,[])]" name="transition_ids"/>
|
||||
<field eval=""""Prospect Partner"""" name="name"/>
|
||||
<field eval=""""Prospect is converting to business partner"""" name="note"/>
|
||||
<field model="process.node" name="target_node_id" ref="process_node_partner0"/>
|
||||
<field model="process.node" name="source_node_id" ref="process_node_leads0"/>
|
||||
</record>
|
||||
|
||||
<record id="process_transition_opportunitymeeting0" model="process.transition">
|
||||
<field eval="[(6,0,[])]" name="role_ids"/>
|
||||
<field eval="[(6,0,[])]" name="transition_ids"/>
|
||||
<field eval=""""Opportunity Meeting"""" name="name"/>
|
||||
<field eval=""""Normal or phone meeting for opportunity"""" name="note"/>
|
||||
<field model="process.node" name="target_node_id" ref="process_node_meeting0"/>
|
||||
<field model="process.node" name="source_node_id" ref="process_node_opportunities0"/>
|
||||
</record>
|
||||
<record id="process_transition_opportunitymeeting0" model="process.transition">
|
||||
<field eval="[(6,0,[])]" name="role_ids"/>
|
||||
<field eval="[(6,0,[])]" name="transition_ids"/>
|
||||
<field eval=""""Opportunity Meeting"""" name="name"/>
|
||||
<field eval=""""Normal or phone meeting for opportunity"""" name="note"/>
|
||||
<field model="process.node" name="target_node_id" ref="process_node_meeting0"/>
|
||||
<field model="process.node" name="source_node_id" ref="process_node_opportunities0"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -109,7 +109,6 @@ class crm_lead_report(osv.osv):
|
||||
'date_closed': fields.date('Close Date', readonly=True),
|
||||
'company_id': fields.many2one('res.company', 'Company', readonly=True),
|
||||
'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'),
|
||||
|
||||
'type':fields.selection([
|
||||
('lead','Lead'),
|
||||
('opportunity','Opportunity'),
|
||||
@@ -148,7 +147,7 @@ class crm_lead_report(osv.osv):
|
||||
0 as avg_answers,
|
||||
0.0 as perc_done,
|
||||
0.0 as perc_cancel,
|
||||
(select count(id) from mailgate_message where thread_id=c.id) as email,
|
||||
(select count(id) from mailgate_message where res_id=c.id and res_model='crm.lead') as email,
|
||||
date_trunc('day',c.create_date) as create_date,
|
||||
avg(extract('epoch' from (c.date_closed-c.create_date)))/(3600*24) as delay_close,
|
||||
avg(extract('epoch' from (c.date_deadline - c.date_closed)))/(3600*24) as delay_expected,
|
||||
|
||||
@@ -185,23 +185,12 @@ class crm_lead_forward_to_partner(osv.osv_memory):
|
||||
email_from = this.email_from or False
|
||||
case_pool._history(cr, uid, [case], _('Forward'), history=True, email=this.email_to, details=body, email_from=email_from)
|
||||
|
||||
flag = False
|
||||
if case.section_id and case.section_id.server_id:
|
||||
flag = smtp_pool.send_email(
|
||||
cr=cr,
|
||||
uid=uid,
|
||||
server_id=case.section_id.server_id.id,
|
||||
emailto=emails,
|
||||
subject=this.subject,
|
||||
body="<pre>%s</pre>" % body,
|
||||
)
|
||||
else:
|
||||
flag = tools.email_send(
|
||||
email_from,
|
||||
emails,
|
||||
this.subject,
|
||||
body,
|
||||
)
|
||||
flag = tools.email_send(
|
||||
email_from,
|
||||
emails,
|
||||
this.subject,
|
||||
body,
|
||||
)
|
||||
if this.add_cc:
|
||||
case_pool.write(cr, uid, case.id, {'email_cc' : case.email_cc and case.email_cc + ', ' + this.email_to or this.email_to})
|
||||
return {}
|
||||
|
||||
@@ -96,11 +96,10 @@ class crm_send_new_email(osv.osv_memory):
|
||||
else:
|
||||
hist = hist_obj.browse(cr, uid, res_id)
|
||||
message_id = hist.message_id
|
||||
model = hist.model_id.model
|
||||
model = hist.res_model
|
||||
model_pool = self.pool.get(model)
|
||||
res_ids = model_pool.search(cr, uid, [('thread_id','=', hist.thread_id.id)])
|
||||
res_id = res_ids and res_ids[0] or False
|
||||
case = model_pool.browse(cr, uid, res_id)
|
||||
case = model_pool.browse(cr, uid, hist.res_id)
|
||||
res_id = hist.res_id
|
||||
emails = [obj.email_to] + (obj.email_cc or '').split(',')
|
||||
emails = filter(None, emails)
|
||||
body = obj.text
|
||||
@@ -120,15 +119,14 @@ class crm_send_new_email(osv.osv_memory):
|
||||
if message_id:
|
||||
x_headers['References'] = "%s" % (message_id)
|
||||
|
||||
flag = False
|
||||
|
||||
print case.section_id
|
||||
flag = tools.email_send(
|
||||
email_from,
|
||||
emails,
|
||||
obj.subject,
|
||||
body,
|
||||
attach=attach,
|
||||
reply_to=case.section_id.reply_to,
|
||||
reply_to=case.section_id and case.section_id.reply_to or email_from,
|
||||
openobject_id=str(case.id),
|
||||
x_headers=x_headers
|
||||
)
|
||||
@@ -196,15 +194,14 @@ class crm_send_new_email(osv.osv_memory):
|
||||
include_original = context and context.get('include_original', False) or False
|
||||
res = {}
|
||||
for hist in hist_obj.browse(cr, uid, res_ids, context=context):
|
||||
model = hist.model_id.model
|
||||
model = hist.res_model
|
||||
|
||||
# In the case where the crm.case does not exist in the database
|
||||
if not model:
|
||||
return {}
|
||||
|
||||
model_pool = self.pool.get(model)
|
||||
res_ids = model_pool.search(cr, uid, [('thread_id','=', hist.thread_id.id)])
|
||||
res_id = res_ids and res_ids[0] or False
|
||||
res_id = hist.res_id or False
|
||||
case = model_pool.browse(cr, uid, res_id)
|
||||
if 'email_to' in fields:
|
||||
res.update({'email_to': case.email_from or hist.email_from or False})
|
||||
|
||||
@@ -9,13 +9,15 @@
|
||||
<field name="model">crm.send.mail</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Send New Mail" col="2">
|
||||
<separator string="Send New Mail" colspan="2"/>
|
||||
<form string="Send New Mail" col="4">
|
||||
<separator string="Send New Mail" colspan="4"/>
|
||||
<group colspan="4" col="6">
|
||||
<field name="email_from" />
|
||||
<field name="email_to" />
|
||||
<field name="email_cc" />
|
||||
<field name="subject" />
|
||||
<notebook colspan="2">
|
||||
<field name="subject" colspan="6"/>
|
||||
</group>
|
||||
<notebook colspan="6">
|
||||
<page string="Message">
|
||||
<field name="text" nolabel="1" colspan="4"/>
|
||||
</page>
|
||||
@@ -31,8 +33,8 @@
|
||||
</field>
|
||||
</page>
|
||||
</notebook>
|
||||
<separator string="" colspan="2"/>
|
||||
<group colspan="2" col="4" >
|
||||
<separator string="" colspan="6"/>
|
||||
<group colspan="6" col="4" >
|
||||
<field name="state" />
|
||||
<button name="action_cancel" string="_Cancel" icon="gtk-cancel" special="cancel" />
|
||||
<button name="action_send" type="object" string="_Send" icon="gtk-go-forward" />
|
||||
|
||||
@@ -29,10 +29,8 @@ class crm_claim(osv.osv, crm.crm_case):
|
||||
_name = "crm.claim"
|
||||
_description = "Claim Cases"
|
||||
_order = "id desc"
|
||||
_inherits = {'mailgate.thread': 'thread_id'}
|
||||
|
||||
_inherit = ['mailgate.thread']
|
||||
_columns = {
|
||||
'thread_id': fields.many2one('mailgate.thread', 'Thread', required=False),
|
||||
'id': fields.integer('ID', readonly=True),
|
||||
'name': fields.char('Name', size=128, required=True),
|
||||
'active': fields.boolean('Active', required=False),
|
||||
@@ -90,6 +88,8 @@ class crm_claim(osv.osv, crm.crm_case):
|
||||
\nIf the case is in progress the state is set to \'Open\'.\
|
||||
\nWhen the case is over, the state is set to \'Done\'.\
|
||||
\nIf the case needs to be reviewed then the state is set to \'Pending\'.'),
|
||||
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('history', '=', True),('res_model','=',_name)]),
|
||||
'log_ids': fields.one2many('mailgate.message', 'res_id', 'Logs', domain=[('history', '=', False),('res_model','=',_name)]),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
|
||||
@@ -28,10 +28,8 @@ class crm_fundraising(osv.osv, crm.crm_case):
|
||||
_name = "crm.fundraising"
|
||||
_description = "Fund Raising Cases"
|
||||
_order = "id desc"
|
||||
_inherits = {'mailgate.thread': 'thread_id'}
|
||||
|
||||
_inherit = ['mailgate.thread']
|
||||
_columns = {
|
||||
'thread_id': fields.many2one('mailgate.thread', 'Thread', required=False),
|
||||
'id': fields.integer('ID'),
|
||||
'name': fields.char('Name', size=128, required=True),
|
||||
'active': fields.boolean('Active', required=False),
|
||||
@@ -87,6 +85,8 @@ class crm_fundraising(osv.osv, crm.crm_case):
|
||||
\nIf the case is in progress the state is set to \'Open\'.\
|
||||
\nWhen the case is over, the state is set to \'Done\'.\
|
||||
\nIf the case needs to be reviewed then the state is set to \'Pending\'.'),
|
||||
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('history', '=', True),('res_model','=',_name)]),
|
||||
'log_ids': fields.one2many('mailgate.message', 'res_id', 'Logs', domain=[('history', '=', False),('res_model','=',_name)]),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
|
||||
@@ -28,10 +28,8 @@ class crm_helpdesk(osv.osv, crm.crm_case):
|
||||
_name = "crm.helpdesk"
|
||||
_description = "Helpdesk Cases"
|
||||
_order = "id desc"
|
||||
_inherits = {'mailgate.thread': 'thread_id'}
|
||||
|
||||
_inherit = ['mailgate.thread']
|
||||
_columns = {
|
||||
'thread_id': fields.many2one('mailgate.thread', 'Thread', required=False),
|
||||
'id': fields.integer('ID', readonly=True),
|
||||
'name': fields.char('Name', size=128, required=True),
|
||||
'active': fields.boolean('Active', required=False),
|
||||
|
||||
@@ -149,7 +149,7 @@ class delivery_grid_line(osv.osv):
|
||||
'name': fields.char('Name', size=32, required=True),
|
||||
'grid_id': fields.many2one('delivery.grid', 'Grid',required=True),
|
||||
'type': fields.selection([('weight','Weight'),('volume','Volume'),('wv','Weight * Volume'), ('price','Price')], 'Variable', required=True),
|
||||
'operator': fields.selection([('=','='),('<=','<='),('>=','>=')], 'Operator', required=True),
|
||||
'operator': fields.selection([('==','='),('<=','<='),('>=','>=')], 'Operator', required=True),
|
||||
'max_value': fields.float('Maximum Value', required=True),
|
||||
'price_type': fields.selection([('fixed','Fixed'),('variable','Variable')], 'Price Type', required=True),
|
||||
'variable_factor': fields.selection([('weight','Weight'),('volume','Volume'),('wv','Weight * Volume'), ('price','Price')], 'Variable Factor', required=True),
|
||||
|
||||
@@ -57,11 +57,11 @@ class hr_applicant(osv.osv, crm.crm_case):
|
||||
_name = "hr.applicant"
|
||||
_description = "Applicant"
|
||||
_order = "id desc"
|
||||
_inherits = {'mailgate.thread': 'thread_id'}
|
||||
|
||||
_inherit = ['mailgate.thread']
|
||||
_columns = {
|
||||
'thread_id': fields.many2one('mailgate.thread', 'Thread', required=False),
|
||||
'name': fields.char('Name', size=128, required=True),
|
||||
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('history', '=', True),('res_model','=',_name)]),
|
||||
'log_ids': fields.one2many('mailgate.message', 'res_id', 'Logs', domain=[('history', '=', False),('res_model','=',_name)]),
|
||||
'active': fields.boolean('Active', help="If the active field is set to false, it will allow you to hide the case without removing it."),
|
||||
'description': fields.text('Description'),
|
||||
'section_id': fields.many2one('crm.case.section', 'Sales Team', \
|
||||
|
||||
@@ -30,14 +30,10 @@ class mailgate_thread(osv.osv):
|
||||
'''
|
||||
_name = 'mailgate.thread'
|
||||
_description = 'Mailgateway Thread'
|
||||
_rec_name = 'thread'
|
||||
|
||||
_columns = {
|
||||
'thread': fields.char('Thread', size=32, required=False),
|
||||
'message_ids': fields.one2many('mailgate.message', 'thread_id', 'Messages', domain=[('history', '=', True)], required=False),
|
||||
'log_ids': fields.one2many('mailgate.message', 'thread_id', 'Logs', domain=[('history', '=', False)], required=False),
|
||||
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('history', '=', True)]),
|
||||
'log_ids': fields.one2many('mailgate.message', 'res_id', 'Logs', domain=[('history', '=', False)]),
|
||||
}
|
||||
|
||||
def _history(self, cr, uid, cases, keyword, history=False, subject=None, email=False, details=None, email_from=False, message_id=False, attach=None, context=None):
|
||||
"""
|
||||
@param self: The object pointer
|
||||
@@ -60,18 +56,16 @@ class mailgate_thread(osv.osv):
|
||||
if all(isinstance(case_id, (int, long)) for case_id in cases):
|
||||
cases = self.browse(cr, uid, cases, context=context)
|
||||
|
||||
model_obj = self.pool.get('ir.model')
|
||||
att_obj = self.pool.get('ir.attachment')
|
||||
obj = self.pool.get('mailgate.message')
|
||||
|
||||
for case in cases:
|
||||
model_ids = model_obj.search(cr, uid, [('model', '=', case._name)])
|
||||
data = {
|
||||
'name': keyword,
|
||||
'user_id': uid,
|
||||
'model_id' : model_ids and model_ids[0] or False,
|
||||
'res_model' : case._name,
|
||||
'res_id': case.id,
|
||||
'date': time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'thread_id': case.thread_id.id,
|
||||
'message_id': message_id,
|
||||
}
|
||||
attachments = []
|
||||
@@ -83,7 +77,7 @@ class mailgate_thread(osv.osv):
|
||||
'name': subject or 'History',
|
||||
'history': True,
|
||||
'user_id': uid,
|
||||
'model_id' : model_ids and model_ids[0] or False,
|
||||
'res_model' : case._name,
|
||||
'res_id': case.id,
|
||||
'date': time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'description': details or (hasattr(case, 'description') and case.description or False),
|
||||
@@ -94,16 +88,11 @@ class mailgate_thread(osv.osv):
|
||||
(hasattr(case, 'user_id') and case.user_id and case.user_id.address_id and \
|
||||
case.user_id.address_id.email) or tools.config.get('email_from', False),
|
||||
'partner_id': hasattr(case, 'partner_id') and (case.partner_id and case.partner_id.id or False) or False,
|
||||
'thread_id': case.thread_id.id,
|
||||
'message_id': message_id,
|
||||
'attachment_ids': [(6, 0, attachments)]
|
||||
}
|
||||
res = obj.create(cr, uid, data, context)
|
||||
return True
|
||||
|
||||
__history = history = _history
|
||||
|
||||
|
||||
mailgate_thread()
|
||||
|
||||
class mailgate_message(osv.osv):
|
||||
@@ -112,15 +101,13 @@ class mailgate_message(osv.osv):
|
||||
'''
|
||||
_name = 'mailgate.message'
|
||||
_description = 'Mailgateway Message'
|
||||
_order = 'date desc'
|
||||
|
||||
_order = 'id desc'
|
||||
_columns = {
|
||||
'name':fields.char('Message', size=64),
|
||||
'model_id': fields.many2one('ir.model', 'Model'),
|
||||
'res_model': fields.char('Object Name', size=128),
|
||||
'res_id': fields.integer('Resource ID'),
|
||||
'thread_id':fields.many2one('mailgate.thread', 'Thread'),
|
||||
'date': fields.datetime('Date'),
|
||||
'history': fields.boolean('Is History?', required=False),
|
||||
'history': fields.boolean('Is History?'),
|
||||
'user_id': fields.many2one('res.users', 'User Responsible', readonly=True),
|
||||
'message': fields.text('Description'),
|
||||
'email_from': fields.char('Email From', size=84),
|
||||
@@ -135,5 +122,3 @@ class mailgate_message(osv.osv):
|
||||
|
||||
mailgate_message()
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -127,13 +127,11 @@ class rpc_proxy(object):
|
||||
return self.rpc.execute(self.dbname, self.user_id, self.passwd, *request, **kwargs)
|
||||
|
||||
class email_parser(object):
|
||||
def __init__(self, uid, password, model, email, email_default, dbname, host, port):
|
||||
def __init__(self, uid, password, model, email, email_default, dbname, host, port):
|
||||
self.rpc = rpc_proxy(uid, password, host=host, port=port, dbname=dbname)
|
||||
try:
|
||||
self.model_id = int(model)
|
||||
self.model = str(model)
|
||||
except:
|
||||
self.model_id = self.rpc('ir.model', 'search', [('model', '=', model)])[0]
|
||||
self.model = str(model)
|
||||
self.email = email
|
||||
self.email_default = email_default
|
||||
@@ -188,7 +186,7 @@ class email_parser(object):
|
||||
values = {
|
||||
'message_ids' : [
|
||||
(0, 0, {
|
||||
'model_id' : self.rpc('ir.model', 'search', [('name', '=', self.model)])[0],
|
||||
'res_model' : self.model,
|
||||
'date' : time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'description' : message['body'],
|
||||
'email_from' : msg_from,
|
||||
@@ -200,8 +198,6 @@ class email_parser(object):
|
||||
)
|
||||
]
|
||||
}
|
||||
thread_id = self.rpc('mailgate.thread', 'create', values)
|
||||
data['thread_id'] = thread_id
|
||||
oid = self.rpc(self.model, 'create', data)
|
||||
|
||||
attachments = message['attachment']
|
||||
@@ -216,7 +212,7 @@ class email_parser(object):
|
||||
}
|
||||
self.rpc('ir.attachment', 'create', data_attach)
|
||||
|
||||
return (oid, thread_id,)
|
||||
return (oid, )
|
||||
|
||||
def msg_body_get(self, msg):
|
||||
message = {
|
||||
@@ -320,8 +316,7 @@ class email_parser(object):
|
||||
> create_message(id, msg['From'], msg['To'], 'Send', message['body'])
|
||||
"""
|
||||
values = {
|
||||
'thread_id' : self.rpc(self.model, 'read', [oid], ['thread_id'])[0]['thread_id'][0],
|
||||
'model_id' : self.rpc('ir.model', 'search', [('name', '=', self.model)])[0],
|
||||
'res_model' : self.model,
|
||||
'res_id' : oid,
|
||||
'date' : time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'description' : body,
|
||||
@@ -390,13 +385,7 @@ class email_parser(object):
|
||||
|
||||
logging.info("email: %s -> %s -- %s", msg['From'], self.email, msg['Subject'])
|
||||
(case_id, emails) = self.msg_test(msg, case_str)
|
||||
thread_id = None
|
||||
if case_id:
|
||||
values = self.rpc(self.model, 'read', [case_id], ['thread_id'])
|
||||
if values:
|
||||
thread_id = values[0]['thread_id'][0]
|
||||
emails = emails[str(thread_id)]
|
||||
|
||||
user_email = filter(None, emails['user_email'])[0]
|
||||
|
||||
if user_email and self.email_get(user_email) == self.email_get(self._decode_header(msg['From'])):
|
||||
@@ -404,13 +393,12 @@ class email_parser(object):
|
||||
else:
|
||||
self.msg_partner(msg, case_id)
|
||||
else:
|
||||
case_id, thread_id = self.msg_new(msg)
|
||||
case_id = self.msg_new(msg)
|
||||
subject = self._decode_header(msg['Subject'])
|
||||
msg['Subject'] = "[%s] %s" % (case_id, subject,)
|
||||
msg['Message-Id'] = "<%s-openerpcrm-%s@%s>" % (time.time(), case_id, socket.gethostname(),)
|
||||
|
||||
logging.info(" case: %r", case_id)
|
||||
logging.info(" thread: %r", thread_id)
|
||||
|
||||
values = self.rpc(self.model, 'emails_get', [case_id])
|
||||
|
||||
@@ -431,7 +419,7 @@ class email_parser(object):
|
||||
a = self._decode_header(msg['Subject'])
|
||||
msg['Subject'] = '[OpenERP-CaseError] ' + a
|
||||
self.msg_send(msg, self.email_default.split(','))
|
||||
return case_id, thread_id, emails
|
||||
return case_id, emails
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = optparse.OptionParser(usage='usage: %prog [options]', version='%prog v1.0')
|
||||
|
||||
@@ -28,11 +28,11 @@ class company(osv.osv):
|
||||
help="This is the time frame analysed by the scheduler when "\
|
||||
"computing procurements. All procurements that are not between "\
|
||||
"today and today+range are skipped for futur computation."),
|
||||
}
|
||||
}
|
||||
_defaults = {
|
||||
'schedule_range': lambda *a: 80.0,
|
||||
}
|
||||
'schedule_range': 80.0,
|
||||
}
|
||||
|
||||
company()
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
@@ -464,7 +464,7 @@ class stock_warehouse_orderpoint(osv.osv):
|
||||
"""
|
||||
_name = "stock.warehouse.orderpoint"
|
||||
_description = "Minimum Inventory Rule"
|
||||
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Name', size=32, required=True),
|
||||
'active': fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the orderpoint without removing it."),
|
||||
@@ -485,17 +485,17 @@ class stock_warehouse_orderpoint(osv.osv):
|
||||
'company_id': fields.many2one('res.company','Company',required=True),
|
||||
}
|
||||
_defaults = {
|
||||
'active': lambda *a: 1,
|
||||
'logic': lambda *a: 'max',
|
||||
'qty_multiple': lambda *a: 1,
|
||||
'active': 1,
|
||||
'logic': 'max',
|
||||
'qty_multiple': 1,
|
||||
'name': lambda x,y,z,c: x.pool.get('ir.sequence').get(y,z,'stock.orderpoint') or '',
|
||||
'product_uom': lambda sel, cr, uid, context: context.get('product_uom', False),
|
||||
'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'stock.warehouse.orderpoint', context=c)
|
||||
}
|
||||
_sql_constraints = [
|
||||
('qty_multiple_check', 'CHECK( qty_multiple > 0 )', _('Qty Multiple must be greater than zero.')),
|
||||
]
|
||||
|
||||
]
|
||||
|
||||
def onchange_warehouse_id(self, cr, uid, ids, warehouse_id, context={}):
|
||||
""" Finds location id for changed warehouse.
|
||||
@param warehouse_id: Changed id of warehouse.
|
||||
@@ -506,7 +506,7 @@ class stock_warehouse_orderpoint(osv.osv):
|
||||
v = {'location_id': w.lot_stock_id.id}
|
||||
return {'value': v}
|
||||
return {}
|
||||
|
||||
|
||||
def onchange_product_id(self, cr, uid, ids, product_id, context={}):
|
||||
""" Finds UoM for changed product.
|
||||
@param product_id: Changed id of product.
|
||||
@@ -517,7 +517,7 @@ class stock_warehouse_orderpoint(osv.osv):
|
||||
v = {'product_uom': prod.uom_id.id}
|
||||
return {'value': v}
|
||||
return {}
|
||||
|
||||
|
||||
def copy(self, cr, uid, id, default=None,context={}):
|
||||
if not default:
|
||||
default = {}
|
||||
@@ -525,6 +525,6 @@ class stock_warehouse_orderpoint(osv.osv):
|
||||
'name': self.pool.get('ir.sequence').get(cr, uid, 'stock.orderpoint') or '',
|
||||
})
|
||||
return super(stock_warehouse_orderpoint, self).copy(cr, uid, id, default, context)
|
||||
|
||||
|
||||
stock_warehouse_orderpoint()
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -19,12 +19,12 @@
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import time
|
||||
from mx import DateTime
|
||||
|
||||
from osv import osv
|
||||
import netsvc
|
||||
import pooler
|
||||
from mx import DateTime
|
||||
import time
|
||||
|
||||
|
||||
class procurement_order(osv.osv):
|
||||
_inherit = 'procurement.order'
|
||||
@@ -37,7 +37,7 @@ class procurement_order(osv.osv):
|
||||
context = {}
|
||||
|
||||
if use_new_cursor:
|
||||
cr = pooler.get_db(use_new_cursor).cursor()
|
||||
cr = pooler.get_db(use_new_cursor).cursor()
|
||||
wf_service = netsvc.LocalService("workflow")
|
||||
|
||||
procurement_obj = self.pool.get('procurement.order')
|
||||
@@ -172,7 +172,7 @@ class procurement_order(osv.osv):
|
||||
if not context:
|
||||
context = {}
|
||||
if use_new_cursor:
|
||||
cr = pooler.get_db(use_new_cursor).cursor()
|
||||
cr = pooler.get_db(use_new_cursor).cursor()
|
||||
orderpoint_obj = self.pool.get('stock.warehouse.orderpoint')
|
||||
location_obj = self.pool.get('stock.location')
|
||||
procurement_obj = self.pool.get('procurement.order')
|
||||
@@ -196,7 +196,7 @@ class procurement_order(osv.osv):
|
||||
qty = max(op.product_min_qty, op.product_max_qty)-prods
|
||||
reste = qty % op.qty_multiple
|
||||
if reste > 0:
|
||||
qty += op.qty_multiple - reste
|
||||
qty += op.qty_multiple - reste
|
||||
newdate = DateTime.now() + DateTime.RelativeDateTime(
|
||||
days = int(op.product_id.seller_delay))
|
||||
if op.product_id.supply_method == 'buy':
|
||||
@@ -238,6 +238,7 @@ class procurement_order(osv.osv):
|
||||
cr.commit()
|
||||
cr.close()
|
||||
return {}
|
||||
|
||||
procurement_order()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -30,36 +30,36 @@ from osv import fields,osv
|
||||
class procurement_compute(osv.osv_memory):
|
||||
_name = 'procurement.orderpoint.compute'
|
||||
_description = 'Automatic Order Point'
|
||||
|
||||
|
||||
_columns = {
|
||||
'automatic': fields.boolean('Automatic Orderpoint', help='If the stock of a product is under 0, it will act like an orderpoint'),
|
||||
'automatic': fields.boolean('Automatic Orderpoint', help='If the stock of a product is under 0, it will act like an orderpoint'),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'automatic' : lambda *a: False,
|
||||
'automatic': False,
|
||||
}
|
||||
|
||||
|
||||
def _procure_calculation_orderpoint(self, cr, uid, ids, context):
|
||||
"""
|
||||
"""
|
||||
@param self: The object pointer.
|
||||
@param cr: A database cursor
|
||||
@param uid: ID of the user currently logged in
|
||||
@param ids: List of IDs selected
|
||||
@param context: A standard dictionary
|
||||
"""
|
||||
@param ids: List of IDs selected
|
||||
@param context: A standard dictionary
|
||||
"""
|
||||
proc_obj = self.pool.get('procurement.order')
|
||||
for proc in self.browse(cr, uid, ids):
|
||||
proc_obj._procure_orderpoint_confirm(cr, uid, automatic=proc.automatic, use_new_cursor=cr.dbname, context=context)
|
||||
|
||||
|
||||
return {}
|
||||
|
||||
|
||||
def procure_calculation(self, cr, uid, ids, context):
|
||||
"""
|
||||
"""
|
||||
@param self: The object pointer.
|
||||
@param cr: A database cursor
|
||||
@param uid: ID of the user currently logged in
|
||||
@param ids: List of IDs selected
|
||||
@param context: A standard dictionary
|
||||
@param ids: List of IDs selected
|
||||
@param context: A standard dictionary
|
||||
"""
|
||||
threaded_calculation = threading.Thread(target=self._procure_calculation_orderpoint, args=(cr, uid, ids, context))
|
||||
threaded_calculation.start()
|
||||
|
||||
@@ -26,43 +26,41 @@ from osv import osv, fields
|
||||
class procurement_compute_all(osv.osv_memory):
|
||||
_name = 'procurement.order.compute.all'
|
||||
_description = 'Compute all schedulers'
|
||||
|
||||
|
||||
_columns = {
|
||||
'automatic': fields.boolean('Automatic orderpoint',help='Triggers an automatic procurement for all products that have a virtual stock under 0. You should probably not use this option, we suggest using a MTO configuration on products.'),
|
||||
}
|
||||
|
||||
|
||||
_defaults ={
|
||||
'automatic': lambda *a: False,
|
||||
}
|
||||
|
||||
|
||||
def _procure_calculation_all(self, cr, uid, ids, context):
|
||||
"""
|
||||
"""
|
||||
@param self: The object pointer.
|
||||
@param cr: A database cursor
|
||||
@param uid: ID of the user currently logged in
|
||||
@param ids: List of IDs selected
|
||||
@param context: A standard dictionary
|
||||
@param ids: List of IDs selected
|
||||
@param context: A standard dictionary
|
||||
"""
|
||||
proc_obj = self.pool.get('procurement.order')
|
||||
for proc in self.browse(cr, uid, ids):
|
||||
proc_obj.run_scheduler(cr, uid, automatic=proc.automatic, use_new_cursor=cr.dbname,\
|
||||
context=context)
|
||||
context=context)
|
||||
return {}
|
||||
|
||||
def procure_calculation(self, cr, uid, ids, context):
|
||||
"""
|
||||
"""
|
||||
@param self: The object pointer.
|
||||
@param cr: A database cursor
|
||||
@param uid: ID of the user currently logged in
|
||||
@param ids: List of IDs selected
|
||||
@param context: A standard dictionary
|
||||
@param ids: List of IDs selected
|
||||
@param context: A standard dictionary
|
||||
"""
|
||||
threaded_calculation = threading.Thread(target=self._procure_calculation_all, args=(cr, uid, ids, context))
|
||||
threaded_calculation.start()
|
||||
return {}
|
||||
|
||||
|
||||
procurement_compute_all()
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
@@ -36,7 +36,7 @@ class project_issue(osv.osv, crm.crm_case):
|
||||
_name = "project.issue"
|
||||
_description = "Project Issue"
|
||||
_order = "priority, id desc"
|
||||
_inherits = {'mailgate.thread': 'thread_id'}
|
||||
_inherit = ['mailgate.thread']
|
||||
|
||||
def case_open(self, cr, uid, ids, *args):
|
||||
"""
|
||||
@@ -121,7 +121,6 @@ class project_issue(osv.osv, crm.crm_case):
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'thread_id': fields.many2one('mailgate.thread', 'Thread', required=False),
|
||||
'id': fields.integer('ID'),
|
||||
'name': fields.char('Name', size=128, required=True),
|
||||
'active': fields.boolean('Active', required=False),
|
||||
@@ -179,6 +178,8 @@ class project_issue(osv.osv, crm.crm_case):
|
||||
method=True, multi='working_days_open', type="float", store=True),
|
||||
'working_hours_close': fields.function(_compute_day, string='Working Hours to Close the Issue', \
|
||||
method=True, multi='working_days_close', type="float", store=True),
|
||||
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('history', '=', True),('res_model','=',_name)]),
|
||||
'log_ids': fields.one2many('mailgate.message', 'res_id', 'Logs', domain=[('history', '=', False),('res_model','=',_name)]),
|
||||
}
|
||||
|
||||
def _get_project(self, cr, uid, context):
|
||||
|
||||
+6
-4
@@ -205,7 +205,8 @@ class sale_order(osv.osv):
|
||||
return result.keys()
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Order Reference', size=64, required=True, select=True, help="unique number of the sale order,computed automatically when the sale order is created"),
|
||||
'name': fields.char('Order Reference', size=64, required=True,
|
||||
readonly=True, states={'draft': [('readonly', False)]}, select=True),
|
||||
'shop_id': fields.many2one('sale.shop', 'Shop', required=True, readonly=True, states={'draft': [('readonly', False)]}),
|
||||
'origin': fields.char('Source document', size=64, help="Reference of the document that generated this sale order request."),
|
||||
'client_order_ref': fields.char('Customer Reference', size=64),
|
||||
@@ -429,7 +430,6 @@ class sale_order(osv.osv):
|
||||
for preline in preinv.invoice_line:
|
||||
inv_line_id = self.pool.get('account.invoice.line').copy(cr, uid, preline.id, {'invoice_id': False, 'price_unit': -preline.price_unit})
|
||||
lines.append(inv_line_id)
|
||||
|
||||
inv = {
|
||||
'name': order.client_order_ref or order.name,
|
||||
'origin': order.name,
|
||||
@@ -462,7 +462,7 @@ class sale_order(osv.osv):
|
||||
invoices = {}
|
||||
invoice_ids = []
|
||||
picking_obj = self.pool.get('stock.picking')
|
||||
|
||||
invoice = self.pool.get('account.invoice')
|
||||
if context is None:
|
||||
context = {}
|
||||
# If date was specified, use it as date invoiced, usefull when invoices are generated this month and put the
|
||||
@@ -477,7 +477,6 @@ class sale_order(osv.osv):
|
||||
created_lines = self.pool.get('sale.order.line').invoice_line_create(cr, uid, lines)
|
||||
if created_lines:
|
||||
invoices.setdefault(o.partner_id.id, []).append((o, created_lines))
|
||||
|
||||
if not invoices:
|
||||
for o in self.browse(cr, uid, ids):
|
||||
for i in o.invoice_ids:
|
||||
@@ -486,11 +485,14 @@ class sale_order(osv.osv):
|
||||
for val in invoices.values():
|
||||
if grouped:
|
||||
res = self._make_invoice(cr, uid, val[0][0], reduce(lambda x,y: x + y, [l for o,l in val], []), context=context)
|
||||
invoice_ref = ''
|
||||
for o, l in val:
|
||||
invoice_ref += o.name + '|'
|
||||
self.write(cr, uid, [o.id], {'state': 'progress'})
|
||||
if o.order_policy == 'picking':
|
||||
picking_obj.write(cr, uid, map(lambda x: x.id, o.picking_ids), {'invoice_state': 'invoiced'})
|
||||
cr.execute('insert into sale_order_invoice_rel (order_id,invoice_id) values (%s,%s)', (o.id, res))
|
||||
invoice.write(cr, uid, [res], {'origin': invoice_ref, 'name': invoice_ref})
|
||||
else:
|
||||
for order, il in val:
|
||||
res = self._make_invoice(cr, uid, order, il, context=context)
|
||||
|
||||
@@ -65,7 +65,6 @@
|
||||
-
|
||||
!record {model: account.account, id: account_account_receivable0}:
|
||||
code: AR
|
||||
company_id: base.main_company
|
||||
currency_mode: current
|
||||
name: Receivable
|
||||
parent_id: account_account_minimalchart0
|
||||
@@ -79,7 +78,6 @@
|
||||
-
|
||||
!record {model: account.account, id: account_account_cash0}:
|
||||
code: C
|
||||
company_id: base.main_company
|
||||
currency_mode: current
|
||||
name: Cash
|
||||
parent_id: account_account_minimalchart0
|
||||
@@ -142,7 +140,6 @@
|
||||
-
|
||||
!record {model: account.journal, id: account_journal_bankjournal0}:
|
||||
code: BNK
|
||||
company_id: base.main_company
|
||||
default_credit_account_id: account_account_cash0
|
||||
default_debit_account_id: account_account_cash0
|
||||
name: Bank Journal
|
||||
|
||||
@@ -78,7 +78,6 @@
|
||||
-
|
||||
!record {model: account.account, id: account_account_cash0}:
|
||||
code: C
|
||||
company_id: base.main_company
|
||||
currency_mode: current
|
||||
name: Cash
|
||||
parent_id: account_account_minimalchart0
|
||||
|
||||
@@ -65,7 +65,6 @@
|
||||
-
|
||||
!record {model: account.account, id: account_account_receivable0}:
|
||||
code: AR
|
||||
company_id: base.main_company
|
||||
currency_mode: current
|
||||
name: Receivable
|
||||
parent_id: account_account_minimalchart0
|
||||
@@ -79,7 +78,6 @@
|
||||
-
|
||||
!record {model: account.account, id: account_account_cash0}:
|
||||
code: C
|
||||
company_id: base.main_company
|
||||
currency_mode: current
|
||||
name: Cash
|
||||
parent_id: account_account_minimalchart0
|
||||
@@ -142,7 +140,6 @@
|
||||
-
|
||||
!record {model: account.journal, id: account_journal_bankjournal0}:
|
||||
code: BNK
|
||||
company_id: base.main_company
|
||||
default_credit_account_id: account_account_cash0
|
||||
default_debit_account_id: account_account_cash0
|
||||
name: Bank Journal
|
||||
|
||||
@@ -65,7 +65,6 @@
|
||||
-
|
||||
!record {model: account.account, id: account_account_receivable0}:
|
||||
code: AR
|
||||
company_id: base.main_company
|
||||
currency_mode: current
|
||||
name: Receivable
|
||||
parent_id: account_account_minimalchart0
|
||||
@@ -79,7 +78,6 @@
|
||||
-
|
||||
!record {model: account.account, id: account_account_cash0}:
|
||||
code: C
|
||||
company_id: base.main_company
|
||||
currency_mode: current
|
||||
name: Cash
|
||||
parent_id: account_account_minimalchart0
|
||||
@@ -142,7 +140,6 @@
|
||||
-
|
||||
!record {model: account.journal, id: account_journal_bankjournal0}:
|
||||
code: BNK
|
||||
company_id: base.main_company
|
||||
default_credit_account_id: account_account_cash0
|
||||
default_debit_account_id: account_account_cash0
|
||||
name: Bank Journal
|
||||
|
||||
@@ -26,7 +26,7 @@ class sale_make_invoice(osv.osv_memory):
|
||||
_name = "sale.make.invoice"
|
||||
_description = "Sale Make Invoice"
|
||||
_columns = {
|
||||
'grouped': fields.boolean('Group the invoices'),
|
||||
'grouped': fields.boolean('Group the invoices', help='Check the box to group the invoices for the same customers'),
|
||||
'invoice_date':fields.date('Invoice Date'),
|
||||
}
|
||||
_default = {
|
||||
@@ -50,11 +50,11 @@ class sale_make_invoice(osv.osv_memory):
|
||||
for o in order_obj.browse(cr, uid, context.get(('active_ids'),[]), context):
|
||||
for i in o.invoice_ids:
|
||||
newinv.append(i.id)
|
||||
|
||||
|
||||
mod_obj =self.pool.get('ir.model.data')
|
||||
result = mod_obj._get_id(cr, uid, 'account', 'view_account_invoice_filter')
|
||||
|
||||
id = mod_obj.read(cr, uid, result, ['res_id'])
|
||||
id = mod_obj.read(cr, uid, result, ['res_id'])
|
||||
return {
|
||||
'domain': "[('id','in', ["+','.join(map(str,newinv))+"])]",
|
||||
'name': 'Invoices',
|
||||
@@ -64,7 +64,7 @@ class sale_make_invoice(osv.osv_memory):
|
||||
'view_id': False,
|
||||
'context': "{'type':'out_refund'}",
|
||||
'type': 'ir.actions.act_window',
|
||||
'search_view_id': id['id']
|
||||
'search_view_id': id['res_id']
|
||||
}
|
||||
|
||||
sale_make_invoice()
|
||||
|
||||
@@ -6,14 +6,15 @@
|
||||
<field name="model">sale.make.invoice</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Create invoices">
|
||||
<separator colspan="4" string="Do you really want to create the invoices ?" />
|
||||
<field name="grouped" />
|
||||
<form string="Create invoices">
|
||||
<separator colspan="4" string="Do you really want to create the invoices ?" />
|
||||
<field name="grouped"/>
|
||||
<newline/>
|
||||
<field name="invoice_date"/>
|
||||
<separator string="" colspan="6" />
|
||||
<separator string="" colspan="6"/>
|
||||
<button special="cancel" string="Cancel" icon="gtk-cancel"/>
|
||||
<button name="make_invoices" string="Create Invoices" type="object" icon="gtk-ok"/>
|
||||
</form>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 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/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
'depends': ['sale', 'delivery'],
|
||||
'init_xml': [],
|
||||
'update_xml': [
|
||||
'delivery_report.xml'
|
||||
'sale_delivery_report.xml'
|
||||
],
|
||||
'demo_xml': [],
|
||||
'installable': True,
|
||||
|
||||
@@ -127,6 +127,7 @@ class picking_journal(osv.osv):
|
||||
'state': fields.selection([
|
||||
('draft','Draft'),
|
||||
('open','Open'),
|
||||
('cancel','Cancel'),
|
||||
('done','Done'),
|
||||
], 'Creation date', required=True, readonly=True),
|
||||
'note': fields.text('Note'),
|
||||
@@ -138,6 +139,7 @@ class picking_journal(osv.osv):
|
||||
'state': lambda self,cr,uid,context: 'draft',
|
||||
}
|
||||
def button_picking_cancel(self, cr, uid, ids, context={}):
|
||||
self.write(cr, uid, ids, {'state':'cancel'})
|
||||
for id in ids:
|
||||
pick_ids = self.pool.get('stock.picking').search(cr, uid, [('journal_id','=',id)])
|
||||
for pickid in pick_ids:
|
||||
@@ -177,7 +179,7 @@ res_partner()
|
||||
class picking(osv.osv):
|
||||
_inherit="stock.picking"
|
||||
_columns = {
|
||||
'journal_id': fields.many2one('sale_journal.picking.journal', 'Journal'),
|
||||
'journal_id': fields.many2one('sale_journal.picking.journal', 'Journal', domain=[('state','!=', 'done')]),
|
||||
'sale_journal_id': fields.many2one('sale_journal.sale.journal', 'Sale Journal'),
|
||||
'invoice_type_id': fields.many2one('sale_journal.invoice.type', 'Invoice Type', readonly=True)
|
||||
}
|
||||
@@ -186,7 +188,7 @@ picking()
|
||||
class sale(osv.osv):
|
||||
_inherit="sale.order"
|
||||
_columns = {
|
||||
'journal_id': fields.many2one('sale_journal.sale.journal', 'Journal'),
|
||||
'journal_id': fields.many2one('sale_journal.sale.journal', 'Journal', domain=[('state','!=', 'done')]),
|
||||
'invoice_type_id': fields.many2one('sale_journal.invoice.type', 'Invoice Type')
|
||||
}
|
||||
def action_ship_create(self, cr, uid, ids, *args):
|
||||
|
||||
@@ -113,13 +113,16 @@
|
||||
<field name="arch" type="xml">
|
||||
<search string="Sales by Journal">
|
||||
<group col="8" colspan="4">
|
||||
<filter icon="terp-personal" string="My Sale Journals" domain="[('user_id','=',uid)]" help="My Sale Journals"/>
|
||||
<filter icon="terp-camera_test" string="Open" domain="[('state','=','open')]" help="Open Sale Journals"/>
|
||||
<separator orientation="vertical"/>
|
||||
<field name="name" select="1"/>
|
||||
<field name="code" select="1"/>
|
||||
<field name="user_id" select="1"/>
|
||||
<field name="date" select="1"/>
|
||||
<filter icon="terp-document-new" string="Draft" domain="[('state','=','draft')]" help="Sale Journals which are in draft state"/>
|
||||
<filter icon="gtk-open" string="Open" domain="[('state','=','open')]" help="Open Sale Journals"/>
|
||||
<filter icon="gtk-cancel" string="Cancel" domain="[('state','=','cancel')]" help="Sale Journals which are cancelled"/>
|
||||
<filter icon="terp-check" string="Confirm" domain="[('state','=','confirm')]" help="Confirmed Sale Journals"/>
|
||||
<filter icon="terp-camera_test" string="Close" domain="[('state','=','done')]" help="Sale Journals which are closed"/>
|
||||
<separator orientation="vertical"/>
|
||||
<field name="name"/>
|
||||
<field name="code"/>
|
||||
<field name="user_id"/>
|
||||
<field name="date"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
@@ -131,6 +134,7 @@
|
||||
<field name="res_model">sale_journal.sale.journal</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="context">{'search_default_user_id':uid}</field>
|
||||
<field name="search_view_id" ref="view_sale_journal_search"/>
|
||||
</record>
|
||||
|
||||
@@ -386,7 +390,7 @@
|
||||
<group col="6" colspan="2">
|
||||
<button name="button_open" string="Open Journal" states="draft" type="object" icon="gtk-open"/>
|
||||
<button name="button_close" string="Close Journal" states="open" type="object" icon="gtk-close"/>
|
||||
<button name="button_draft" string="Set to Draft" states="close,open" type="object" icon="gtk-convert"/>
|
||||
<button name="button_draft" string="Set to Draft" states="close,open,cancel" type="object" icon="gtk-convert"/>
|
||||
<button string="Cancel Picking" name="button_picking_cancel" states="draft,open" type="object" icon="gtk-cancel"/>
|
||||
</group>
|
||||
</form>
|
||||
@@ -417,13 +421,15 @@
|
||||
<field name="arch" type="xml">
|
||||
<search string="Picking Journals">
|
||||
<group col="8" colspan="4">
|
||||
<filter icon="terp-personal" string="My Picking Journals" domain="[('user_id','=',uid)]" help="My Picking Journals"/>
|
||||
<filter icon="terp-camera_test" string="Open" domain="[('state','=','open')]" help="Open Picking Journals"/>
|
||||
<filter icon="terp-document-new" string="Draft" domain="[('state','=','draft')]" help="Picking Journals which are in draft state"/>
|
||||
<filter icon="gtk-open" string="Open" domain="[('state','=','open')]" help="Open Picking Journals"/>
|
||||
<filter icon="gtk-cancel" string="Cancel" domain="[('state','=','cancel')]" help="Picking Journals which are cancelled"/>
|
||||
<filter icon="terp-camera_test" string="Close" domain="[('state','=','done')]" help="Picking Journals which are closed"/>
|
||||
<separator orientation="vertical"/>
|
||||
<field name="name" select="1"/>
|
||||
<field name="code" select="1"/>
|
||||
<field name="user_id" select="1"/>
|
||||
<field name="date" select="1"/>
|
||||
<field name="name"/>
|
||||
<field name="code"/>
|
||||
<field name="user_id"/>
|
||||
<field name="date"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
@@ -436,6 +442,7 @@
|
||||
<field name="res_model">sale_journal.picking.journal</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="context">{'search_default_user_id':uid}</field>
|
||||
<field name="search_view_id" ref="view_picking_journal_search"/>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -26,6 +26,16 @@ class sale_order_line(osv.osv):
|
||||
_name = "sale.order.line"
|
||||
_inherit = "sale.order.line"
|
||||
|
||||
def product_id_change(self, cr, uid, ids, pricelist, product, qty=0,
|
||||
uom=False, qty_uos=0, uos=False, name='', partner_id=False,
|
||||
lang=False, update_tax=True, date_order=False, packaging=False, fiscal_position=False, flag=False):
|
||||
res = super(sale_order_line, self).product_id_change(cr, uid, ids, pricelist, product, qty=qty,
|
||||
uom=uom, qty_uos=qty_uos, uos=uos, name=name, partner_id=partner_id,
|
||||
lang=lang, update_tax=update_tax, date_order=date_order, packaging=packaging, fiscal_position=fiscal_position, flag=flag)
|
||||
purchase_price = self.pool.get('product.product').browse(cr, uid, product).standard_price
|
||||
res['value'].update({'purchase_price':purchase_price})
|
||||
return res
|
||||
|
||||
def _product_margin(self, cr, uid, ids, field_name, arg, context=None):
|
||||
res = {}
|
||||
for line in self.browse(cr, uid, ids):
|
||||
@@ -38,7 +48,7 @@ class sale_order_line(osv.osv):
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'margin': fields.function(_product_margin, method=True, string='Margin', store=True),
|
||||
'margin': fields.function(_product_margin, method=True, string='Margin', store={}),
|
||||
'purchase_price': fields.float('Cost Price', digits=(16,2))
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,31 @@
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="sale_margin_sale_order_line">
|
||||
<field name="name">sale.order.line.margin.view.form</field>
|
||||
<field name="type">form</field>
|
||||
<field name="model">sale.order</field>
|
||||
<field name="inherit_id" ref="sale.view_order_form" />
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="/form/notebook/page/field[@name='order_line']/form/notebook/page/field[@name='price_unit']" position="after">
|
||||
<field name="purchase_price"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="sale_margin_sale_order_line_form">
|
||||
<field name="name">sale.order.line.tree.margin.view.form</field>
|
||||
<field name="type">form</field>
|
||||
<field name="model">sale.order</field>
|
||||
<field name="inherit_id" ref="sale.view_order_form" />
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="/form/notebook/page/field[@name='order_line']/tree/field[@name='price_unit']" position="after">
|
||||
<field name="purchase_price"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="sale_margin_sale_order_tree">
|
||||
<field name="name">sale.order.margin.view.tree</field>
|
||||
<field name="type">tree</field>
|
||||
@@ -24,7 +49,7 @@
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record model="ir.ui.view" id="sale_margin_sale_order_line_tree">
|
||||
<field name="name">sale.order.margin.line.view.tree</field>
|
||||
<field name="type">tree</field>
|
||||
@@ -42,7 +67,7 @@
|
||||
<field name="name">picking.margin.view.form</field>
|
||||
<field name="type">form</field>
|
||||
<field name="model">stock.picking</field>
|
||||
<field name="inherit_id" ref="stock.view_picking_out_form" />
|
||||
<field name="inherit_id" ref="stock.view_picking_in_form" />
|
||||
<field name="arch" type="xml">
|
||||
<notebook colspan="4">
|
||||
<page string="Supplier Invoices">
|
||||
|
||||
Reference in New Issue
Block a user