# -*- encoding: utf-8 -*- ############################################################################## # # OpenERP, Open Source Management Solution # Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved # $Id$ # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # ############################################################################## import base64 from osv import osv, fields from osv.orm import except_orm import urlparse import os import pooler from content_index import content_index import netsvc import StringIO import random import string from psycopg2 import Binary from tools import config import tools def random_name(): random.seed() d = [random.choice(string.letters) for x in xrange(10) ] name = "".join(d) return name # Unsupported WebDAV Commands: # label # search # checkin # checkout # propget # propset # # An object that represent an uri # path: the uri of the object # content: the Content it belongs to (_print.pdf) # type: content or collection # content: objct = res.partner # collection: object = directory, object2 = res.partner # file: objct = ir.attachement # root: if we are at the first directory of a ressource # INVALID_CHARS={'*':str(hash('*')), '|':str(hash('|')) , "\\":str(hash("\\")), '/':'__', ':':str(hash(':')), '"':str(hash('"')), '<':str(hash('<')) , '>':str(hash('>')) , '?':str(hash('?'))} class node_class(object): def __init__(self, cr, uid, path,object,object2=False, context={}, content=False, type='collection', root=False): self.cr = cr self.uid = uid self.path = path self.object = object self.object2 = object2 self.context = context self.content = content self.type=type self.root=root def _file_get(self, nodename=False): if not self.object: return [] pool = pooler.get_pool(self.cr.dbname) fobj = pool.get('ir.attachment') res2 = [] where = [] if self.object2: where.append( ('res_model','=',self.object2._name) ) where.append( ('res_id','=',self.object2.id) ) else: where.append( ('parent_id','=',self.object.id) ) where.append( ('res_id','=',False) ) if nodename: where.append( (fobj._rec_name,'like',nodename) ) for content in self.object.content_ids: if self.object2 or not content.include_name: if content.include_name: test_nodename = self.object2.name + (content.suffix or '') + (content.extension or '') else: test_nodename = (content.suffix or '') + (content.extension or '') if test_nodename.find('/'): test_nodename=test_nodename.replace('/', '_') path = self.path+'/'+test_nodename if not nodename: n = node_class(self.cr, self.uid,path, self.object2, False, content=content, type='content', root=False) res2.append( n) else: if nodename == test_nodename: n = node_class(self.cr, self.uid, path, self.object2, False, content=content, type='content', root=False) res2.append(n) ids = fobj.search(self.cr, self.uid, where+[ ('parent_id','=',self.object and self.object.id or False) ], context=self.context) if self.object and self.root and (self.object.type=='ressource'): ids += fobj.search(self.cr, self.uid, where+[ ('parent_id','=',False) ], context=self.context) res = fobj.browse(self.cr, self.uid, ids, context=self.context) return map(lambda x: node_class(self.cr, self.uid, self.path+'/'+x.name, x, False, type='file', root=False), res) + res2 def directory_list_for_child(self,nodename,parent=False): pool = pooler.get_pool(self.cr.dbname) where = [] if nodename: where.append(('name','like',nodename)) if (self.object and self.object.type=='directory') or not self.object2: where.append(('parent_id','=',self.object and self.object.id or False)) else: where.append(('parent_id','=',False)) if self.object: where.append(('ressource_parent_type_id','=',self.object.ressource_type_id.id)) else: where.append(('ressource_parent_type_id','=',False)) ids = pool.get('document.directory').search(self.cr, self.uid, where+[('ressource_id','=',0)], self.context) if self.object2: ids += pool.get('document.directory').search(self.cr, self.uid, where+[('ressource_id','=',self.object2.id)], self.context) res = pool.get('document.directory').browse(self.cr, self.uid, ids,self.context) return res def _child_get(self, nodename=False): if self.type not in ('collection','database'): return [] res = self.directory_list_for_child(nodename) result= map(lambda x: node_class(self.cr, self.uid, self.path+'/'+x.name, x, x.type=='directory' and self.object2 or False, root=self.root), res) if self.type=='database': pool = pooler.get_pool(self.cr.dbname) fobj = pool.get('ir.attachment') vargs = [('parent_id','=',False),('res_id','=',False)] if nodename: vargs.append(('name','like',nodename)) file_ids=fobj.search(self.cr,self.uid,vargs) res = fobj.browse(self.cr, self.uid, file_ids, context=self.context) result +=map(lambda x: node_class(self.cr, self.uid, self.path+'/'+x.name, x, False, type='file', root=self.root), res) if self.type=='collection' and self.object.type=="ressource": where = self.object.domain and eval(self.object.domain, {'active_id':self.root}) or [] pool = pooler.get_pool(self.cr.dbname) obj = pool.get(self.object.ressource_type_id.model) if self.object.ressource_tree: if obj._parent_name in obj.fields_get(self.cr,self.uid): where.append((obj._parent_name,'=',self.object2 and self.object2.id or False)) else : if self.object2: return result else: if self.object2: return result name_for = obj._name.split('.')[-1] if nodename and nodename.find(name_for) == 0 : id = int(nodename.replace(name_for,'')) where.append(('id','=',id)) elif nodename: if nodename.find('__') : nodename=nodename.replace('__','/') for invalid in INVALID_CHARS: if nodename.find(INVALID_CHARS[invalid]) : nodename=nodename.replace(INVALID_CHARS[invalid],invalid) where.append(('name','like',nodename)) ids = obj.search(self.cr, self.uid, where, self.context) res = obj.browse(self.cr, self.uid, ids,self.context) for r in res: if not r.name: r.name = name_for+'%d'%r.id for invalid in INVALID_CHARS: if r.name.find(invalid) : r.name=r.name.replace(invalid,INVALID_CHARS[invalid]) result2 = map(lambda x: node_class(self.cr, self.uid, self.path+'/'+x.name.replace('/','__'), self.object, x, root=r.id), res) if result2: result = result2 return result def children(self): return self._child_get() + self._file_get() def child(self, name): res = self._child_get(name) if res: return res[0] res = self._file_get(name) if res: return res[0] return None def path_get(self): path = self.path if self.path[0]=='/': path = self.path[1:] return path class document_directory(osv.osv): _name = 'document.directory' _description = 'Document directory' _columns = { 'name': fields.char('Name', size=64, required=True, select=1), 'write_date': fields.datetime('Date Modified', readonly=True), 'write_uid': fields.many2one('res.users', 'Last Modification User', readonly=True), 'create_date': fields.datetime('Date Created', readonly=True), 'create_uid': fields.many2one('res.users', 'Creator', readonly=True), 'file_type': fields.char('Content Type', size=32), 'domain': fields.char('Domain', size=128, help="Use a domain if you want to apply an automatic filter on visible resources."), 'user_id': fields.many2one('res.users', 'Owner'), 'group_ids': fields.many2many('res.groups', 'document_directory_group_rel', 'item_id', 'group_id', 'Groups'), 'parent_id': fields.many2one('document.directory', 'Parent Item'), 'child_ids': fields.one2many('document.directory', 'parent_id', 'Children'), 'file_ids': fields.one2many('ir.attachment', 'parent_id', 'Files'), 'content_ids': fields.one2many('document.directory.content', 'directory_id', 'Virtual Files'), 'type': fields.selection([('directory','Static Directory'),('ressource','Other Resources')], 'Type', required=True), 'ressource_type_id': fields.many2one('ir.model', 'Directories Mapped to Objects', help="Select an object here and Open ERP will create a mapping for each of these " \ "objects, using the given domain, when browsing through FTP."), 'ressource_parent_type_id': fields.many2one('ir.model', 'Parent Model', help="If you put an object here, this directory template will appear bellow all of these objects. " \ "Don't put a parent directory if you select a parent model."), 'ressource_id': fields.integer('Resource ID'), 'ressource_tree': fields.boolean('Tree Structure', help="Check this if you want to use the same tree structure as the object selected in the system."), } _defaults = { 'user_id': lambda self,cr,uid,ctx: uid, 'domain': lambda self,cr,uid,ctx: '[]', 'type': lambda *args: 'directory', 'ressource_id': lambda *a: 0 } _sql_constraints = [ ('dirname_uniq', 'unique (name,parent_id,ressource_id,ressource_parent_type_id)', 'The directory name must be unique !') ] def get_resource_path(self,cr,uid,dir_id,res_model,res_id): # this method will be used in process module # to be need test and Improvement if resource dir has parent resource (link resource) path=[] def _parent(dir_id,path): parent=self.browse(cr,uid,dir_id) if parent.parent_id and not parent.ressource_parent_type_id: _parent(parent.parent_id.id,path) path.append(parent.name) else: path.append(parent.name) return path directory=self.browse(cr,uid,dir_id) model_ids=self.pool.get('ir.model').search(cr,uid,[('model','=',res_model)]) if directory: _parent(dir_id,path) path.append(self.pool.get(directory.ressource_type_id.model).browse(cr,uid,res_id).name) user=self.pool.get('res.users').browse(cr,uid,uid) return "ftp://%s:%s@localhost:%s/%s/%s"%(user.login,user.password,config.get('ftp_server_port',8021),cr.dbname,'/'.join(path)) return False def _check_recursion(self, cr, uid, ids): level = 100 while len(ids): cr.execute('select distinct parent_id from document_directory where id in ('+','.join(map(str,ids))+')') ids = filter(None, map(lambda x:x[0], cr.fetchall())) if not level: return False level -= 1 return True _constraints = [ (_check_recursion, 'Error! You can not create recursive Directories.', ['parent_id']) ] def __init__(self, *args, **kwargs): res = super(document_directory, self).__init__(*args, **kwargs) self._cache = {} return res def onchange_content_id(self, cr, uid, ids, ressource_type_id): return {} def _get_childs(self, cr, uid, node, nodename=False, context={}): where = [] if nodename: where.append(('name','like',nodename)) if object: where.append(('parent_id','=',object.id)) ids = self.search(cr, uid, where, context) return self.browse(cr, uid, ids, context), False """ PRE: uri: of the form "Sales Order/SO001" PORT: uri object: the object.directory or object.directory.content object2: the other object linked (if object.directory.content) """ def get_object(self, cr, uid, uri, context={}): if not uri: return node_class(cr, uid, '', False, type='database') turi = tuple(uri) if False and (turi in self._cache): (path, oo, oo2, content,type,root) = self._cache[turi] if oo: object = self.pool.get(oo[0]).browse(cr, uid, oo[1], context) else: object = False if oo2: object2 = self.pool.get(oo2[0]).browse(cr, uid, oo2[1], context) else: object2 = False node = node_class(cr, uid, path, object,object2, context, content, type, root) return node node = node_class(cr, uid, '/', False, type='database') for path in uri[:]: if path: node = node.child(path) if not node: return False oo = node.object and (node.object._name, node.object.id) or False oo2 = node.object2 and (node.object2._name, node.object2.id) or False self._cache[turi] = (node.path, oo, oo2, node.content,node.type,node.root) return node def get_childs(self, cr, uid, uri, context={}): node = self.get_object(cr, uid, uri, context) if uri: children = node.children() else: children= [node] result = map(lambda node: node.path_get(), children) #childs,object2 = self._get_childs(cr, uid, object, False, context) #result = map(lambda x: urlparse.urljoin(path+'/',x.name), childs) return result def copy(self, cr, uid, id, default=None, context=None): if not default: default ={} name = self.read(cr, uid, [id])[0]['name'] default.update({'name': name+ " (copy)"}) return super(document_directory,self).copy(cr,uid,id,default,context) def _check_duplication(self, cr, uid,vals,ids=[],op='create'): name=vals.get('name',False) parent_id=vals.get('parent_id',False) ressource_parent_type_id=vals.get('ressource_parent_type_id',False) ressource_id=vals.get('ressource_id',0) if op=='write': for directory in self.browse(cr,uid,ids): if not name: name=directory.name if not parent_id: parent_id=directory.parent_id and directory.parent_id.id or False if not ressource_parent_type_id: ressource_parent_type_id=directory.ressource_parent_type_id and directory.ressource_parent_type_id.id or False if not ressource_id: ressource_id=directory.ressource_id and directory.ressource_id or 0 res=self.search(cr,uid,[('id','<>',directory.id),('name','=',name),('parent_id','=',parent_id),('ressource_parent_type_id','=',ressource_parent_type_id),('ressource_id','=',ressource_id)]) if len(res): return False if op=='create': res=self.search(cr,uid,[('name','=',name),('parent_id','=',parent_id),('ressource_parent_type_id','=',ressource_parent_type_id),('ressource_id','=',ressource_id)]) if len(res): return False return True def write(self, cr, uid, ids, vals, context=None): if not self._check_duplication(cr,uid,vals,ids,op='write'): raise osv.except_osv('ValidateError', _('Directory name must be unique!')) return super(document_directory,self).write(cr,uid,ids,vals,context=context) def create(self, cr, uid, vals, context=None): if not self._check_duplication(cr,uid,vals): raise osv.except_osv('ValidateError', _('Directory name must be unique!')) if vals.get('name',False) and (vals.get('name').find('/')+1 or vals.get('name').find('@')+1 or vals.get('name').find('$')+1 or vals.get('name').find('#')+1) : raise osv.except_osv('ValidateError', _('Directory name contains special characters!')) return super(document_directory,self).create(cr, uid, vals, context) document_directory() class document_directory_node(osv.osv): _inherit = 'process.node' _columns = { 'directory_id': fields.many2one('document.directory', 'Document directory', ondelete="set null"), } document_directory_node() class document_directory_content_type(osv.osv): _name = 'document.directory.content.type' _description = 'Directory Content Type' _columns = { 'name': fields.char('Content Type', size=64, required=True), 'code': fields.char('Extension', size=4), 'active': fields.boolean('Active'), } _defaults = { 'active': lambda *args: 1 } document_directory_content_type() class document_directory_content(osv.osv): _name = 'document.directory.content' _description = 'Directory Content' _order = "sequence" def _extension_get(self, cr, uid, context={}): cr.execute('select code,name from document_directory_content_type where active') res = cr.fetchall() return res _columns = { 'name': fields.char('Content Name', size=64, required=True), 'sequence': fields.integer('Sequence', size=16), 'suffix': fields.char('Suffix', size=16), 'report_id': fields.many2one('ir.actions.report.xml', 'Report'), 'extension': fields.selection(_extension_get, 'Document Type', required=True, size=4), 'include_name': fields.boolean('Include Record Name', help="Check this field if you want that the name of the file start by the record name."), 'directory_id': fields.many2one('document.directory', 'Directory'), } _defaults = { 'extension': lambda *args: '.pdf', 'sequence': lambda *args: 1, 'include_name': lambda *args: 1, } def process_write_pdf(self, cr, uid, node, context={}): return True def process_read_pdf(self, cr, uid, node, context={}): report = self.pool.get('ir.actions.report.xml').browse(cr, uid, node.content.report_id.id) srv = netsvc.LocalService('report.'+report.report_name) pdf,pdftype = srv.create(cr, uid, [node.object.id], {}, {}) s = StringIO.StringIO(pdf) s.name = node return s document_directory_content() class ir_action_report_xml(osv.osv): _name="ir.actions.report.xml" _inherit ="ir.actions.report.xml" def _model_get(self, cr, uid, ids, name, arg, context): res = {} model_pool = self.pool.get('ir.model') for data in self.read(cr,uid,ids,['model']): model = data.get('model',False) if model: model_id =model_pool.search(cr,uid,[('model','=',model)]) if model_id: res[data.get('id')] = model_id[0] else: res[data.get('id')] = False return res def _model_search(self, cr, uid, obj, name, args): if not len(args): return [] model_id= args[0][2] if not model_id: return [] model = self.pool.get('ir.model').read(cr,uid,[model_id])[0]['model'] report_id = self.search(cr,uid,[('model','=',model)]) if not report_id: return [('id','=','0')] return [('id','in',report_id)] _columns={ 'model_id' : fields.function(_model_get,fnct_search=_model_search,method=True,string='Model Id'), } ir_action_report_xml() def create_directory(path): dir_name = random_name() path = os.path.join(path,dir_name) os.makedirs(path) return dir_name class document_file(osv.osv): _inherit = 'ir.attachment' def _get_filestore(self, cr): return os.path.join(tools.config['root_path'], 'filestore', cr.dbname) def _data_get(self, cr, uid, ids, name, arg, context): result = {} cr.execute('select id,store_fname,link from ir_attachment where id in ('+','.join(map(str,ids))+')') for id,r,l in cr.fetchall(): try: value = file(os.path.join(self._get_filestore(cr), r), 'rb').read() result[id] = base64.encodestring(value) except: result[id]='' if context.get('bin_size', False): result[id] = tools.human_size(len(result[id])) return result # # This code can be improved # def _data_set(self, cr, obj, id, name, value, uid=None, context={}): if not value: return True #if (not context) or context.get('store_method','fs')=='fs': path = self._get_filestore(cr) if not os.path.isdir(path): os.makedirs(path) flag = None # This can be improved for dirs in os.listdir(path): if os.path.isdir(os.path.join(path,dirs)) and len(os.listdir(os.path.join(path,dirs)))<4000: flag = dirs break flag = flag or create_directory(path) filename = random_name() fname = os.path.join(path, flag, filename) fp = file(fname,'wb') v = base64.decodestring(value) fp.write(v) filesize = os.stat(fname).st_size cr.execute('update ir_attachment set store_fname=%s,store_method=%s,file_size=%s where id=%s', (os.path.join(flag,filename),'fs',len(v),id)) return True _columns = { 'user_id': fields.many2one('res.users', 'Owner', select=1), 'group_ids': fields.many2many('res.groups', 'document_directory_group_rel', 'item_id', 'group_id', 'Groups'), 'parent_id': fields.many2one('document.directory', 'Directory', select=1), 'file_size': fields.integer('File Size', required=True), 'file_type': fields.char('Content Type', size=32), 'index_content': fields.text('Indexed Content'), 'write_date': fields.datetime('Date Modified', readonly=True), 'write_uid': fields.many2one('res.users', 'Last Modification User', readonly=True), 'create_date': fields.datetime('Date Created', readonly=True), 'create_uid': fields.many2one('res.users', 'Creator', readonly=True), 'store_method': fields.selection([('db','Database'),('fs','Filesystem'),('link','Link')], "Storing Method"), 'datas': fields.function(_data_get,method=True,fnct_inv=_data_set,string='File Content',type="binary"), 'store_fname': fields.char('Stored Filename', size=200), 'res_model': fields.char('Attached Model', size=64), #res_model 'res_id': fields.integer('Attached ID'), #res_id 'partner_id':fields.many2one('res.partner', 'Partner', select=1), 'title': fields.char('Resource Title',size=64), } _defaults = { 'user_id': lambda self,cr,uid,ctx:uid, 'file_size': lambda self,cr,uid,ctx:0, 'store_method': lambda *args: 'db' } _sql_constraints = [ ('filename_uniq', 'unique (name,parent_id,res_id,res_model)', 'The file name must be unique !') ] def _check_duplication(self, cr, uid,vals,ids=[],op='create'): name=vals.get('name',False) parent_id=vals.get('parent_id',False) res_model=vals.get('res_model',False) res_id=vals.get('res_id',0) if op=='write': for file in self.browse(cr,uid,ids): if not name: name=file.name if not parent_id: parent_id=file.parent_id and file.parent_id.id or False if not res_model: res_model=file.res_model and file.res_model or False if not res_id: res_id=file.res_id and file.res_id or 0 res=self.search(cr,uid,[('id','<>',file.id),('name','=',name),('parent_id','=',parent_id),('res_model','=',res_model),('res_id','=',res_id)]) if len(res): return False if op=='create': res=self.search(cr,uid,[('name','=',name),('parent_id','=',parent_id),('res_id','=',res_id),('res_model','=',res_model)]) if len(res): return False return True def copy(self, cr, uid, id, default=None, context=None): if not default: default ={} name = self.read(cr, uid, [id])[0]['name'] default.update({'name': name+ " (copy)"}) return super(document_file,self).copy(cr,uid,id,default,context) def write(self, cr, uid, ids, vals, context=None): res=self.search(cr,uid,[('id','in',ids)]) if not len(res): return False if not self._check_duplication(cr,uid,vals,ids,'write'): raise except_orm('ValidateError', 'File name must be unique!') result = super(document_file,self).write(cr,uid,ids,vals,context=context) cr.commit() try: for f in self.browse(cr, uid, ids, context=context): #if 'datas' not in vals: # vals['datas']=f.datas res = content_index(base64.decodestring(vals['datas']), f.datas_fname, f.file_type or None) super(document_file,self).write(cr, uid, ids, { 'index_content': res }) cr.commit() except: pass return result def create(self, cr, uid, vals, context={}): vals['title']=vals['name'] vals['parent_id'] = context.get('parent_id',False) if not vals.get('res_id', False) and context.get('default_res_id',False): vals['res_id']=context.get('default_res_id',False) if not vals.get('res_model', False) and context.get('default_res_model',False): vals['res_model']=context.get('default_res_model',False) if vals.get('res_id', False) and vals.get('res_model',False): obj_model=self.pool.get(vals['res_model']) result = obj_model.read(cr, uid, [vals['res_id']], context=context) if len(result): obj=result[0] vals['title'] = (obj['name'] or '')[:60] if obj_model._name=='res.partner': vals['partner_id']=obj['id'] elif obj.get('address_id',False): if isinstance(obj['address_id'],tuple) or isinstance(obj['address_id'],list): address_id=obj['address_id'][0] else: address_id=obj['address_id'] address=self.pool.get('res.partner.address').read(cr,uid,[address_id],context=context) if len(address): vals['partner_id']=address[0]['partner_id'][0] or False elif obj.get('partner_id',False): if isinstance(obj['partner_id'],tuple) or isinstance(obj['partner_id'],list): vals['partner_id']=obj['partner_id'][0] else: vals['partner_id']=obj['partner_id'] datas=None if vals.get('link',False) : import urllib datas=base64.encodestring(urllib.urlopen(vals['link']).read()) else: datas=vals.get('datas',False) vals['file_size']= len(datas) if not self._check_duplication(cr,uid,vals): raise except_orm('ValidateError', 'File name must be unique!') result = super(document_file,self).create(cr, uid, vals, context) cr.commit() try: res = content_index(base64.decodestring(datas), vals['datas_fname'], vals.get('content_type', None)) super(document_file,self).write(cr, uid, [result], { 'index_content': res, }) cr.commit() except: pass return result def unlink(self,cr, uid, ids, context={}): for f in self.browse(cr, uid, ids, context): #if f.store_method=='fs': try: os.unlink(os.path.join(self._get_filestore(cr), f.store_fname)) except: pass return super(document_file, self).unlink(cr, uid, ids, context) document_file() class document_configuration_wizard(osv.osv_memory): _name='document.configuration.wizard' _rec_name = 'Auto Directory configuration' _columns = { 'host': fields.char('Server Address', size=64, help="Put here the server address or IP. " \ "Keep localhost if you don't know what to write.", required=True) } _defaults = { 'host': lambda *args: 'localhost' } def action_cancel(self,cr,uid,ids,conect=None): return { 'view_type': 'form', "view_mode": 'form', 'res_model': 'ir.actions.configuration.wizard', 'type': 'ir.actions.act_window', 'target':'new', } def action_config(self, cr, uid, ids, context=None): conf = self.browse(cr, uid, ids[0], context) obj=self.pool.get('document.directory') objid=self.pool.get('ir.model.data') if self.pool.get('sale.order'): id = objid._get_id(cr, uid, 'document', 'dir_sale_order_all') id = objid.browse(cr, uid, id, context=context).res_id mid = self.pool.get('ir.model').search(cr, uid, [('model','=','sale.order')]) obj.write(cr, uid, [id], { 'type':'ressource', 'ressource_type_id': mid[0], 'domain': '[]', }) aid = objid._get_id(cr, uid, 'sale', 'report_sale_order') aid = objid.browse(cr, uid, aid, context=context).res_id self.pool.get('document.directory.content').create(cr, uid, { 'name': "Print Order", 'suffix': "_print", 'report_id': aid, 'extension': '.pdf', 'include_name': 1, 'directory_id': id, }) id = objid._get_id(cr, uid, 'document', 'dir_sale_order_quote') id = objid.browse(cr, uid, id, context=context).res_id obj.write(cr, uid, [id], { 'type':'ressource', 'ressource_type_id': mid[0], 'domain': "[('state','=','draft')]", }) if self.pool.get('product.product'): id = objid._get_id(cr, uid, 'document', 'dir_product') id = objid.browse(cr, uid, id, context=context).res_id mid = self.pool.get('ir.model').search(cr, uid, [('model','=','product.product')]) obj.write(cr, uid, [id], { 'type':'ressource', 'ressource_type_id': mid[0], }) if self.pool.get('stock.location'): aid = objid._get_id(cr, uid, 'stock', 'report_product_history') aid = objid.browse(cr, uid, aid, context=context).res_id self.pool.get('document.directory.content').create(cr, uid, { 'name': "Product Stock", 'suffix': "_stock_forecast", 'report_id': aid, 'extension': '.pdf', 'include_name': 1, 'directory_id': id, }) if self.pool.get('account.analytic.account'): id = objid._get_id(cr, uid, 'document', 'dir_project') id = objid.browse(cr, uid, id, context=context).res_id mid = self.pool.get('ir.model').search(cr, uid, [('model','=','account.analytic.account')]) obj.write(cr, uid, [id], { 'type':'ressource', 'ressource_type_id': mid[0], 'domain': '[]', 'ressource_tree': 1 }) aid = objid._get_id(cr, uid, 'document', 'action_document_browse') aid = objid.browse(cr, uid, aid, context=context).res_id self.pool.get('ir.actions.url').write(cr, uid, [aid], {'url': 'ftp://'+(conf.host or 'localhost')+':8021/'}) return { 'view_type': 'form', "view_mode": 'form', 'res_model': 'ir.actions.configuration.wizard', 'type': 'ir.actions.act_window', 'target':'new', } document_configuration_wizard()