You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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