diff --git a/.hgignore b/.hgignore index 05eeec70d0..2e6331fd7e 100644 --- a/.hgignore +++ b/.hgignore @@ -1,4 +1,6 @@ syntax: glob .hgignore *.pyc -*~ \ No newline at end of file +*~ +addons/* +trytond.conf diff --git a/trytond/config.py b/trytond/config.py index eff831c265..e468671caf 100644 --- a/trytond/config.py +++ b/trytond/config.py @@ -50,7 +50,7 @@ class ConfigManager(object): parser.add_option("-c", "--config", dest="config", help="specify alternate config file") parser.add_option("-s", "--save", action="store_true", dest="save", - default=False, help="save configuration to ~/.terp_serverrc") + default=False, help="save configuration to ~/.trytondrc") parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False, help="enable debugging") parser.add_option("--pidfile", dest="pidfile", @@ -125,12 +125,12 @@ class ConfigManager(object): # or even to start the server... if os.name == 'nt': rcfilepath = os.path.join(os.path.abspath( - os.path.dirname(sys.argv[0])), 'tinyerp-server.conf') + os.path.dirname(sys.argv[0])), 'tryton-server.conf') else: - rcfilepath = os.path.expanduser('~/.terp_serverrc') + rcfilepath = os.path.expanduser('~/.trytondrc') self.rcfile = fname or opt.config \ - or os.environ.get('TERP_SERVER') or rcfilepath + or os.environ.get('TRYTOND') or rcfilepath self.load() # Verify that we want to log or not, if not the output will go to stdout diff --git a/trytond/init.sql b/trytond/init.sql index e6b3fb4866..fa62e6df2d 100644 --- a/trytond/init.sql +++ b/trytond/init.sql @@ -41,7 +41,7 @@ CREATE TABLE ir_model ( CREATE TABLE ir_model_fields ( id serial, model varchar(64) DEFAULT ''::varchar NOT NULL, - model_id int references ir_model, + model_id int references ir_model on delete cascade, name varchar(64) DEFAULT ''::varchar NOT NULL, relation varchar(64), field_description varchar(256), @@ -172,7 +172,7 @@ create table wkf_transition create table wkf_instance ( id serial, - wkf_id int references wkf on delete set null, + wkf_id int references wkf on delete restrict, uid int default null, res_id int not null, res_type varchar(64) not null, diff --git a/trytond/ir/__terp__.py b/trytond/ir/__tryton__.py similarity index 100% rename from trytond/ir/__terp__.py rename to trytond/ir/__tryton__.py diff --git a/trytond/ir/actions.xml b/trytond/ir/actions.xml index 62ff273969..54df963dcf 100644 --- a/trytond/ir/actions.xml +++ b/trytond/ir/actions.xml @@ -1,5 +1,5 @@ - + @@ -245,4 +245,4 @@ - + diff --git a/trytond/ir/attachment.xml b/trytond/ir/attachment.xml index 05e7482258..97bb07810e 100644 --- a/trytond/ir/attachment.xml +++ b/trytond/ir/attachment.xml @@ -1,5 +1,5 @@ - + ir.attachment @@ -53,4 +53,4 @@ - + diff --git a/trytond/ir/cron.xml b/trytond/ir/cron.xml index d5eec554fe..eeb437a02f 100644 --- a/trytond/ir/cron.xml +++ b/trytond/ir/cron.xml @@ -1,5 +1,5 @@ - + ir.cron @@ -63,4 +63,4 @@ - + diff --git a/trytond/ir/exports.xml b/trytond/ir/exports.xml index c5cbf1108e..6815936e65 100644 --- a/trytond/ir/exports.xml +++ b/trytond/ir/exports.xml @@ -1,5 +1,5 @@ - + ir.exports @@ -47,4 +47,4 @@ - + diff --git a/trytond/ir/ir.xml b/trytond/ir/ir.xml index 057da56bf9..8fce1df812 100644 --- a/trytond/ir/ir.xml +++ b/trytond/ir/ir.xml @@ -1,7 +1,7 @@ - + - + diff --git a/trytond/ir/model.py b/trytond/ir/model.py index 3b2b7dce13..d00a922f33 100644 --- a/trytond/ir/model.py +++ b/trytond/ir/model.py @@ -32,7 +32,7 @@ class ModelFields(OSV): 'model': fields.char('Model Name', size=64, required=True), 'relation': fields.char('Model Relation', size=64), 'model_id': fields.many2one('ir.model', 'Model id', required=True, - select=True), + select=True, ondelete='cascade'), 'field_description': fields.char('Field Description', size=256), 'ttype': fields.char('Field Type', size=64), 'relate': fields.boolean('Click and Relate'), diff --git a/trytond/ir/model.xml b/trytond/ir/model.xml index c678beea70..755d869100 100644 --- a/trytond/ir/model.xml +++ b/trytond/ir/model.xml @@ -1,5 +1,5 @@ - + ir.model @@ -153,4 +153,4 @@ action="act_model_access_form" id="menu_model_access_form"/> - + diff --git a/trytond/ir/module/category.xml b/trytond/ir/module/category.xml index 4c09f7f3c5..6629353189 100644 --- a/trytond/ir/module/category.xml +++ b/trytond/ir/module/category.xml @@ -1,5 +1,5 @@ - + ir.module.category @@ -41,4 +41,4 @@ - + diff --git a/trytond/ir/module/module.py b/trytond/ir/module/module.py index e4376fbb8f..2493ce998b 100644 --- a/trytond/ir/module/module.py +++ b/trytond/ir/module/module.py @@ -128,10 +128,10 @@ class Module(OSV): @staticmethod def get_module_info(name): - "Return the content of the __terp__.py" + "Return the content of the __tryton__.py" try: file_p = tools.file_open(os.path.join(ADDONS_PATH, name, - '__terp__.py')) + '__tryton__.py')) data = file_p.read() info = eval(data) file_p.close() @@ -320,36 +320,36 @@ class Module(OSV): if ids: module_id = ids[0] mod = self.browse(cursor, user, module_id) - terp = Module.get_module_info(mod_name) - if terp.get('installable', True) \ + tryton = Module.get_module_info(mod_name) + if tryton.get('installable', True) \ and mod.state == 'uninstallable': self.write(cursor, user, module_id, { 'state': 'uninstalled'}, context=context) - if vercmp(terp.get('version', ''), + if vercmp(tryton.get('version', ''), mod.latest_version or '0') > 0: self.write(cursor, user, module_id, { - 'latest_version': terp.get('version'), + 'latest_version': tryton.get('version'), 'url': '', }, context=context) res[0] += 1 self.write(cursor, user, module_id, { - 'description': terp.get('description', ''), - 'shortdesc': terp.get('name', ''), - 'author': terp.get('author', ''), - 'website': terp.get('website', ''), - 'license': terp.get('license', 'GPL-2'), + 'description': tryton.get('description', ''), + 'shortdesc': tryton.get('name', ''), + 'author': tryton.get('author', ''), + 'website': tryton.get('website', ''), + 'license': tryton.get('license', 'GPL-2'), }) self._update_dependencies(cursor, user, module_id, - terp.get('depends', [])) + tryton.get('depends', [])) self._update_category(cursor, user, module_id, - terp.get('category', 'None')) + tryton.get('category', 'None')) continue mod_path = os.path.join(ADDONS_PATH, name) if os.path.isdir(mod_path) \ or os.path.islink(mod_path) \ or zipfile.is_zipfile(mod_path): - terp = Module.get_module_info(mod_name) - if not terp or not terp.get('installable', True): + tryton = Module.get_module_info(mod_name) + if not tryton or not tryton.get('installable', True): continue if not os.path.isfile( os.path.join(ADDONS_PATH, mod_name+'.zip')): @@ -364,18 +364,18 @@ class Module(OSV): new_id = self.create(cursor, user, { 'name': mod_name, 'state': 'uninstalled', - 'description': terp.get('description', ''), - 'shortdesc': terp.get('name', ''), - 'author': terp.get('author', 'Unknown'), - 'website': terp.get('website', ''), - 'latest_version': terp.get('version', ''), - 'license': terp.get('license', 'GPL-2'), + 'description': tryton.get('description', ''), + 'shortdesc': tryton.get('name', ''), + 'author': tryton.get('author', 'Unknown'), + 'website': tryton.get('website', ''), + 'latest_version': tryton.get('version', ''), + 'license': tryton.get('license', 'GPL-2'), }) res[1] += 1 self._update_dependencies(cursor, user, new_id, - terp.get('depends', [])) + tryton.get('depends', [])) self._update_category(cursor, user, new_id, - terp.get('category', 'None')) + tryton.get('category', 'None')) import socket socket.setdefaulttimeout(10) @@ -448,17 +448,17 @@ class Module(OSV): except IOError: raise ExceptORM('Error', 'Can not create the module file: %s' % (fname,)) - terp = Module.get_module_info(mod.name) + tryton = Module.get_module_info(mod.name) self.write(cursor, user, mod.id, { - 'description': terp.get('description', ''), - 'shortdesc': terp.get('name', ''), - 'author': terp.get('author', 'Unknown'), - 'website': terp.get('website', ''), - 'license': terp.get('license', 'GPL-2'), + 'description': tryton.get('description', ''), + 'shortdesc': tryton.get('name', ''), + 'author': tryton.get('author', 'Unknown'), + 'website': tryton.get('website', ''), + 'license': tryton.get('license', 'GPL-2'), }) - self._update_dependencies(cursor, user, mod.id, terp.get('depends', + self._update_dependencies(cursor, user, mod.id, tryton.get('depends', [])) - self._update_category(cursor, user, mod.id, terp.get('category', + self._update_category(cursor, user, mod.id, tryton.get('category', 'Uncategorized')) return res @@ -524,7 +524,7 @@ class ModuleDependency(OSV): _columns = { 'name': fields.char('Name', size=128), - 'module_id': fields.many2one('ir.module.module', 'Module', select=1), + 'module_id': fields.many2one('ir.module.module', 'Module', select=1, ondelete='cascade'), 'state': fields.function(_state, method=True, type='selection', selection=[ ('uninstallable','Uninstallable'), diff --git a/trytond/ir/module/module.xml b/trytond/ir/module/module.xml index dd87930c05..74499be1d4 100644 --- a/trytond/ir/module/module.xml +++ b/trytond/ir/module/module.xml @@ -1,5 +1,5 @@ - + @@ -187,4 +187,4 @@ type="wizard" id="menu_module_install_upgrade"/> - + diff --git a/trytond/ir/module/repository.xml b/trytond/ir/module/repository.xml index 193a87ce73..72e9219218 100644 --- a/trytond/ir/module/repository.xml +++ b/trytond/ir/module/repository.xml @@ -1,5 +1,5 @@ - + ir.module.repository @@ -51,4 +51,4 @@ - + diff --git a/trytond/ir/property.xml b/trytond/ir/property.xml index 6909026848..ae4c0c7672 100644 --- a/trytond/ir/property.xml +++ b/trytond/ir/property.xml @@ -1,5 +1,5 @@ - + ir.property @@ -72,4 +72,4 @@ - + diff --git a/trytond/ir/rule.xml b/trytond/ir/rule.xml index 46ec065e93..1bd3153c71 100644 --- a/trytond/ir/rule.xml +++ b/trytond/ir/rule.xml @@ -1,5 +1,5 @@ - + ir.rule.group @@ -82,4 +82,4 @@ - + diff --git a/trytond/ir/sequence.xml b/trytond/ir/sequence.xml index 116a7e5e27..f8be96f28b 100644 --- a/trytond/ir/sequence.xml +++ b/trytond/ir/sequence.xml @@ -1,5 +1,5 @@ - + @@ -106,4 +106,4 @@ - + diff --git a/trytond/ir/translation.xml b/trytond/ir/translation.xml index ed26bbb89f..915fb7a047 100644 --- a/trytond/ir/translation.xml +++ b/trytond/ir/translation.xml @@ -1,5 +1,5 @@ - + ir.translation @@ -52,4 +52,4 @@ - + diff --git a/trytond/ir/ui/menu.xml b/trytond/ir/ui/menu.xml index 4b51c6d78e..58692cc19e 100644 --- a/trytond/ir/ui/menu.xml +++ b/trytond/ir/ui/menu.xml @@ -1,5 +1,5 @@ - + ir.ui.menu @@ -75,4 +75,4 @@ - + diff --git a/trytond/ir/ui/ui.xml b/trytond/ir/ui/ui.xml index 1e9bf9d053..18aae7c6cd 100644 --- a/trytond/ir/ui/ui.xml +++ b/trytond/ir/ui/ui.xml @@ -1,6 +1,6 @@ - + - + diff --git a/trytond/ir/ui/view.xml b/trytond/ir/ui/view.xml index b1e9f3a124..ea22bf5c7c 100644 --- a/trytond/ir/ui/view.xml +++ b/trytond/ir/ui/view.xml @@ -1,5 +1,5 @@ - + ir.ui.view @@ -95,4 +95,4 @@ - + diff --git a/trytond/ir/values.xml b/trytond/ir/values.xml index 9efc3ab89f..1c259be65e 100644 --- a/trytond/ir/values.xml +++ b/trytond/ir/values.xml @@ -1,5 +1,5 @@ - + ir.values @@ -56,4 +56,4 @@ - + diff --git a/trytond/module.py b/trytond/module.py index 95c2cc0624..edb1d542c7 100644 --- a/trytond/module.py +++ b/trytond/module.py @@ -106,18 +106,18 @@ def create_graph(module_list, force=None): for module in module_list: if module[-4:] == '.zip': module = module[:-4] - terp_file = OPJ(ADDONS_PATH, module, '__terp__.py') + tryton_file = OPJ(ADDONS_PATH, module, '__tryton__.py') mod_path = OPJ(ADDONS_PATH, module) if module in ('ir', 'workflow', 'res'): root_path = os.path.dirname(__file__) - terp_file = OPJ(root_path, module, '__terp__.py') + tryton_file = OPJ(root_path, module, '__tryton__.py') mod_path = OPJ(root_path, module) - if os.path.isfile(terp_file) or zipfile.is_zipfile(mod_path+'.zip'): + if os.path.isfile(tryton_file) or zipfile.is_zipfile(mod_path+'.zip'): try: - info = eval(tools.file_open(terp_file).read()) + info = eval(tools.file_open(tryton_file).read()) except: Logger().notify_channel('init', LOG_ERROR, - 'addon:%s:eval file %s' % (module, terp_file)) + 'addon:%s:eval file %s' % (module, tryton_file)) raise if info.get('installable', True): packages.append((module, info.get('depends', []), info)) diff --git a/trytond/osv/orm.py b/trytond/osv/orm.py index dde2b92e46..6f0f24edc2 100644 --- a/trytond/osv/orm.py +++ b/trytond/osv/orm.py @@ -584,6 +584,55 @@ class ORM(object): cursor.execute("DROP INDEX \"%s_%s_index\"" % \ (self._table, k)) cursor.commit() + if isinstance(field, fields.many2one): + ref_obj = self.pool.get(field._obj) + if ref_obj: + ref = ref_obj._table + else: + ref = field._obj.replace('.', '_') + if ref != 'ir_actions': + cursor.execute('SELECT confdeltype, conname ' \ + 'FROM pg_constraint as con, ' \ + 'pg_class as cl1, pg_class as cl2, ' \ + 'pg_attribute as att1, pg_attribute as att2 ' \ + 'WHERE con.conrelid = cl1.oid ' \ + 'AND cl1.relname = %s ' \ + 'AND con.confrelid = cl2.oid ' \ + 'AND cl2.relname = %s ' \ + 'AND array_lower(con.conkey, 1) = 1 ' \ + 'AND con.conkey[1] = att1.attnum ' \ + 'AND att1.attrelid = cl1.oid ' \ + 'AND att1.attname = %s ' \ + 'AND array_lower(con.confkey, 1) = 1 ' \ + 'AND con.confkey[1] = att2.attnum ' \ + 'AND att2.attrelid = cl2.oid ' \ + 'AND att2.attname = %s ' \ + 'AND con.contype = \'f\'', + (self._table, ref, k, 'id')) + res = cursor.dictfetchall() + if res: + confdeltype = { + 'RESTRICT': 'r', + 'NO ACTION': 'a', + 'CASCADE': 'c', + 'SET NULL': 'n', + 'SET DEFAULT': 'd', + } + if res[0]['confdeltype'] != \ + confdeltype.get( + field.ondelete.upper(), + 'a'): + cursor.execute('ALTER TABLE "' + \ + self._table + '" ' \ + 'DROP CONSTRAINT "' + \ + res[0]['conname'] + '"') + cursor.execute('ALTER TABLE "' + \ + self._table + '" ' \ + 'ADD FOREIGN KEY ' \ + '("' + k + '") ' \ + 'REFERENCES "' + ref + \ + '" ON DELETE ' + field.ondelete) + cursor.commit() else: # TODO add error message logger.notify_channel('init', LOG_ERROR, '') @@ -1562,7 +1611,7 @@ class ORM(object): result = self.view_header_get(cursor, user, False, node.localName, context) if result: - node.setAttribute('string', result) + node.setAttribute('string', result.decode('utf8')) if node.nodeType == node.ELEMENT_NODE: # translate view @@ -1594,13 +1643,13 @@ class ORM(object): for fname, gname in cursor.fetchall(): if oldgroup != gname: child = doc.createElement('separator') - child.setAttribute('string', gname) + child.setAttribute('string', gname.decode('utf8')) child.setAttribute('colspan', "4") oldgroup = gname parent.insertBefore(child, node) child = doc.createElement('field') - child.setAttribute('name', fname) + child.setAttribute('name', fname.decode('utf8')) parent.insertBefore(child, node) parent.removeChild(node) diff --git a/trytond/res/__terp__.py b/trytond/res/__tryton__.py similarity index 100% rename from trytond/res/__terp__.py rename to trytond/res/__tryton__.py diff --git a/trytond/res/lang.xml b/trytond/res/lang.xml index d50454b4e9..04385ec260 100644 --- a/trytond/res/lang.xml +++ b/trytond/res/lang.xml @@ -1,5 +1,5 @@ - + en_US @@ -35,4 +35,4 @@ - + diff --git a/trytond/res/report/user.odt b/trytond/res/report/user.odt new file mode 100644 index 0000000000..7b1b0e7446 Binary files /dev/null and b/trytond/res/report/user.odt differ diff --git a/trytond/res/request.xml b/trytond/res/request.xml index 20e439c31c..8da2872e9a 100644 --- a/trytond/res/request.xml +++ b/trytond/res/request.xml @@ -1,5 +1,5 @@ - + res.request @@ -136,4 +136,4 @@ - + diff --git a/trytond/res/res.xml b/trytond/res/res.xml index 34c4dfd13c..7600ca808d 100644 --- a/trytond/res/res.xml +++ b/trytond/res/res.xml @@ -1,6 +1,6 @@ - + - + diff --git a/trytond/res/users.xml b/trytond/res/users.xml index e5e0510c4a..c08abefd33 100644 --- a/trytond/res/users.xml +++ b/trytond/res/users.xml @@ -1,5 +1,5 @@ - + admin @@ -186,4 +186,4 @@ - + diff --git a/trytond/sql_db.py b/trytond/sql_db.py index e72e709d04..ecdc0641d6 100644 --- a/trytond/sql_db.py +++ b/trytond/sql_db.py @@ -116,20 +116,20 @@ def init_db(cursor): addons_path = os.path.join(os.path.dirname(__file__), 'addons') for i in (os.listdir(addons_path) + ['ir', 'workflow', 'res']): - terp_file = opj(addons_path, i, '__terp__.py') + tryton_file = opj(addons_path, i, '__tryton__.py') mod_path = opj(addons_path, i) if i in ('ir', 'workflow', 'res'): root_path = os.path.dirname(__file__) - terp_file = opj(root_path, i, '__terp__.py') + tryton_file = opj(root_path, i, '__tryton__.py') mod_path = opj(root_path, i) info = {} - if os.path.isfile(terp_file) \ + if os.path.isfile(tryton_file) \ and not os.path.isfile(opj(addons_path, i + '.zip')): - info = eval(file(terp_file).read()) + info = eval(file(tryton_file).read()) elif zipfile.is_zipfile(mod_path): zfile = zipfile.ZipFile(mod_path) i = os.path.splitext(i)[0] - info = eval(zfile.read(opj(i, '__terp__.py'))) + info = eval(zfile.read(opj(i, '__tryton__.py'))) if info: categs = info.get('category', 'Uncategorized').split('/') p_id = None diff --git a/trytond/tools/convert.py b/trytond/tools/convert.py index 34c3848021..c38a183334 100644 --- a/trytond/tools/convert.py +++ b/trytond/tools/convert.py @@ -274,7 +274,7 @@ class TrytondXmlHandler(sax.handler.ContentHandler): self.taghandler = None # Managed tags are handled by the current class - self.managedtags= ["data", "terp"] + self.managedtags= ["data", "tryton"] self.idlist = [] @@ -301,7 +301,7 @@ class TrytondXmlHandler(sax.handler.ContentHandler): elif name == "data": self.noupdate = attributes.get("noupdate", False) - elif name == "terp": + elif name == "tryton": pass else: diff --git a/trytond/workflow/__terp__.py b/trytond/workflow/__tryton__.py similarity index 100% rename from trytond/workflow/__terp__.py rename to trytond/workflow/__tryton__.py diff --git a/trytond/workflow/workflow.py b/trytond/workflow/workflow.py index 01733fec21..62a5b1b0cf 100644 --- a/trytond/workflow/workflow.py +++ b/trytond/workflow/workflow.py @@ -44,7 +44,7 @@ class WorkflowActivity(OSV): _columns = { 'name': fields.char('Name', size=64, required=True), 'wkf_id': fields.many2one('workflow', 'Workflow', required=True, - select=1), + select=1, ondelete='cascade'), 'split_mode': fields.selection([ ('XOR', 'Xor'), ('OR', 'Or'), @@ -93,9 +93,9 @@ class WorkflowTransition(OSV): 'role_id': fields.many2one('res.role', 'Role Required'), 'condition': fields.char('Condition', required=True, size=128), 'act_from': fields.many2one('workflow.activity', 'Source Activity', - required=True, select=1), + required=True, select=1, ondelete='cascade'), 'act_to': fields.many2one('workflow.activity', 'Destination Activity', - required=True, select=1), + required=True, select=1, ondelete='cascade'), } _defaults = { 'condition': lambda *a: 'True', @@ -112,7 +112,7 @@ class WorkflowInstance(OSV): _log_access = False _description = __doc__ _columns = { - 'wkf_id': fields.many2one('workflow', 'Workflow', ondelete="cascade"), + 'wkf_id': fields.many2one('workflow', 'Workflow', ondelete="restrict"), 'uid': fields.integer('User ID'), 'res_id': fields.integer('Resource ID'), 'res_type': fields.char('Resource Model', size=64), diff --git a/trytond/workflow/workflow.xml b/trytond/workflow/workflow.xml index 14d1d75e74..23e01e4d6e 100644 --- a/trytond/workflow/workflow.xml +++ b/trytond/workflow/workflow.xml @@ -1,5 +1,5 @@ - + @@ -271,4 +271,4 @@ - +