您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

787 行
24 KiB

  1. # Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com)
  2. #
  3. # MIT License (MIT)
  4. #
  5. # Permission is hereby granted, free of charge, to any person obtaining a
  6. # copy of this software and associated documentation files (the "Software"),
  7. # to deal in the Software without restriction, including without limitation
  8. # the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9. # and/or sell copies of the Software, and to permit persons to whom the
  10. # Software is furnished to do so, subject to the following conditions:
  11. #
  12. # The above copyright notice and this permission notice shall be included in
  13. # all copies or substantial portions of the Software.
  14. #
  15. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  16. # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  17. # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  18. # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  19. # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
  20. # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. #
  22. from __future__ import unicode_literals
  23. """
  24. Contains the Document class representing an object / record
  25. """
  26. import webnotes
  27. import webnotes.model.meta
  28. from webnotes.utils import *
  29. valid_fields_map = {}
  30. class Document:
  31. """
  32. The wn(meta-data)framework equivalent of a Database Record.
  33. Stores,Retrieves,Updates the record in the corresponding table.
  34. Runs the triggers required.
  35. The `Document` class represents the basic Object-Relational Mapper (ORM). The object type is defined by
  36. `DocType` and the object ID is represented by `name`::
  37. Please note the anamoly in the Web Notes Framework that `ID` is always called as `name`
  38. If both `doctype` and `name` are specified in the constructor, then the object is loaded from the database.
  39. If only `doctype` is given, then the object is not loaded
  40. If `fielddata` is specfied, then the object is created from the given dictionary.
  41. **Note 1:**
  42. The getter and setter of the object are overloaded to map to the fields of the object that
  43. are loaded when it is instantiated.
  44. For example: doc.name will be the `name` field and doc.owner will be the `owner` field
  45. **Note 2 - Standard Fields:**
  46. * `name`: ID / primary key
  47. * `owner`: creator of the record
  48. * `creation`: datetime of creation
  49. * `modified`: datetime of last modification
  50. * `modified_by` : last updating user
  51. * `docstatus` : Status 0 - Saved, 1 - Submitted, 2- Cancelled
  52. * `parent` : if child (table) record, this represents the parent record
  53. * `parenttype` : type of parent record (if any)
  54. * `parentfield` : table fieldname of parent record (if any)
  55. * `idx` : Index (sequence) of the child record
  56. """
  57. def __init__(self, doctype = None, name = None, fielddata = None, prefix='tab'):
  58. self._roles = []
  59. self._perms = []
  60. self._user_defaults = {}
  61. self._prefix = prefix
  62. if isinstance(doctype, dict):
  63. fielddata = doctype
  64. doctype = None
  65. if fielddata:
  66. self.fields = webnotes._dict(fielddata)
  67. else:
  68. self.fields = webnotes._dict()
  69. if not self.fields.has_key('name'):
  70. self.fields['name']='' # required on save
  71. if not self.fields.has_key('doctype'):
  72. self.fields['doctype']='' # required on save
  73. if not self.fields.has_key('owner'):
  74. self.fields['owner']='' # required on save
  75. if doctype:
  76. self.fields['doctype'] = doctype
  77. if name:
  78. self.fields['name'] = name
  79. self.__initialized = 1
  80. if (doctype and name):
  81. self._loadfromdb(doctype, name)
  82. else:
  83. if not fielddata:
  84. self.fields['__islocal'] = 1
  85. if not self.fields.docstatus:
  86. self.fields.docstatus = 0
  87. def __nonzero__(self):
  88. return True
  89. def __str__(self):
  90. return str(self.fields)
  91. def __eq__(self, other):
  92. return self.fields == other.fields
  93. def __getstate__(self):
  94. return self.fields
  95. def __setstate__(self, d):
  96. self.fields = d
  97. # Load Document
  98. # ---------------------------------------------------------------------------
  99. def encode(self, encoding='utf-8'):
  100. """convert all unicode values to utf-8"""
  101. for key in self.fields:
  102. if isinstance(self.fields[key], unicode):
  103. self.fields[key] = self.fields[key].encode(encoding)
  104. def _loadfromdb(self, doctype = None, name = None):
  105. if name: self.name = name
  106. if doctype: self.doctype = doctype
  107. is_single = False
  108. try:
  109. is_single = webnotes.model.meta.is_single(self.doctype)
  110. except Exception, e:
  111. pass
  112. if is_single:
  113. self._loadsingle()
  114. else:
  115. dataset = webnotes.conn.sql('select * from `%s%s` where name="%s"' % (self._prefix, self.doctype, self.name.replace('"', '\"')))
  116. if not dataset:
  117. raise Exception, '[WNF] %s %s does not exist' % (self.doctype, self.name)
  118. self._load_values(dataset[0], webnotes.conn.get_description())
  119. # Load Fields from dataset
  120. # ---------------------------------------------------------------------------
  121. def _load_values(self, data, description):
  122. if '__islocal' in self.fields:
  123. del self.fields['__islocal']
  124. for i in range(len(description)):
  125. v = data[i]
  126. self.fields[description[i][0]] = webnotes.conn.convert_to_simple_type(v)
  127. def _merge_values(self, data, description):
  128. for i in range(len(description)):
  129. v = data[i]
  130. if v: # only if value, over-write
  131. self.fields[description[i][0]] = webnotes.conn.convert_to_simple_type(v)
  132. # Load Single Type
  133. # ---------------------------------------------------------------------------
  134. def _loadsingle(self):
  135. self.name = self.doctype
  136. self.fields.update(getsingle(self.doctype))
  137. # Setter
  138. # ---------------------------------------------------------------------------
  139. def __setattr__(self, name, value):
  140. # normal attribute
  141. if not self.__dict__.has_key('_Document__initialized'):
  142. self.__dict__[name] = value
  143. elif self.__dict__.has_key(name):
  144. self.__dict__[name] = value
  145. else:
  146. # field attribute
  147. f = self.__dict__['fields']
  148. f[name] = value
  149. # Getter
  150. # ---------------------------------------------------------------------------
  151. def __getattr__(self, name):
  152. if self.__dict__.has_key(name):
  153. return self.__dict__[name]
  154. elif self.fields.has_key(name):
  155. return self.fields[name]
  156. else:
  157. return ''
  158. # Get Amendement number
  159. # ---------------------------------------------------------------------------
  160. def _get_amended_name(self):
  161. am_id = 1
  162. am_prefix = self.amended_from
  163. if webnotes.conn.sql('select amended_from from `tab%s` where name = "%s"' % (self.doctype, self.amended_from))[0][0] or '':
  164. am_id = cint(self.amended_from.split('-')[-1]) + 1
  165. am_prefix = '-'.join(self.amended_from.split('-')[:-1]) # except the last hyphen
  166. self.name = am_prefix + '-' + str(am_id)
  167. # Set Name
  168. # ---------------------------------------------------------------------------
  169. def _set_name(self, autoname, istable):
  170. self.localname = self.name
  171. # get my object
  172. import webnotes.model.code
  173. so = webnotes.model.code.get_server_obj(self, [])
  174. # amendments
  175. if self.amended_from:
  176. self._get_amended_name()
  177. # by method
  178. elif so and hasattr(so, 'autoname'):
  179. r = webnotes.model.code.run_server_obj(so, 'autoname')
  180. if r: return r
  181. # based on a field
  182. elif autoname and autoname.startswith('field:'):
  183. n = self.fields[autoname[6:]]
  184. if not n:
  185. raise Exception, 'Name is required'
  186. self.name = n.strip()
  187. elif autoname and autoname.startswith("naming_series:"):
  188. if not self.naming_series:
  189. # pick default naming series
  190. from webnotes.model.doctype import get_property
  191. self.naming_series = get_property(self.doctype, "options", "naming_series").split("\n")
  192. self.naming_series = self.naming_series[0] or self.naming_series[1]
  193. self.name = make_autoname(self.naming_series+'.#####')
  194. # based on expression
  195. elif autoname and autoname.startswith('eval:'):
  196. doc = self # for setting
  197. self.name = eval(autoname[5:])
  198. # call the method!
  199. elif autoname and autoname!='Prompt':
  200. self.name = make_autoname(autoname, self.doctype)
  201. # given
  202. elif self.fields.get('__newname',''):
  203. self.name = self.fields['__newname']
  204. # default name for table
  205. elif istable:
  206. self.name = make_autoname('#########', self.doctype)
  207. # unable to determine a name, use a serial number!
  208. if not self.name:
  209. self.name = make_autoname('#########', self.doctype)
  210. # Validate Name
  211. # ---------------------------------------------------------------------------
  212. def _validate_name(self, case):
  213. if webnotes.conn.sql('select name from `tab%s` where name=%s' % (self.doctype,'%s'), self.name):
  214. raise NameError, 'Name %s already exists' % self.name
  215. # no name
  216. if not self.name: return 'No Name Specified for %s' % self.doctype
  217. # new..
  218. if self.name.startswith('New '+self.doctype):
  219. raise NameError, 'There were some errors setting the name, please contact the administrator'
  220. if case=='Title Case': self.name = self.name.title()
  221. if case=='UPPER CASE': self.name = self.name.upper()
  222. self.name = self.name.strip() # no leading and trailing blanks
  223. forbidden = ['%', "'", '"', '#', '*', '?', '`']
  224. for f in forbidden:
  225. if f in self.name:
  226. webnotes.msgprint('%s not allowed in ID (name)' % f, raise_exception =1)
  227. # Insert
  228. # ---------------------------------------------------------------------------
  229. def insert(self, autoname, istable, case='', make_autoname=1, keep_timestamps=False):
  230. # set name
  231. if make_autoname:
  232. self._set_name(autoname, istable)
  233. # validate name
  234. self._validate_name(case)
  235. # insert!
  236. if not keep_timestamps:
  237. if not self.owner:
  238. self.owner = webnotes.session['user']
  239. self.modified_by = webnotes.session['user']
  240. self.creation = self.modified = now()
  241. webnotes.conn.sql("insert into `tab%(doctype)s`" % self.fields \
  242. + """ (name, owner, creation, modified, modified_by)
  243. values (%(name)s, %(owner)s, %(creation)s, %(modified)s,
  244. %(modified_by)s)""", self.fields)
  245. # Update Values
  246. # ---------------------------------------------------------------------------
  247. def _update_single(self, link_list):
  248. update_str = ["(%s, 'modified', %s)",]
  249. values = [self.doctype, now()]
  250. webnotes.conn.sql("delete from tabSingles where doctype='%s'" % self.doctype)
  251. for f in self.fields.keys():
  252. if not (f in ('modified', 'doctype', 'name', 'perm', 'localname', 'creation'))\
  253. and (not f.startswith('__')): # fields not saved
  254. # validate links
  255. if link_list and link_list.get(f):
  256. self.fields[f] = self._validate_link(link_list[f][0], self.fields[f])
  257. if self.fields[f]==None:
  258. update_str.append("(%s,%s,NULL)")
  259. values.append(self.doctype)
  260. values.append(f)
  261. else:
  262. update_str.append("(%s,%s,%s)")
  263. values.append(self.doctype)
  264. values.append(f)
  265. values.append(self.fields[f])
  266. webnotes.conn.sql("insert into tabSingles(doctype, field, value) values %s" % (', '.join(update_str)), values)
  267. # Validate Links
  268. # ---------------------------------------------------------------------------
  269. def validate_links(self, link_list):
  270. err_list = []
  271. for f in self.fields.keys():
  272. # validate links
  273. old_val = self.fields[f]
  274. if link_list and link_list.get(f):
  275. self.fields[f] = self._validate_link(link_list[f][0], self.fields[f])
  276. if old_val and not self.fields[f]:
  277. s = link_list[f][1] + ': ' + old_val
  278. err_list.append(s)
  279. return err_list
  280. def make_link_list(self):
  281. res = webnotes.model.meta.get_link_fields(self.doctype)
  282. link_list = {}
  283. for i in res: link_list[i[0]] = (i[1], i[2]) # options, label
  284. return link_list
  285. def _validate_link(self, dt, dn):
  286. if not dt: return dn
  287. if not dn: return None
  288. if dt=="[Select]": return dn
  289. if dt.lower().startswith('link:'):
  290. dt = dt[5:]
  291. if '\n' in dt:
  292. dt = dt.split('\n')[0]
  293. tmp = webnotes.conn.sql("""SELECT name FROM `tab%s`
  294. WHERE name = %s""" % (dt, '%s'), dn)
  295. return tmp and tmp[0][0] or ''# match case
  296. def _update_values(self, issingle, link_list, ignore_fields=0, keep_timestamps=False):
  297. if issingle:
  298. self._update_single(link_list)
  299. else:
  300. update_str, values = [], []
  301. # set modified timestamp
  302. if self.modified and not keep_timestamps:
  303. self.modified = now()
  304. self.modified_by = webnotes.session['user']
  305. fields_list = ignore_fields and self.get_valid_fields() or self.fields.keys()
  306. for f in fields_list:
  307. if (not (f in ('doctype', 'name', 'perm', 'localname',
  308. 'creation','_user_tags'))) and (not f.startswith('__')):
  309. # fields not saved
  310. # validate links
  311. if link_list and link_list.get(f):
  312. self.fields[f] = self._validate_link(link_list[f][0],
  313. self.fields.get(f))
  314. if self.fields.get(f) is None or self.fields.get(f)=='':
  315. update_str.append("`%s`=NULL" % f)
  316. else:
  317. values.append(self.fields.get(f))
  318. update_str.append("`%s`=%s" % (f, '%s'))
  319. if values:
  320. values.append(self.name)
  321. r = webnotes.conn.sql("update `tab%s` set %s where name=%s" % \
  322. (self.doctype, ', '.join(update_str), "%s"), values)
  323. def get_valid_fields(self):
  324. global valid_fields_map
  325. if not valid_fields_map.get(self.doctype):
  326. import webnotes.model.doctype
  327. if cint(webnotes.conn.get_value("DocType", self.doctype, "issingle")):
  328. doctypelist = webnotes.model.doctype.get(self.doctype)
  329. valid_fields_map[self.doctype] = doctypelist.get_fieldnames({
  330. "fieldtype": ["not in", webnotes.model.no_value_fields]})
  331. else:
  332. valid_fields_map[self.doctype] = \
  333. webnotes.conn.get_table_columns(self.doctype)
  334. return valid_fields_map.get(self.doctype)
  335. # Save values
  336. # ---------------------------------------------------------------------------
  337. def save(self, new=0, check_links=1, ignore_fields=0, make_autoname=1,
  338. keep_timestamps=False):
  339. """
  340. Saves the current record in the database.
  341. If new = 1, creates a new instance of the record.
  342. Also clears temperory fields starting with `__`
  343. * if check_links is set, it validates all `Link` fields
  344. * if ignore_fields is sets, it does not throw an exception
  345. for any field that does not exist in the database table
  346. """
  347. res = webnotes.model.meta.get_dt_values(self.doctype,
  348. 'autoname, issingle, istable, name_case', as_dict=1)
  349. res = res and res[0] or {}
  350. # add missing parentinfo (if reqd)
  351. if self.parent and not (self.parenttype and self.parentfield):
  352. self.update_parentinfo()
  353. if self.parent and not self.idx:
  354. self.set_idx()
  355. # if required, make new
  356. if new or (not new and self.fields.get('__islocal')) and (not res.get('issingle')):
  357. # new
  358. r = self.insert(res.get('autoname'), res.get('istable'), res.get('name_case'),
  359. make_autoname, keep_timestamps = keep_timestamps)
  360. if r:
  361. return r
  362. else:
  363. if not res.get('issingle') and not webnotes.conn.exists(self.doctype, self.name):
  364. webnotes.msgprint("""This document was updated before your change. Please refresh before saving.""", raise_exception=1)
  365. # save the values
  366. self._update_values(res.get('issingle'),
  367. check_links and self.make_link_list() or {}, ignore_fields=ignore_fields,
  368. keep_timestamps=keep_timestamps)
  369. self._clear_temp_fields()
  370. def update_parentinfo(self):
  371. """update parent type and parent field, if not explicitly specified"""
  372. tmp = webnotes.conn.sql("""select parent, fieldname from tabDocField
  373. where fieldtype='Table' and options=%s""", self.doctype)
  374. if len(tmp)==0:
  375. raise Exception, 'Incomplete parent info in child table (%s, %s)' \
  376. % (self.doctype, self.fields.get('name', '[new]'))
  377. elif len(tmp)>1:
  378. raise Exception, 'Ambiguous parent info (%s, %s)' \
  379. % (self.doctype, self.fields.get('name', '[new]'))
  380. else:
  381. self.parenttype = tmp[0][0]
  382. self.parentfield = tmp[0][1]
  383. def set_idx(self):
  384. """set idx"""
  385. self.idx = (webnotes.conn.sql("""select max(idx) from `tab%s`
  386. where parent=%s and parentfield=%s""" % (self.doctype, '%s', '%s'),
  387. (self.parent, self.parentfield))[0][0] or 0) + 1
  388. # check permissions
  389. # ---------------------------------------------------------------------------
  390. def _get_perms(self):
  391. if not self._perms:
  392. self._perms = webnotes.conn.sql("""select role, `match` from tabDocPerm
  393. where parent=%s and ifnull(`read`,0) = 1
  394. and ifnull(permlevel,0)=0""", self.doctype)
  395. def _get_roles(self):
  396. # check if roles match/
  397. if not self._roles:
  398. if webnotes.user:
  399. self._roles = webnotes.user.get_roles()
  400. else:
  401. self._roles = ['Guest']
  402. def _get_user_defaults(self):
  403. if not self._user_defaults:
  404. if webnotes.user:
  405. self._user_defaults = webnotes.user.get_defaults()
  406. else:
  407. self.defaults = {}
  408. def check_perm(self, verbose=0):
  409. import webnotes
  410. # Admin has all permissions
  411. if webnotes.session['user']=='Administrator':
  412. return 1
  413. # find roles with read access for this record at 0
  414. self._get_perms()
  415. self._get_roles()
  416. self._get_user_defaults()
  417. has_perm, match = 0, []
  418. # loop through everything to find if there is a match
  419. for r in self._perms:
  420. if r[0] in self._roles:
  421. has_perm = 1
  422. if r[1] and match != -1:
  423. match.append(r[1]) # add to match check
  424. else:
  425. match = -1 # has permission and no match, so match not required!
  426. if has_perm and match and match != -1:
  427. for m in match:
  428. if ":" in m:
  429. document_key, default_key = m.split(":")
  430. else:
  431. document_key = default_key = m
  432. if self.fields.get(document_key, 'no value') in \
  433. self._user_defaults.get(default_key, 'no default'):
  434. has_perm = 1
  435. break # permission found! break
  436. else:
  437. has_perm = 0
  438. return has_perm
  439. def _clear_temp_fields(self):
  440. # clear temp stuff
  441. keys = self.fields.keys()
  442. for f in keys:
  443. if f.startswith('__'):
  444. del self.fields[f]
  445. def clear_table(self, doclist, tablefield, save=0):
  446. """
  447. Clears the child records from the given `doclist` for a particular `tablefield`
  448. """
  449. from webnotes.model.utils import getlist
  450. table_list = getlist(doclist, tablefield)
  451. delete_list = [d.name for d in table_list]
  452. if delete_list:
  453. #filter doclist
  454. doclist = filter(lambda d: d.name not in delete_list, doclist)
  455. # delete from db
  456. webnotes.conn.sql("""\
  457. delete from `tab%s`
  458. where parent=%s and parenttype=%s"""
  459. % (table_list[0].doctype, '%s', '%s'),
  460. (self.name, self.doctype))
  461. self.fields['__unsaved'] = 1
  462. return webnotes.doclist(doclist)
  463. def addchild(self, fieldname, childtype = '', doclist=None):
  464. """
  465. Returns a child record of the give `childtype`.
  466. * if local is set, it does not save the record
  467. * if doclist is passed, it append the record to the doclist
  468. """
  469. d = Document()
  470. d.parent = self.name
  471. d.parenttype = self.doctype
  472. d.parentfield = fieldname
  473. d.doctype = childtype
  474. d.docstatus = 0;
  475. d.name = ''
  476. d.owner = webnotes.session['user']
  477. d.fields['__islocal'] = 1 # for Client to identify unsaved doc
  478. if doclist != None:
  479. doclist.append(d)
  480. return d
  481. def get_values(self):
  482. """get non-null fields dict withouth standard fields"""
  483. from webnotes.model import default_fields
  484. ret = {}
  485. for key in self.fields:
  486. if key not in default_fields and self.fields[key]:
  487. ret[key] = self.fields[key]
  488. return ret
  489. def addchild(parent, fieldname, childtype = '', doclist=None):
  490. """
  491. Create a child record to the parent doc.
  492. Example::
  493. c = Document('Contact','ABC')
  494. d = addchild(c, 'contact_updates', 'Contact Update')
  495. d.last_updated = 'Phone call'
  496. d.save(1)
  497. """
  498. return parent.addchild(fieldname, childtype, doclist)
  499. # Naming
  500. # ------
  501. def make_autoname(key, doctype=''):
  502. """
  503. Creates an autoname from the given key:
  504. **Autoname rules:**
  505. * The key is separated by '.'
  506. * '####' represents a series. The string before this part becomes the prefix:
  507. Example: ABC.#### creates a series ABC0001, ABC0002 etc
  508. * 'MM' represents the current month
  509. * 'YY' and 'YYYY' represent the current year
  510. *Example:*
  511. * DE/./.YY./.MM./.##### will create a series like
  512. DE/09/01/0001 where 09 is the year, 01 is the month and 0001 is the series
  513. """
  514. n = ''
  515. l = key.split('.')
  516. for e in l:
  517. en = ''
  518. if e.startswith('#'):
  519. digits = len(e)
  520. en = getseries(n, digits, doctype)
  521. elif e=='YY':
  522. import time
  523. en = time.strftime('%y')
  524. elif e=='MM':
  525. import time
  526. en = time.strftime('%m')
  527. elif e=='YYYY':
  528. import time
  529. en = time.strftime('%Y')
  530. else: en = e
  531. n+=en
  532. return n
  533. # Get Series for Autoname
  534. # -----------------------
  535. def getseries(key, digits, doctype=''):
  536. # series created ?
  537. if webnotes.conn.sql("select name from tabSeries where name='%s'" % key):
  538. # yes, update it
  539. webnotes.conn.sql("update tabSeries set current = current+1 where name='%s'" % key)
  540. # find the series counter
  541. r = webnotes.conn.sql("select current from tabSeries where name='%s'" % key)
  542. n = r[0][0]
  543. else:
  544. # no, create it
  545. webnotes.conn.sql("insert into tabSeries (name, current) values ('%s', 1)" % key)
  546. n = 1
  547. return ('%0'+str(digits)+'d') % n
  548. # Get Children
  549. # ------------
  550. def getchildren(name, childtype, field='', parenttype='', from_doctype=0, prefix='tab'):
  551. import webnotes
  552. from webnotes.model.doclist import DocList
  553. tmp = ''
  554. if field:
  555. tmp = ' and parentfield="%s" ' % field
  556. if parenttype:
  557. tmp = ' and parenttype="%s" ' % parenttype
  558. dataset = webnotes.conn.sql("select * from `%s%s` where parent='%s' %s order by idx" \
  559. % (prefix, childtype, name, tmp))
  560. desc = webnotes.conn.get_description()
  561. l = DocList()
  562. for i in dataset:
  563. d = Document()
  564. d.doctype = childtype
  565. d._load_values(i, desc)
  566. l.append(d)
  567. return l
  568. # Check if "Guest" is allowed to view this page
  569. # ---------------------------------------------
  570. def check_page_perm(doc):
  571. if doc.name=='Login Page':
  572. return
  573. if doc.publish:
  574. return
  575. if not webnotes.conn.sql("select name from `tabPage Role` where parent=%s and role='Guest'", doc.name):
  576. webnotes.response['403'] = 1
  577. raise webnotes.PermissionError, '[WNF] No read permission for %s %s' % ('Page', doc.name)
  578. def get_report_builder_code(doc):
  579. if doc.doctype=='Search Criteria':
  580. from webnotes.model.code import get_code
  581. if doc.standard != 'No':
  582. doc.report_script = get_code(doc.module, 'Search Criteria', doc.name, 'js')
  583. doc.custom_query = get_code(doc.module, 'Search Criteria', doc.name, 'sql')
  584. # called from everywhere
  585. # load a record and its child records and bundle it in a list - doclist
  586. # ---------------------------------------------------------------------
  587. def get(dt, dn='', with_children = 1, from_get_obj = 0, prefix = 'tab'):
  588. """
  589. Returns a doclist containing the main record and all child records
  590. """
  591. import webnotes
  592. import webnotes.model
  593. from webnotes.model.doclist import DocList
  594. dn = dn or dt
  595. # load the main doc
  596. doc = Document(dt, dn, prefix=prefix)
  597. # check permission - for doctypes, pages
  598. if (dt in ('DocType', 'Page', 'Control Panel', 'Search Criteria')) or (from_get_obj and webnotes.session.get('user') != 'Guest'):
  599. if dt=='Page' and webnotes.session['user'] == 'Guest':
  600. check_page_perm(doc)
  601. else:
  602. if not doc.check_perm():
  603. webnotes.response['403'] = 1
  604. raise webnotes.ValidationError, '[WNF] No read permission for %s %s' % (dt, dn)
  605. if not with_children:
  606. # done
  607. return DocList([doc,])
  608. # get all children types
  609. tablefields = webnotes.model.meta.get_table_fields(dt)
  610. # load chilren
  611. doclist = DocList([doc,])
  612. for t in tablefields:
  613. doclist += getchildren(doc.name, t[0], t[1], dt, prefix=prefix)
  614. # import report_builder code
  615. if not from_get_obj:
  616. get_report_builder_code(doc)
  617. return doclist
  618. def getsingle(doctype):
  619. """get single doc as dict"""
  620. dataset = webnotes.conn.sql("select field, value from tabSingles where doctype=%s", doctype)
  621. return dict(dataset)