improve
[odoo/odoo.git] / addons / document / document.py
1 # -*- encoding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution   
5 #    Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
6 #    $Id$
7 #
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.
12 #
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.
17 #
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/>.
20 #
21 ##############################################################################
22
23 import base64
24
25 from osv import osv, fields
26 from osv.orm import except_orm
27 import urlparse
28
29 import os
30
31 import pooler
32 from content_index import content_index
33 import netsvc
34 import StringIO
35
36 # Unsupported WebDAV Commands:
37 #     label
38 #     search
39 #     checkin
40 #     checkout
41 #     propget
42 #     propset
43
44 #
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
53 #
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):
57         self.cr = cr
58         self.uid = uid
59         self.path = path
60         self.object = object
61         self.object2 = object2
62         self.context = context
63         self.content = content
64         self.type=type
65         self.root=root
66
67     def _file_get(self, nodename=False):
68         if not self.object:
69             return []
70         pool = pooler.get_pool(self.cr.dbname)
71         fobj = pool.get('ir.attachment')
72         res2 = []
73         where = []
74         if self.object2:
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 '')
81                 else:
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 '')
87                 if not nodename:
88                     n = node_class(self.cr, self.uid,path, self.object2, False, content=content, type='content', root=False)
89                     res2.append( n)
90                 else:
91                     if nodename == test_nodename:
92                         n = node_class(self.cr, self.uid, path, self.object2, False, content=content, type='content', root=False)
93                         res2.append(n)
94         else:
95             where.append( ('parent_id','=',self.object.id) )
96             where.append( ('res_id','=',False) )
97         if nodename:
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
104
105     def directory_list_for_child(self,nodename,parent=False):
106         pool = pooler.get_pool(self.cr.dbname)
107         where = []
108         if nodename:
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))
112         else:
113             where.append(('parent_id','=',False))
114         if self.object:
115             where.append(('ressource_parent_type_id','=',self.object.ressource_type_id.id))
116         else:
117             where.append(('ressource_parent_type_id','=',False))
118
119         ids = pool.get('document.directory').search(self.cr, self.uid, where+[('ressource_id','=',0)], self.context)
120         if self.object2:
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)
123         return res
124
125     def _child_get(self, nodename=False):
126         if self.type not in ('collection','database'):
127             return []
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)]
134             if nodename:
135                 vargs.append(('name','=',nodename))
136             file_ids=fobj.search(self.cr,self.uid,vargs)
137
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)
144
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))
148                 else :
149                     if self.object2:
150                         return result
151             else:
152                 if self.object2:
153                     return result
154
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))
159             elif nodename:
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)
168             for r in res:
169                 if not r.name:
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)
175             if result2:
176                 result = result2
177         return result
178
179     def children(self):
180         return self._child_get() + self._file_get()
181
182     def child(self, name):
183         res = self._child_get(name)
184         if res:
185             return res[0]
186         res = self._file_get(name)
187         if res:
188             return res[0]
189         return None
190
191     def path_get(self):
192         path = self.path
193         if self.path[0]=='/':
194             path = self.path[1:]
195         return path
196
197 class document_directory(osv.osv):
198     _name = 'document.directory'
199     _description = 'Document directory'
200     _columns = {
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'),
219     }
220     _defaults = {
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
225     }
226     _sql_constraints = [
227         ('dirname_uniq', 'unique (name,parent_id,ressource_id,ressource_parent_type_id)', 'The directory name must be unique !')
228     ]
229
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)
233         path=[]
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)
239             else:
240                 path.append(parent.name)
241                 return path
242
243         directory=self.browse(cr,uid,dir_id)
244         model_ids=self.pool.get('ir.model').search(cr,uid,[('model','=',res_model)])
245         if directory:
246             _parent(dir_id,path)
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))
250         return False
251     def _check_duplication(self, cr, uid,vals):
252         if 'name' in vals:
253             where=" name='%s'"% (vals['name'])
254             if not 'parent_id' in vals or not vals['parent_id']:
255                 where+=' and parent_id is null'
256             else:
257                 where+=' and parent_id=%d'%(vals['parent_id'])
258             if not 'ressource_parent_type_id' in vals or not vals['ressource_parent_type_id']:
259                 where+= ' and ressource_parent_type_id is null'
260             else:
261                 where+=" and ressource_parent_type_id='%s'"%(vals['ressource_parent_type_id'])
262 #            if not 'ressource_id' in vals or not vals['ressource_id']:
263 #                where+= ' and ressource_id is null'
264 #            else:
265 #                where+=" and ressource_id=%d"%(vals['ressource_id'])
266             cr.execute("select id from document_directory where" + where)
267             res = cr.fetchall()
268             if len(res):
269                 return False
270         return True
271     def _check_recursion(self, cr, uid, ids):
272         level = 100
273         while len(ids):
274             cr.execute('select distinct parent_id from document_directory where id in ('+','.join(map(str,ids))+')')
275             ids = filter(None, map(lambda x:x[0], cr.fetchall()))
276             if not level:
277                 return False
278             level -= 1
279         return True
280
281     _constraints = [
282         (_check_recursion, 'Error! You can not create recursive Directories.', ['parent_id'])
283     ]
284     def __init__(self, *args, **kwargs):
285         res = super(document_directory, self).__init__(*args, **kwargs)
286         self._cache = {}
287         return res
288
289     def onchange_content_id(self, cr, uid, ids, ressource_type_id):
290         return {}
291
292     def _get_childs(self, cr, uid, node, nodename=False, context={}):
293         where = []
294         if nodename:
295             where.append(('name','=',nodename))
296         if object:
297             where.append(('parent_id','=',object.id))
298         ids = self.search(cr, uid, where, context)
299         return self.browse(cr, uid, ids, context), False
300
301     """
302         PRE:
303             uri: of the form "Sales Order/SO001"
304         PORT:
305             uri
306             object: the object.directory or object.directory.content
307             object2: the other object linked (if object.directory.content)
308     """
309     def get_object(self, cr, uid, uri, context={}):
310         if not uri:
311             return node_class(cr, uid, '', False, type='database')
312         turi = tuple(uri)
313         if False and (turi in self._cache):
314             (path, oo, oo2, content,type,root) = self._cache[turi]
315             if oo:
316                 object = self.pool.get(oo[0]).browse(cr, uid, oo[1], context)
317             else:
318                 object = False
319             if oo2:
320                 object2 = self.pool.get(oo2[0]).browse(cr, uid, oo2[1], context)
321             else:
322                 object2 = False
323             node = node_class(cr, uid, path, object,object2, context, content, type, root)
324             return node
325
326         node = node_class(cr, uid, '/', False, type='database')
327         for path in uri[:]:
328             if path:
329                 node = node.child(path)
330                 if not node:
331                     return False
332         oo = node.object and (node.object._name, node.object.id) or False
333         oo2 = node.object2 and (node.object2._name, node.object2.id) or False
334         self._cache[turi] = (node.path, oo, oo2, node.content,node.type,node.root)
335         return node
336
337     def get_childs(self, cr, uid, uri, context={}):
338         node = self.get_object(cr, uid, uri, context)
339         if uri:
340             children = node.children()
341         else:
342             children= [node]
343         result = map(lambda node: node.path_get(), children)
344         #childs,object2 = self._get_childs(cr, uid, object, False, context)
345         #result = map(lambda x: urlparse.urljoin(path+'/',x.name), childs)
346         return result
347
348     def write(self, cr, uid, ids, vals, context=None):
349         # need to make constraints to checking duplicate
350         #if not self._check_duplication(cr,uid,vals):
351         #    raise except_orm('ValidateError', 'Directory name must be unique!')
352         return super(document_directory,self).write(cr,uid,ids,vals,context=context)
353
354     def copy(self, cr, uid, id, default=None, context=None):
355         if not default:
356             default ={}
357         name = self.read(cr, uid, [id])[0]['name']
358         default.update({'name': name+ " (copy)"})
359         return super(document_directory,self).copy(cr,uid,id,default,context)
360
361     def create(self, cr, uid, vals, context=None):
362         if not self._check_duplication(cr,uid,vals):
363             raise except_orm('ValidateError', 'Directory name must be unique!')
364         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) :
365             raise 'Error'
366         return super(document_directory,self).create(cr, uid, vals, context)
367
368 document_directory()
369
370 class document_directory_node(osv.osv):
371     _inherit = 'process.node'
372     _columns = {
373         'directory_id':  fields.many2one('document.directory', 'Document directory', ondelete="set null"),
374     }
375 document_directory_node()
376
377 class document_directory_content_type(osv.osv):
378     _name = 'document.directory.content.type'
379     _description = 'Directory Content Type'
380     _columns = {
381         'name': fields.char('Content Type', size=64, required=True),
382         'code': fields.char('Extension', size=4),
383         'active': fields.boolean('Active'),
384     }
385     _defaults = {
386         'active': lambda *args: 1
387     }
388 document_directory_content_type()
389
390 class document_directory_content(osv.osv):
391     _name = 'document.directory.content'
392     _description = 'Directory Content'
393     _order = "sequence"
394     def _extension_get(self, cr, uid, context={}):
395         cr.execute('select code,name from document_directory_content_type where active')
396         res = cr.fetchall()
397         return res
398     _columns = {
399         'name': fields.char('Content Name', size=64, required=True),
400         'sequence': fields.integer('Sequence', size=16),
401         'suffix': fields.char('Suffix', size=16),
402         'report_id': fields.many2one('ir.actions.report.xml', 'Report'),
403         'extension': fields.selection(_extension_get, 'Document Type', required=True, size=4),
404         'include_name': fields.boolean('Include Record Name', help="Check if you cant that the name of the file start by the record name."),
405         'directory_id': fields.many2one('document.directory', 'Directory'),
406     }
407     _defaults = {
408         'extension': lambda *args: '.pdf',
409         'sequence': lambda *args: 1,
410         'include_name': lambda *args: 1,
411     }
412     def process_write_pdf(self, cr, uid, node, context={}):
413         return True
414     def process_read_pdf(self, cr, uid, node, context={}):
415         report = self.pool.get('ir.actions.report.xml').browse(cr, uid, node.content.report_id.id)
416         srv = netsvc.LocalService('report.'+report.report_name)
417         pdf,pdftype = srv.create(cr, uid, [node.object.id], {}, {})
418         s = StringIO.StringIO(pdf)
419         s.name = node
420         return s
421 document_directory_content()
422
423 class ir_action_report_xml(osv.osv):
424     _name="ir.actions.report.xml"
425     _inherit ="ir.actions.report.xml"
426
427     def _model_get(self, cr, uid, ids, name, arg, context):
428         res = {}
429         model_pool = self.pool.get('ir.model')
430         for data in self.read(cr,uid,ids,['model']):
431             model = data.get('model',False)
432             if model:
433                 model_id =model_pool.search(cr,uid,[('model','=',model)])
434                 if model_id:
435                     res[data.get('id')] = model_id[0]
436                 else:
437                     res[data.get('id')] = False
438         return res
439
440     def _model_search(self, cr, uid, obj, name, args):
441         if not len(args):
442             return []
443         model_id= args[0][2]
444         if not model_id:
445             return []
446         model = self.pool.get('ir.model').read(cr,uid,[model_id])[0]['model']
447         report_id = self.search(cr,uid,[('model','=',model)])
448         if not report_id:
449             return [('id','=','0')]
450         return [('id','in',report_id)]
451
452     _columns={
453         'model_id' : fields.function(_model_get,fnct_search=_model_search,method=True,string='Model Id'),
454     }
455
456 ir_action_report_xml()
457
458
459 import random
460 import string
461
462
463 def random_name():
464     random.seed()
465     d = [random.choice(string.letters) for x in xrange(10) ]
466     name = "".join(d)
467     return name
468
469
470 def create_directory(path):
471     dir_name = random_name()
472     path = os.path.join(path,dir_name)
473     os.mkdir(path)
474     return dir_name
475
476 class document_file(osv.osv):
477     _inherit = 'ir.attachment'
478     def _data_get(self, cr, uid, ids, name, arg, context):
479         result = {}
480         cr.execute('select id,store_method,datas,store_fname,link from ir_attachment where id in ('+','.join(map(str,ids))+')')
481         for id,m,d,r,l in cr.fetchall():
482             if m=='db':
483                 result[id] = d
484             elif m=='fs':
485                 try:
486                     path = os.path.join(os.getcwd(),'filestore')
487                     value = file(os.path.join(path,r), 'rb').read()
488                     result[id] = base64.encodestring(value)
489                 except:
490                     result[id]=''
491             else:
492                 result[id] = ''
493         return result
494
495     #
496     # This code can be improved
497     #
498     def _data_set(self, cr, obj, id, name, value, uid=None, context={}):
499         if not value:
500             return True
501         if (not context) or context.get('store_method','fs')=='fs':
502             path = os.path.join(os.getcwd(), "filestore")
503             if not os.path.isdir(path):
504                 os.mkdir(path)
505             flag = None
506             # This can be improved
507             for dirs in os.listdir(path):
508                 if os.path.isdir(os.path.join(path,dirs)) and len(os.listdir(os.path.join(path,dirs)))<4000:
509                     flag = dirs
510                     break
511             flag = flag or create_directory(path)
512             filename = random_name()
513             fname = os.path.join(path, flag, filename)
514             fp = file(fname,'wb')
515             v = base64.decodestring(value)
516             fp.write(v)
517             filesize = os.stat(fname).st_size
518             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))
519         else:
520             cr.execute('update ir_attachment set datas=%s,store_method=%s where id=%d', (psycopg.Binary(value),'db',id))
521         return True
522
523     _columns = {
524         'user_id': fields.many2one('res.users', 'Owner', select=1),
525         'group_ids': fields.many2many('res.groups', 'document_directory_group_rel', 'item_id', 'group_id', 'Groups'),
526         'parent_id': fields.many2one('document.directory', 'Directory', select=1),
527         'file_size': fields.integer('File Size', required=True),
528         'file_type': fields.char('Content Type', size=32),
529         'index_content': fields.text('Indexed Content'),
530         'write_date': fields.datetime('Date Modified', readonly=True),
531         'write_uid':  fields.many2one('res.users', 'Last Modification User', readonly=True),
532         'create_date': fields.datetime('Date Created', readonly=True),
533         'create_uid':  fields.many2one('res.users', 'Creator', readonly=True),
534         'store_method': fields.selection([('db','Database'),('fs','Filesystem'),('link','Link')], "Storing Method"),
535         'datas': fields.function(_data_get,method=True,store=True,fnct_inv=_data_set,string='File Content',type="binary"),
536         'store_fname': fields.char('Stored Filename', size=200),
537         'res_model': fields.char('Attached Model', size=64), #res_model
538         'res_id': fields.integer('Attached ID'), #res_id
539         'partner_id':fields.many2one('res.partner', 'Partner', select=1),
540         'title': fields.char('Resource Title',size=64),
541     }
542
543     _defaults = {
544         'user_id': lambda self,cr,uid,ctx:uid,
545         'file_size': lambda self,cr,uid,ctx:0,
546         'store_method': lambda *args: 'db'
547     }
548     _sql_constraints = [
549         ('filename_uniq', 'unique (name,parent_id,res_id,res_model)', 'The file name must be unique !')
550     ]
551
552     def _check_duplication(self, cr, uid,vals):
553         if 'name' in vals:
554             res=self.search(cr,uid,[('name','=',vals['name']),('parent_id','=','parent_id' in vals and vals['parent_id'] or False),('res_id','=','res_id' in vals and vals['res_id'] or False),('res_model','=','res_model' in vals and vals['res_model']) or False])
555             if len(res):
556                 return False
557         return True
558
559     def write(self, cr, uid, ids, vals, context=None):
560         if not self._check_duplication(cr,uid,vals):
561             raise except_orm('ValidateError', 'File name must be unique!')
562         result = super(document_file,self).write(cr,uid,ids,vals,context=context)
563         try:
564             for f in self.browse(cr, uid, ids, context=context):
565                 if 'datas' not in vals:
566                     vals['datas']=f.datas
567                 res = content_index(base64.decodestring(vals['datas']), f.datas_fname, f.file_type or None)
568                 super(document_file,self).write(cr, uid, ids, {
569                     'index_content': res
570                 })
571         except:
572             pass
573         return result
574
575     def create(self, cr, uid, vals, context={}):
576         vals['title']=vals['name']
577         if vals.get('res_id', False) and vals.get('res_model',False):
578             obj_model=self.pool.get(vals['res_model'])
579             result = obj_model.read(cr, uid, [vals['res_id']], context=context)
580             if len(result):
581                 obj=result[0]
582                 vals['title'] = (obj['name'] or '')[:60]
583                 if obj_model._name=='res.partner':
584                     vals['partner_id']=obj['id']
585                 elif 'address_id' in obj:
586                     address=self.pool.get('res.partner.address').read(cr,uid,[obj['address_id']],context=context)
587                     if len(address):
588                         vals['partner_id']=address[0]['partner_id'] or False
589                 elif 'partner_id' in obj:
590                     if isinstance(obj['partner_id'],tuple) or isinstance(obj['partner_id'],list):
591                         vals['partner_id']=obj['partner_id'][0]
592                     else:
593                         vals['partner_id']=obj['partner_id']
594
595         datas=None
596         if 'datas' not in vals:
597             import urllib
598             datas=base64.encodestring(urllib.urlopen(vals['link']).read())
599         else:
600             datas=vals['datas']
601         vals['file_size']= len(datas)
602         if not self._check_duplication(cr,uid,vals):
603             raise except_orm('ValidateError', 'File name must be unique!')
604         result = super(document_file,self).create(cr, uid, vals, context)
605         cr.commit()
606         try:
607             res = content_index(base64.decodestring(datas), vals['datas_fname'], vals.get('content_type', None))
608             super(document_file,self).write(cr, uid, [result], {
609                 'index_content': res,
610             })
611             cr.commit()
612         except:
613             pass
614         return result
615
616     def unlink(self,cr, uid, ids, context={}):
617         for f in self.browse(cr, uid, ids, context):
618             if f.store_method=='fs':
619                 try:
620                     path = os.path.join(os.getcwd(),'filestore',f.store_fname)
621                     os.unlink(path)
622                 except:
623                     pass
624         return super(document_file, self).unlink(cr, uid, ids, context)
625 document_file()
626
627 class document_configuration_wizard(osv.osv_memory):
628     _name='document.configuration.wizard'
629     _rec_name = 'Auto Directory configuration'
630     _columns = {
631                  }
632     def action_cancel(self,cr,uid,ids,conect=None):
633         return {
634                 'view_type': 'form',
635                 "view_mode": 'form',
636                 'res_model': 'ir.actions.configuration.wizard',
637                 'type': 'ir.actions.act_window',
638                 'target':'new',
639          }
640
641     def action_config(self, cr, uid, ids, context=None):
642         obj=self.pool.get('document.directory')
643         objid=self.pool.get('ir.model.data')
644
645         if self.pool.get('sale.order'):
646             id = objid._get_id(cr, uid, 'document', 'dir_sale_order_all')
647             id = objid.browse(cr, uid, id, context=context).res_id
648             mid = self.pool.get('ir.model').search(cr, uid, [('model','=','sale.order')])
649             obj.write(cr, uid, [id], {
650                 'type':'ressource',
651                 'ressource_type_id': mid[0],
652                 'domain': '[]',
653             })
654             aid = objid._get_id(cr, uid, 'sale', 'report_sale_order')
655             aid = objid.browse(cr, uid, aid, context=context).res_id
656
657             self.pool.get('document.directory.content').create(cr, uid, {
658                 'name': "Print Order",
659                 'suffix': "_print",
660                 'report_id': aid,
661                 'extension': '.pdf',
662                 'include_name': 1,
663                 'directory_id': id,
664             })
665             id = objid._get_id(cr, uid, 'document', 'dir_sale_order_quote')
666             id = objid.browse(cr, uid, id, context=context).res_id
667             obj.write(cr, uid, [id], {
668                 'type':'ressource',
669                 'ressource_type_id': mid[0],
670                 'domain': "[('state','=','draft')]",
671             })
672
673         if self.pool.get('product.product'):
674             id = objid._get_id(cr, uid, 'document', 'dir_product')
675             id = objid.browse(cr, uid, id, context=context).res_id
676             mid = self.pool.get('ir.model').search(cr, uid, [('model','=','product.product')])
677             obj.write(cr, uid, [id], {
678                 'type':'ressource',
679                 'ressource_type_id': mid[0],
680             })
681
682         if self.pool.get('stock.location'):
683             aid = objid._get_id(cr, uid, 'stock', 'report_product_history')
684             aid = objid.browse(cr, uid, aid, context=context).res_id
685
686             self.pool.get('document.directory.content').create(cr, uid, {
687                 'name': "Product Stock",
688                 'suffix': "_stock_forecast",
689                 'report_id': aid,
690                 'extension': '.pdf',
691                 'include_name': 1,
692                 'directory_id': id,
693             })
694  
695         if self.pool.get('account.analytic.account'):
696             id = objid._get_id(cr, uid, 'document', 'dir_project')
697             id = objid.browse(cr, uid, id, context=context).res_id
698             mid = self.pool.get('ir.model').search(cr, uid, [('model','=','account.analytic.account')])
699             obj.write(cr, uid, [id], {
700                 'type':'ressource',
701                 'ressource_type_id': mid[0],
702                 'domain': '[]',
703                 'ressource_tree': 1
704         })
705
706         return {
707                 'view_type': 'form',
708                 "view_mode": 'form',
709                 'res_model': 'ir.actions.configuration.wizard',
710                 'type': 'ir.actions.act_window',
711                 'target':'new',
712         }
713 document_configuration_wizard()