1 # -*- encoding: utf-8 -*-
2 ##############################################################################
4 # OpenERP, Open Source Management Solution
5 # Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program. If not, see <http://www.gnu.org/licenses/>.
21 ##############################################################################
25 from osv import osv, fields
26 from osv.orm import except_orm
32 from content_index import content_index
36 # Unsupported WebDAV Commands:
45 # An object that represent an uri
46 # path: the uri of the object
47 # content: the Content it belongs to (_print.pdf)
48 # type: content or collection
49 # content: objct = res.partner
50 # collection: object = directory, object2 = res.partner
51 # file: objct = ir.attachement
52 # root: if we are at the first directory of a ressource
54 INVALID_CHARS={'*':str(hash('*')), '|':str(hash('|')) , "\\":str(hash("\\")), '/':'__', ':':str(hash(':')), '"':str(hash('"')), '<':str(hash('<')) , '>':str(hash('>')) , '?':str(hash('?'))}
55 class node_class(object):
56 def __init__(self, cr, uid, path,object,object2=False, context={}, content=False, type='collection', root=False):
61 self.object2 = object2
62 self.context = context
63 self.content = content
67 def _file_get(self, nodename=False):
70 pool = pooler.get_pool(self.cr.dbname)
71 fobj = pool.get('ir.attachment')
75 where.append( ('res_model','=',self.object2._name) )
76 where.append( ('res_id','=',self.object2.id) )
77 for content in self.object.content_ids:
78 if self.object2 or not content.include_name:
79 if content.include_name:
80 test_nodename = self.object2.name + (content.suffix or '') + (content.extension or '')
82 test_nodename = (content.suffix or '') + (content.extension or '')
83 if test_nodename.find('/'):
84 test_nodename=test_nodename.replace('/', '_')
85 path = self.path+'/'+test_nodename
86 #path = self.path+'/'+self.object2.name + (content.suffix or '') + (content.extension or '')
88 n = node_class(self.cr, self.uid,path, self.object2, False, content=content, type='content', root=False)
91 if nodename == test_nodename:
92 n = node_class(self.cr, self.uid, path, self.object2, False, content=content, type='content', root=False)
95 where.append( ('parent_id','=',self.object.id) )
96 where.append( ('res_id','=',False) )
98 where.append( (fobj._rec_name,'=',nodename) )
99 ids = fobj.search(self.cr, self.uid, where+[ ('parent_id','=',self.object and self.object.id or False) ], context=self.context)
100 if self.object and self.root and (self.object.type=='ressource'):
101 ids += fobj.search(self.cr, self.uid, where+[ ('parent_id','=',False) ], context=self.context)
102 res = fobj.browse(self.cr, self.uid, ids, context=self.context)
103 return map(lambda x: node_class(self.cr, self.uid, self.path+'/'+x.name, x, False, type='file', root=False), res) + res2
105 def directory_list_for_child(self,nodename,parent=False):
106 pool = pooler.get_pool(self.cr.dbname)
109 where.append(('name','=',nodename))
110 if (self.object and self.object.type=='directory') or not self.object2:
111 where.append(('parent_id','=',self.object and self.object.id or False))
113 where.append(('parent_id','=',False))
115 where.append(('ressource_parent_type_id','=',self.object.ressource_type_id.id))
117 where.append(('ressource_parent_type_id','=',False))
119 ids = pool.get('document.directory').search(self.cr, self.uid, where+[('ressource_id','=',0)], self.context)
121 ids += pool.get('document.directory').search(self.cr, self.uid, where+[('ressource_id','=',self.object2.id)], self.context)
122 res = pool.get('document.directory').browse(self.cr, self.uid, ids,self.context)
125 def _child_get(self, nodename=False):
126 if self.type not in ('collection','database'):
128 res = self.directory_list_for_child(nodename)
129 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)
130 if self.type=='database':
131 pool = pooler.get_pool(self.cr.dbname)
132 fobj = pool.get('ir.attachment')
133 vargs = [('parent_id','=',False),('res_id','=',False)]
135 vargs.append(('name','=',nodename))
136 file_ids=fobj.search(self.cr,self.uid,vargs)
138 res = fobj.browse(self.cr, self.uid, file_ids, context=self.context)
139 result +=map(lambda x: node_class(self.cr, self.uid, self.path+'/'+x.name, x, False, type='file', root=self.root), res)
140 if self.type=='collection' and self.object.type=="ressource":
141 where = self.object.domain and eval(self.object.domain, {'active_id':self.root}) or []
142 pool = pooler.get_pool(self.cr.dbname)
143 obj = pool.get(self.object.ressource_type_id.model)
145 if self.object.ressource_tree:
146 if obj._parent_name in obj.fields_get(self.cr,self.uid):
147 where.append((obj._parent_name,'=',self.object2 and self.object2.id or False))
155 name_for = obj._name.split('.')[-1]
156 if nodename and nodename.find(name_for) == 0 :
157 id = int(nodename.replace(name_for,''))
158 where.append(('id','=',id))
160 if nodename.find('__') :
161 nodename=nodename.replace('__','/')
162 for invalid in INVALID_CHARS:
163 if nodename.find(INVALID_CHARS[invalid]) :
164 nodename=nodename.replace(INVALID_CHARS[invalid],invalid)
165 where.append(('name','=',nodename))
166 ids = obj.search(self.cr, self.uid, where, self.context)
167 res = obj.browse(self.cr, self.uid, ids,self.context)
170 r.name = name_for+'%d'%r.id
171 for invalid in INVALID_CHARS:
172 if r.name.find(invalid) :
173 r.name=r.name.replace(invalid,INVALID_CHARS[invalid])
174 result2 = map(lambda x: node_class(self.cr, self.uid, self.path+'/'+x.name.replace('/','__'), self.object, x, root=r.id), res)
180 return self._child_get() + self._file_get()
182 def child(self, name):
183 res = self._child_get(name)
186 res = self._file_get(name)
193 if self.path[0]=='/':
197 class document_directory(osv.osv):
198 _name = 'document.directory'
199 _description = 'Document directory'
201 'name': fields.char('Name', size=64, required=True, select=1),
202 'write_date': fields.datetime('Date Modified', readonly=True),
203 'write_uid': fields.many2one('res.users', 'Last Modification User', readonly=True),
204 'create_date': fields.datetime('Date Created', readonly=True),
205 'create_uid': fields.many2one('res.users', 'Creator', readonly=True),
206 'file_type': fields.char('Content Type', size=32),
207 'domain': fields.char('Domain', size=128),
208 'user_id': fields.many2one('res.users', 'Owner'),
209 'group_ids': fields.many2many('res.groups', 'document_directory_group_rel', 'item_id', 'group_id', 'Groups'),
210 'parent_id': fields.many2one('document.directory', 'Parent Item'),
211 'child_ids': fields.one2many('document.directory', 'parent_id', 'Childs'),
212 'file_ids': fields.one2many('ir.attachment', 'parent_id', 'Files'),
213 'content_ids': fields.one2many('document.directory.content', 'directory_id', 'Virtual Files'),
214 'type': fields.selection([('directory','Static Directory'),('ressource','Other Ressources')], 'Type', required=True),
215 'ressource_type_id': fields.many2one('ir.model', 'Childs Model'),
216 'ressource_parent_type_id': fields.many2one('ir.model', 'Linked Model'),
217 'ressource_id': fields.integer('Ressource ID'),
218 'ressource_tree': fields.boolean('Tree Structure'),
221 'user_id': lambda self,cr,uid,ctx: uid,
222 'domain': lambda self,cr,uid,ctx: '[]',
223 'type': lambda *args: 'directory',
224 'ressource_id': lambda *a: 0
227 ('dirname_uniq', 'unique (name,parent_id,ressource_id,ressource_parent_type_id)', 'The directory name must be unique !')
230 def get_resource_path(self,cr,uid,dir_id,res_model,res_id):
231 # this method will be used in process module
232 # to be need test and Improvement if resource dir has parent resource (link resource)
234 def _parent(dir_id,path):
235 parent=self.browse(cr,uid,dir_id)
236 if parent.parent_id and not parent.ressource_parent_type_id:
237 _parent(parent.parent_id.id,path)
238 path.append(parent.name)
240 path.append(parent.name)
243 directory=self.browse(cr,uid,dir_id)
244 model_ids=self.pool.get('ir.model').search(cr,uid,[('model','=',res_model)])
247 path.append(self.pool.get(directory.ressource_type_id.model).browse(cr,uid,res_id).name)
248 user=self.pool.get('res.users').browse(cr,uid,uid)
249 return "ftp://%s:%s@localhost:8021/%s/%s"%(user.login,user.password,cr.dbname,'/'.join(path))
251 def _check_recursion(self, cr, uid, ids):
254 cr.execute('select distinct parent_id from document_directory where id in ('+','.join(map(str,ids))+')')
255 ids = filter(None, map(lambda x:x[0], cr.fetchall()))
262 (_check_recursion, 'Error! You can not create recursive Directories.', ['parent_id'])
264 def __init__(self, *args, **kwargs):
265 res = super(document_directory, self).__init__(*args, **kwargs)
269 def onchange_content_id(self, cr, uid, ids, ressource_type_id):
272 def _get_childs(self, cr, uid, node, nodename=False, context={}):
275 where.append(('name','=',nodename))
277 where.append(('parent_id','=',object.id))
278 ids = self.search(cr, uid, where, context)
279 return self.browse(cr, uid, ids, context), False
283 uri: of the form "Sales Order/SO001"
286 object: the object.directory or object.directory.content
287 object2: the other object linked (if object.directory.content)
289 def get_object(self, cr, uid, uri, context={}):
291 return node_class(cr, uid, '', False, type='database')
293 if False and (turi in self._cache):
294 (path, oo, oo2, content,type,root) = self._cache[turi]
296 object = self.pool.get(oo[0]).browse(cr, uid, oo[1], context)
300 object2 = self.pool.get(oo2[0]).browse(cr, uid, oo2[1], context)
303 node = node_class(cr, uid, path, object,object2, context, content, type, root)
306 node = node_class(cr, uid, '/', False, type='database')
309 node = node.child(path)
312 oo = node.object and (node.object._name, node.object.id) or False
313 oo2 = node.object2 and (node.object2._name, node.object2.id) or False
314 self._cache[turi] = (node.path, oo, oo2, node.content,node.type,node.root)
317 def get_childs(self, cr, uid, uri, context={}):
318 node = self.get_object(cr, uid, uri, context)
320 children = node.children()
323 result = map(lambda node: node.path_get(), children)
324 #childs,object2 = self._get_childs(cr, uid, object, False, context)
325 #result = map(lambda x: urlparse.urljoin(path+'/',x.name), childs)
328 def write(self, cr, uid, ids, vals, context=None):
329 # need to make constraints to checking duplicate
330 #if not self._check_duplication(cr,uid,vals):
331 # raise except_orm('ValidateError', 'Directory name must be unique!')
334 def copy(self, cr, uid, id, default=None, context=None):
337 name = self.read(cr, uid, [id])[0]['name']
338 default.update({'name': name+ " (copy)"})
339 return super(document_directory,self).copy(cr,uid,id,default,context)
341 def _check_duplication(self, cr, uid,vals,ids=[],op='create'):
342 name=vals.get('name',False)
343 parent_id=vals.get('parent_id',False)
344 ressource_parent_type_id=vals.get('ressource_parent_type_id',False)
345 ressource_id=vals.get('ressource_id',0)
347 for directory in self.browse(cr,uid,ids):
351 parent_id=directory.parent_id and directory.parent_id.id or False
352 if not ressource_parent_type_id:
353 ressource_parent_type_id=directory.ressource_parent_type_id and directory.ressource_parent_type_id.id or False
355 ressource_id=directory.ressource_id and directory.ressource_id.id or 0
356 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)])
360 res=self.search(cr,uid,[('name','=',name),('parent_id','=',parent_id),('ressource_parent_type_id','=',ressource_parent_type_id),('ressource_id','=',ressource_id)])
364 def write(self, cr, uid, ids, vals, context=None):
365 if not self._check_duplication(cr,uid,vals,ids,op='write'):
366 raise except_orm('ValidateError', 'Directory name must be unique!')
367 return super(document_directory,self).write(cr,uid,ids,vals,context=context)
369 def create(self, cr, uid, vals, context=None):
370 if not self._check_duplication(cr,uid,vals):
371 raise except_orm('ValidateError', 'Directory name must be unique!')
372 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) :
374 return super(document_directory,self).create(cr, uid, vals, context)
378 class document_directory_node(osv.osv):
379 _inherit = 'process.node'
381 'directory_id': fields.many2one('document.directory', 'Document directory', ondelete="set null"),
383 document_directory_node()
385 class document_directory_content_type(osv.osv):
386 _name = 'document.directory.content.type'
387 _description = 'Directory Content Type'
389 'name': fields.char('Content Type', size=64, required=True),
390 'code': fields.char('Extension', size=4),
391 'active': fields.boolean('Active'),
394 'active': lambda *args: 1
396 document_directory_content_type()
398 class document_directory_content(osv.osv):
399 _name = 'document.directory.content'
400 _description = 'Directory Content'
402 def _extension_get(self, cr, uid, context={}):
403 cr.execute('select code,name from document_directory_content_type where active')
407 'name': fields.char('Content Name', size=64, required=True),
408 'sequence': fields.integer('Sequence', size=16),
409 'suffix': fields.char('Suffix', size=16),
410 'report_id': fields.many2one('ir.actions.report.xml', 'Report'),
411 'extension': fields.selection(_extension_get, 'Document Type', required=True, size=4),
412 'include_name': fields.boolean('Include Record Name', help="Check if you cant that the name of the file start by the record name."),
413 'directory_id': fields.many2one('document.directory', 'Directory'),
416 'extension': lambda *args: '.pdf',
417 'sequence': lambda *args: 1,
418 'include_name': lambda *args: 1,
420 def process_write_pdf(self, cr, uid, node, context={}):
422 def process_read_pdf(self, cr, uid, node, context={}):
423 report = self.pool.get('ir.actions.report.xml').browse(cr, uid, node.content.report_id.id)
424 srv = netsvc.LocalService('report.'+report.report_name)
425 pdf,pdftype = srv.create(cr, uid, [node.object.id], {}, {})
426 s = StringIO.StringIO(pdf)
429 document_directory_content()
431 class ir_action_report_xml(osv.osv):
432 _name="ir.actions.report.xml"
433 _inherit ="ir.actions.report.xml"
435 def _model_get(self, cr, uid, ids, name, arg, context):
437 model_pool = self.pool.get('ir.model')
438 for data in self.read(cr,uid,ids,['model']):
439 model = data.get('model',False)
441 model_id =model_pool.search(cr,uid,[('model','=',model)])
443 res[data.get('id')] = model_id[0]
445 res[data.get('id')] = False
448 def _model_search(self, cr, uid, obj, name, args):
454 model = self.pool.get('ir.model').read(cr,uid,[model_id])[0]['model']
455 report_id = self.search(cr,uid,[('model','=',model)])
457 return [('id','=','0')]
458 return [('id','in',report_id)]
461 'model_id' : fields.function(_model_get,fnct_search=_model_search,method=True,string='Model Id'),
464 ir_action_report_xml()
473 d = [random.choice(string.letters) for x in xrange(10) ]
478 def create_directory(path):
479 dir_name = random_name()
480 path = os.path.join(path,dir_name)
484 class document_file(osv.osv):
485 _inherit = 'ir.attachment'
486 def _data_get(self, cr, uid, ids, name, arg, context):
488 cr.execute('select id,store_method,datas,store_fname,link from ir_attachment where id in ('+','.join(map(str,ids))+')')
489 for id,m,d,r,l in cr.fetchall():
494 path = os.path.join(os.getcwd(), 'filestore', cr.dbname)
495 value = file(os.path.join(path,r), 'rb').read()
496 result[id] = base64.encodestring(value)
504 # This code can be improved
506 def _data_set(self, cr, obj, id, name, value, uid=None, context={}):
509 if (not context) or context.get('store_method','fs')=='fs':
510 path = os.path.join(os.getcwd(), "filestore", cr.dbname)
511 if not os.path.isdir(path):
514 # This can be improved
515 for dirs in os.listdir(path):
516 if os.path.isdir(os.path.join(path,dirs)) and len(os.listdir(os.path.join(path,dirs)))<4000:
519 flag = flag or create_directory(path)
520 filename = random_name()
521 fname = os.path.join(path, flag, filename)
522 fp = file(fname,'wb')
523 v = base64.decodestring(value)
525 filesize = os.stat(fname).st_size
526 cr.execute('update ir_attachment set store_fname=%s,store_method=%s,file_size=%d where id=%d', (os.path.join(flag,filename),'fs',len(v),id))
528 cr.execute('update ir_attachment set datas=%s,store_method=%s where id=%d', (psycopg.Binary(value),'db',id))
532 'user_id': fields.many2one('res.users', 'Owner', select=1),
533 'group_ids': fields.many2many('res.groups', 'document_directory_group_rel', 'item_id', 'group_id', 'Groups'),
534 'parent_id': fields.many2one('document.directory', 'Directory', select=1),
535 'file_size': fields.integer('File Size', required=True),
536 'file_type': fields.char('Content Type', size=32),
537 'index_content': fields.text('Indexed Content'),
538 'write_date': fields.datetime('Date Modified', readonly=True),
539 'write_uid': fields.many2one('res.users', 'Last Modification User', readonly=True),
540 'create_date': fields.datetime('Date Created', readonly=True),
541 'create_uid': fields.many2one('res.users', 'Creator', readonly=True),
542 'store_method': fields.selection([('db','Database'),('fs','Filesystem'),('link','Link')], "Storing Method"),
543 'datas': fields.function(_data_get,method=True,store=True,fnct_inv=_data_set,string='File Content',type="binary"),
544 'store_fname': fields.char('Stored Filename', size=200),
545 'res_model': fields.char('Attached Model', size=64), #res_model
546 'res_id': fields.integer('Attached ID'), #res_id
547 'partner_id':fields.many2one('res.partner', 'Partner', select=1),
548 'title': fields.char('Resource Title',size=64),
552 'user_id': lambda self,cr,uid,ctx:uid,
553 'file_size': lambda self,cr,uid,ctx:0,
554 'store_method': lambda *args: 'db'
557 ('filename_uniq', 'unique (name,parent_id,res_id,res_model)', 'The file name must be unique !')
559 def _check_duplication(self, cr, uid,vals,ids=[],op='create'):
560 name=vals.get('name',False)
561 parent_id=vals.get('parent_id',False)
562 res_model=vals.get('res_model',False)
563 res_id=vals.get('res_id',0)
565 for file in self.browse(cr,uid,ids):
569 parent_id=file.parent_id and file.parent_id.id or False
571 res_model=file.res_model and file.res_model or False
573 res_id=file.res_id and file.res_id or 0
574 res=self.search(cr,uid,[('id','<>',file.id),('name','=',name),('parent_id','=',parent_id),('res_model','=',res_model),('res_id','=',res_id)])
578 res=self.search(cr,uid,[('name','=',name),('parent_id','=',parent_id),('res_id','=',res_id),('res_model','=',res_model)])
582 def copy(self, cr, uid, id, default=None, context=None):
585 name = self.read(cr, uid, [id])[0]['name']
586 default.update({'name': name+ " (copy)"})
587 return super(document_file,self).copy(cr,uid,id,default,context)
588 def write(self, cr, uid, ids, vals, context=None):
589 if not self._check_duplication(cr,uid,vals,ids,'write'):
590 raise except_orm('ValidateError', 'File name must be unique!')
591 result = super(document_file,self).write(cr,uid,ids,vals,context=context)
594 for f in self.browse(cr, uid, ids, context=context):
595 if 'datas' not in vals:
596 vals['datas']=f.datas
597 res = content_index(base64.decodestring(vals['datas']), f.datas_fname, f.file_type or None)
598 super(document_file,self).write(cr, uid, ids, {
606 def create(self, cr, uid, vals, context={}):
607 vals['title']=vals['name']
608 if not vals.get('res_id', False) and context.get('default_res_id',False):
609 vals['res_id']=context.get('default_res_id',False)
610 if not vals.get('res_model', False) and context.get('default_res_model',False):
611 vals['res_model']=context.get('default_res_model',False)
612 if vals.get('res_id', False) and vals.get('res_model',False):
613 obj_model=self.pool.get(vals['res_model'])
614 result = obj_model.read(cr, uid, [vals['res_id']], context=context)
617 vals['title'] = (obj['name'] or '')[:60]
618 if obj_model._name=='res.partner':
619 vals['partner_id']=obj['id']
620 elif obj.get('address_id',False):
621 if isinstance(obj['address_id'],tuple) or isinstance(obj['address_id'],list):
622 address_id=obj['address_id'][0]
624 address_id=obj['address_id']
625 address=self.pool.get('res.partner.address').read(cr,uid,[address_id],context=context)
627 vals['partner_id']=address[0]['partner_id'][0] or False
628 elif obj.get('partner_id',False):
629 if isinstance(obj['partner_id'],tuple) or isinstance(obj['partner_id'],list):
630 vals['partner_id']=obj['partner_id'][0]
632 vals['partner_id']=obj['partner_id']
635 if vals.get('datas',False) and vals.get('link',False) :
637 datas=base64.encodestring(urllib.urlopen(vals['link']).read())
640 vals['file_size']= len(datas)
641 if not self._check_duplication(cr,uid,vals):
642 raise except_orm('ValidateError', 'File name must be unique!')
643 result = super(document_file,self).create(cr, uid, vals, context)
646 res = content_index(base64.decodestring(datas), vals['datas_fname'], vals.get('content_type', None))
647 super(document_file,self).write(cr, uid, [result], {
648 'index_content': res,
655 def unlink(self,cr, uid, ids, context={}):
656 for f in self.browse(cr, uid, ids, context):
657 if f.store_method=='fs':
659 path = os.path.join(os.getcwd(), cr.dbname, 'filestore',f.store_fname)
663 return super(document_file, self).unlink(cr, uid, ids, context)
666 class document_configuration_wizard(osv.osv_memory):
667 _name='document.configuration.wizard'
668 _rec_name = 'Auto Directory configuration'
670 'host': fields.char('Server Address', size=64, help="Put here the server address or IP. " \
671 "Keep localhost if you don't know what to write.", required=True)
674 'host': lambda *args: 'localhost'
676 def action_cancel(self,cr,uid,ids,conect=None):
680 'res_model': 'ir.actions.configuration.wizard',
681 'type': 'ir.actions.act_window',
685 def action_config(self, cr, uid, ids, context=None):
686 conf = self.browse(cr, uid, ids[0], context)
687 obj=self.pool.get('document.directory')
688 objid=self.pool.get('ir.model.data')
690 if self.pool.get('sale.order'):
691 id = objid._get_id(cr, uid, 'document', 'dir_sale_order_all')
692 id = objid.browse(cr, uid, id, context=context).res_id
693 mid = self.pool.get('ir.model').search(cr, uid, [('model','=','sale.order')])
694 obj.write(cr, uid, [id], {
696 'ressource_type_id': mid[0],
699 aid = objid._get_id(cr, uid, 'sale', 'report_sale_order')
700 aid = objid.browse(cr, uid, aid, context=context).res_id
702 self.pool.get('document.directory.content').create(cr, uid, {
703 'name': "Print Order",
710 id = objid._get_id(cr, uid, 'document', 'dir_sale_order_quote')
711 id = objid.browse(cr, uid, id, context=context).res_id
712 obj.write(cr, uid, [id], {
714 'ressource_type_id': mid[0],
715 'domain': "[('state','=','draft')]",
718 if self.pool.get('product.product'):
719 id = objid._get_id(cr, uid, 'document', 'dir_product')
720 id = objid.browse(cr, uid, id, context=context).res_id
721 mid = self.pool.get('ir.model').search(cr, uid, [('model','=','product.product')])
722 obj.write(cr, uid, [id], {
724 'ressource_type_id': mid[0],
727 if self.pool.get('stock.location'):
728 aid = objid._get_id(cr, uid, 'stock', 'report_product_history')
729 aid = objid.browse(cr, uid, aid, context=context).res_id
731 self.pool.get('document.directory.content').create(cr, uid, {
732 'name': "Product Stock",
733 'suffix': "_stock_forecast",
740 if self.pool.get('account.analytic.account'):
741 id = objid._get_id(cr, uid, 'document', 'dir_project')
742 id = objid.browse(cr, uid, id, context=context).res_id
743 mid = self.pool.get('ir.model').search(cr, uid, [('model','=','account.analytic.account')])
744 obj.write(cr, uid, [id], {
746 'ressource_type_id': mid[0],
751 aid = objid._get_id(cr, uid, 'document', 'action_document_browse')
752 aid = objid.browse(cr, uid, aid, context=context).res_id
753 self.pool.get('ir.actions.url').write(cr, uid, [aid], {'url': 'ftp://'+(conf.host or 'localhost')+':8021/'})
758 'res_model': 'ir.actions.configuration.wizard',
759 'type': 'ir.actions.act_window',
762 document_configuration_wizard()