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