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