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.
 
 
 
 
 
 

854 regels
26 KiB

  1. # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
  2. # MIT License. See license.txt
  3. from __future__ import unicode_literals
  4. from six import reraise as raise_, iteritems, string_types
  5. import frappe, sys
  6. from frappe import _
  7. from frappe.utils import (cint, flt, now, cstr, strip_html, getdate, get_datetime, to_timedelta,
  8. sanitize_html, sanitize_email)
  9. from frappe.model import default_fields
  10. from frappe.model.naming import set_new_name
  11. from frappe.model.utils.link_count import notify_link_count
  12. from frappe.modules import load_doctype_module
  13. from frappe.model import display_fieldtypes
  14. from frappe.model.db_schema import type_map, varchar_len
  15. from frappe.utils.password import get_decrypted_password, set_encrypted_password
  16. _classes = {}
  17. def get_controller(doctype):
  18. """Returns the **class** object of the given DocType.
  19. For `custom` type, returns `frappe.model.document.Document`.
  20. :param doctype: DocType name as string."""
  21. from frappe.model.document import Document
  22. global _classes
  23. if not doctype in _classes:
  24. module_name, custom = frappe.db.get_value("DocType", doctype, ["module", "custom"]) \
  25. or ["Core", False]
  26. if custom:
  27. _class = Document
  28. else:
  29. module = load_doctype_module(doctype, module_name)
  30. classname = doctype.replace(" ", "").replace("-", "")
  31. if hasattr(module, classname):
  32. _class = getattr(module, classname)
  33. if issubclass(_class, BaseDocument):
  34. _class = getattr(module, classname)
  35. else:
  36. raise ImportError(doctype)
  37. else:
  38. raise ImportError(doctype)
  39. _classes[doctype] = _class
  40. return _classes[doctype]
  41. class BaseDocument(object):
  42. ignore_in_getter = ("doctype", "_meta", "meta", "_table_fields", "_valid_columns")
  43. def __init__(self, d):
  44. self.update(d)
  45. self.dont_update_if_missing = []
  46. if hasattr(self, "__setup__"):
  47. self.__setup__()
  48. @property
  49. def meta(self):
  50. if not hasattr(self, "_meta"):
  51. self._meta = frappe.get_meta(self.doctype)
  52. return self._meta
  53. def update(self, d):
  54. if "doctype" in d:
  55. self.set("doctype", d.get("doctype"))
  56. # first set default field values of base document
  57. for key in default_fields:
  58. if key in d:
  59. self.set(key, d.get(key))
  60. for key, value in iteritems(d):
  61. self.set(key, value)
  62. return self
  63. def update_if_missing(self, d):
  64. if isinstance(d, BaseDocument):
  65. d = d.get_valid_dict()
  66. if "doctype" in d:
  67. self.set("doctype", d.get("doctype"))
  68. for key, value in iteritems(d):
  69. # dont_update_if_missing is a list of fieldnames, for which, you don't want to set default value
  70. if (self.get(key) is None) and (value is not None) and (key not in self.dont_update_if_missing):
  71. self.set(key, value)
  72. def get_db_value(self, key):
  73. return frappe.db.get_value(self.doctype, self.name, key)
  74. def get(self, key=None, filters=None, limit=None, default=None):
  75. if key:
  76. if isinstance(key, dict):
  77. return _filter(self.get_all_children(), key, limit=limit)
  78. if filters:
  79. if isinstance(filters, dict):
  80. value = _filter(self.__dict__.get(key, []), filters, limit=limit)
  81. else:
  82. default = filters
  83. filters = None
  84. value = self.__dict__.get(key, default)
  85. else:
  86. value = self.__dict__.get(key, default)
  87. if value is None and key not in self.ignore_in_getter \
  88. and key in (d.fieldname for d in self.meta.get_table_fields()):
  89. self.set(key, [])
  90. value = self.__dict__.get(key)
  91. return value
  92. else:
  93. return self.__dict__
  94. def getone(self, key, filters=None):
  95. return self.get(key, filters=filters, limit=1)[0]
  96. def set(self, key, value, as_value=False):
  97. if isinstance(value, list) and not as_value:
  98. self.__dict__[key] = []
  99. self.extend(key, value)
  100. else:
  101. self.__dict__[key] = value
  102. def delete_key(self, key):
  103. if key in self.__dict__:
  104. del self.__dict__[key]
  105. def append(self, key, value=None):
  106. if value==None:
  107. value={}
  108. if isinstance(value, (dict, BaseDocument)):
  109. if not self.__dict__.get(key):
  110. self.__dict__[key] = []
  111. value = self._init_child(value, key)
  112. self.__dict__[key].append(value)
  113. # reference parent document
  114. value.parent_doc = self
  115. return value
  116. else:
  117. raise ValueError(
  118. "Document attached to child table must be a dict or BaseDocument, not " + str(type(value))[1:-1]
  119. )
  120. def extend(self, key, value):
  121. if isinstance(value, list):
  122. for v in value:
  123. self.append(key, v)
  124. else:
  125. raise ValueError
  126. def remove(self, doc):
  127. self.get(doc.parentfield).remove(doc)
  128. def _init_child(self, value, key):
  129. if not self.doctype:
  130. return value
  131. if not isinstance(value, BaseDocument):
  132. if "doctype" not in value:
  133. value["doctype"] = self.get_table_field_doctype(key)
  134. if not value["doctype"]:
  135. raise AttributeError(key)
  136. value = get_controller(value["doctype"])(value)
  137. value.init_valid_columns()
  138. value.parent = self.name
  139. value.parenttype = self.doctype
  140. value.parentfield = key
  141. if value.docstatus is None:
  142. value.docstatus = 0
  143. if not getattr(value, "idx", None):
  144. value.idx = len(self.get(key) or []) + 1
  145. if not getattr(value, "name", None):
  146. value.__dict__['__islocal'] = 1
  147. return value
  148. def get_valid_dict(self, sanitize=True):
  149. d = frappe._dict()
  150. for fieldname in self.meta.get_valid_columns():
  151. d[fieldname] = self.get(fieldname)
  152. # if no need for sanitization and value is None, continue
  153. if not sanitize and d[fieldname] is None:
  154. continue
  155. df = self.meta.get_field(fieldname)
  156. if df:
  157. if df.fieldtype=="Check":
  158. if d[fieldname]==None:
  159. d[fieldname] = 0
  160. elif (not isinstance(d[fieldname], int) or d[fieldname] > 1):
  161. d[fieldname] = 1 if cint(d[fieldname]) else 0
  162. elif df.fieldtype=="Int" and not isinstance(d[fieldname], int):
  163. d[fieldname] = cint(d[fieldname])
  164. elif df.fieldtype in ("Currency", "Float", "Percent") and not isinstance(d[fieldname], float):
  165. d[fieldname] = flt(d[fieldname])
  166. elif df.fieldtype in ("Datetime", "Date") and d[fieldname]=="":
  167. d[fieldname] = None
  168. elif df.get("unique") and cstr(d[fieldname]).strip()=="":
  169. # unique empty field should be set to None
  170. d[fieldname] = None
  171. if isinstance(d[fieldname], list) and df.fieldtype != 'Table':
  172. frappe.throw(_('Value for {0} cannot be a list').format(_(df.label)))
  173. return d
  174. def init_valid_columns(self):
  175. for key in default_fields:
  176. if key not in self.__dict__:
  177. self.__dict__[key] = None
  178. if key in ("idx", "docstatus") and self.__dict__[key] is None:
  179. self.__dict__[key] = 0
  180. for key in self.get_valid_columns():
  181. if key not in self.__dict__:
  182. self.__dict__[key] = None
  183. def get_valid_columns(self):
  184. if self.doctype not in frappe.local.valid_columns:
  185. if self.doctype in ("DocField", "DocPerm") and self.parent in ("DocType", "DocField", "DocPerm"):
  186. from frappe.model.meta import get_table_columns
  187. valid = get_table_columns(self.doctype)
  188. else:
  189. valid = self.meta.get_valid_columns()
  190. frappe.local.valid_columns[self.doctype] = valid
  191. return frappe.local.valid_columns[self.doctype]
  192. def is_new(self):
  193. return self.get("__islocal")
  194. def as_dict(self, no_nulls=False, no_default_fields=False):
  195. doc = self.get_valid_dict()
  196. doc["doctype"] = self.doctype
  197. for df in self.meta.get_table_fields():
  198. children = self.get(df.fieldname) or []
  199. doc[df.fieldname] = [d.as_dict(no_nulls=no_nulls) for d in children]
  200. if no_nulls:
  201. for k in doc.keys():
  202. if doc[k] is None:
  203. del doc[k]
  204. if no_default_fields:
  205. for k in doc.keys():
  206. if k in default_fields:
  207. del doc[k]
  208. for key in ("_user_tags", "__islocal", "__onload", "_liked_by", "__run_link_triggers"):
  209. if self.get(key):
  210. doc[key] = self.get(key)
  211. return doc
  212. def as_json(self):
  213. return frappe.as_json(self.as_dict())
  214. def get_table_field_doctype(self, fieldname):
  215. return self.meta.get_field(fieldname).options
  216. def get_parentfield_of_doctype(self, doctype):
  217. fieldname = [df.fieldname for df in self.meta.get_table_fields() if df.options==doctype]
  218. return fieldname[0] if fieldname else None
  219. def db_insert(self):
  220. """INSERT the document (with valid columns) in the database."""
  221. if not self.name:
  222. # name will be set by document class in most cases
  223. set_new_name(self)
  224. if not self.creation:
  225. self.creation = self.modified = now()
  226. self.created_by = self.modifield_by = frappe.session.user
  227. d = self.get_valid_dict()
  228. columns = d.keys()
  229. try:
  230. frappe.db.sql("""insert into `tab{doctype}`
  231. ({columns}) values ({values})""".format(
  232. doctype = self.doctype,
  233. columns = ", ".join(["`"+c+"`" for c in columns]),
  234. values = ", ".join(["%s"] * len(columns))
  235. ), list(d.values()))
  236. except Exception as e:
  237. if e.args[0]==1062:
  238. if "PRIMARY" in cstr(e.args[1]):
  239. if self.meta.autoname=="hash":
  240. # hash collision? try again
  241. self.name = None
  242. self.db_insert()
  243. return
  244. frappe.msgprint(_("Duplicate name {0} {1}").format(self.doctype, self.name))
  245. traceback = sys.exc_info()[2]
  246. raise_(frappe.DuplicateEntryError, (self.doctype, self.name, e), traceback)
  247. elif "Duplicate" in cstr(e.args[1]):
  248. # unique constraint
  249. self.show_unique_validation_message(e)
  250. else:
  251. raise
  252. else:
  253. raise
  254. self.set("__islocal", False)
  255. def db_update(self):
  256. if self.get("__islocal") or not self.name:
  257. self.db_insert()
  258. return
  259. d = self.get_valid_dict()
  260. # don't update name, as case might've been changed
  261. name = d['name']
  262. del d['name']
  263. columns = d.keys()
  264. try:
  265. frappe.db.sql("""update `tab{doctype}`
  266. set {values} where name=%s""".format(
  267. doctype = self.doctype,
  268. values = ", ".join(["`"+c+"`=%s" for c in columns])
  269. ), list(d.values()) + [name])
  270. except Exception as e:
  271. if e.args[0]==1062 and "Duplicate" in cstr(e.args[1]):
  272. self.show_unique_validation_message(e)
  273. else:
  274. raise
  275. def show_unique_validation_message(self, e):
  276. type, value, traceback = sys.exc_info()
  277. fieldname, label = str(e).split("'")[-2], None
  278. # unique_first_fieldname_second_fieldname is the constraint name
  279. # created using frappe.db.add_unique
  280. if "unique_" in fieldname:
  281. fieldname = fieldname.split("_", 1)[1]
  282. df = self.meta.get_field(fieldname)
  283. if df:
  284. label = df.label
  285. frappe.msgprint(_("{0} must be unique".format(label or fieldname)))
  286. # this is used to preserve traceback
  287. raise_(frappe.UniqueValidationError, (self.doctype, self.name, e), traceback)
  288. def db_set(self, fieldname, value=None, update_modified=True):
  289. '''Set a value in the document object, update the timestamp and update the database.
  290. WARNING: This method does not trigger controller validations and should
  291. be used very carefully.
  292. :param fieldname: fieldname of the property to be updated, or a {"field":"value"} dictionary
  293. :param value: value of the property to be updated
  294. :param update_modified: default True. updates the `modified` and `modified_by` properties
  295. '''
  296. if isinstance(fieldname, dict):
  297. self.update(fieldname)
  298. else:
  299. self.set(fieldname, value)
  300. if update_modified and (self.doctype, self.name) not in frappe.flags.currently_saving:
  301. # don't update modified timestamp if called from post save methods
  302. # like on_update or on_submit
  303. self.set("modified", now())
  304. self.set("modified_by", frappe.session.user)
  305. # to trigger email alert on value change
  306. self.run_method('before_change')
  307. frappe.db.set_value(self.doctype, self.name, fieldname, value,
  308. self.modified, self.modified_by, update_modified=update_modified)
  309. self.run_method('on_change')
  310. def db_get(self, fieldname):
  311. '''get database vale for this fieldname'''
  312. return frappe.db.get_value(self.doctype, self.name, fieldname)
  313. def update_modified(self):
  314. '''Update modified timestamp'''
  315. self.set("modified", now())
  316. frappe.db.set_value(self.doctype, self.name, 'modified', self.modified, update_modified=False)
  317. def _fix_numeric_types(self):
  318. for df in self.meta.get("fields"):
  319. if df.fieldtype == "Check":
  320. self.set(df.fieldname, cint(self.get(df.fieldname)))
  321. elif self.get(df.fieldname) is not None:
  322. if df.fieldtype == "Int":
  323. self.set(df.fieldname, cint(self.get(df.fieldname)))
  324. elif df.fieldtype in ("Float", "Currency", "Percent"):
  325. self.set(df.fieldname, flt(self.get(df.fieldname)))
  326. if self.docstatus is not None:
  327. self.docstatus = cint(self.docstatus)
  328. def _get_missing_mandatory_fields(self):
  329. """Get mandatory fields that do not have any values"""
  330. def get_msg(df):
  331. if df.fieldtype == "Table":
  332. return "{}: {}: {}".format(_("Error"), _("Data missing in table"), _(df.label))
  333. elif self.parentfield:
  334. return "{}: {} {} #{}: {}: {}".format(_("Error"), frappe.bold(_(self.doctype)),
  335. _("Row"), self.idx, _("Value missing for"), _(df.label))
  336. else:
  337. return _("Error: Value missing for {0}: {1}").format(_(df.parent), _(df.label))
  338. missing = []
  339. for df in self.meta.get("fields", {"reqd": ('=', 1)}):
  340. if self.get(df.fieldname) in (None, []) or not strip_html(cstr(self.get(df.fieldname))).strip():
  341. missing.append((df.fieldname, get_msg(df)))
  342. # check for missing parent and parenttype
  343. if self.meta.istable:
  344. for fieldname in ("parent", "parenttype"):
  345. if not self.get(fieldname):
  346. missing.append((fieldname, get_msg(frappe._dict(label=fieldname))))
  347. return missing
  348. def get_invalid_links(self, is_submittable=False):
  349. '''Returns list of invalid links and also updates fetch values if not set'''
  350. def get_msg(df, docname):
  351. if self.parentfield:
  352. return "{} #{}: {}: {}".format(_("Row"), self.idx, _(df.label), docname)
  353. else:
  354. return "{}: {}".format(_(df.label), docname)
  355. invalid_links = []
  356. cancelled_links = []
  357. for df in (self.meta.get_link_fields()
  358. + self.meta.get("fields", {"fieldtype": ('=', "Dynamic Link")})):
  359. docname = self.get(df.fieldname)
  360. if docname:
  361. if df.fieldtype=="Link":
  362. doctype = df.options
  363. if not doctype:
  364. frappe.throw(_("Options not set for link field {0}").format(df.fieldname))
  365. else:
  366. doctype = self.get(df.options)
  367. if not doctype:
  368. frappe.throw(_("{0} must be set first").format(self.meta.get_label(df.options)))
  369. # MySQL is case insensitive. Preserve case of the original docname in the Link Field.
  370. # get a map of values ot fetch along with this link query
  371. # that are mapped as link_fieldname.source_fieldname in Options of
  372. # Readonly or Data or Text type fields
  373. fields_to_fetch = [
  374. _df for _df in self.meta.get_fields_to_fetch(df.fieldname)
  375. if not self.get(_df.fieldname)
  376. ]
  377. if not fields_to_fetch:
  378. # cache a single value type
  379. values = frappe._dict(name=frappe.db.get_value(doctype, docname,
  380. 'name', cache=True))
  381. else:
  382. values_to_fetch = ['name'] + [_df.options.split('.')[-1]
  383. for _df in fields_to_fetch]
  384. # don't cache if fetching other values too
  385. values = frappe.db.get_value(doctype, docname,
  386. values_to_fetch, as_dict=True)
  387. if frappe.get_meta(doctype).issingle:
  388. values.name = doctype
  389. setattr(self, df.fieldname, values.name)
  390. for _df in fields_to_fetch:
  391. setattr(self, _df.fieldname, values[_df.options.split('.')[-1]])
  392. notify_link_count(doctype, docname)
  393. if not values.name:
  394. invalid_links.append((df.fieldname, docname, get_msg(df, docname)))
  395. elif (df.fieldname != "amended_from"
  396. and (is_submittable or self.meta.is_submittable) and frappe.get_meta(doctype).is_submittable
  397. and cint(frappe.db.get_value(doctype, docname, "docstatus"))==2):
  398. cancelled_links.append((df.fieldname, docname, get_msg(df, docname)))
  399. return invalid_links, cancelled_links
  400. def _validate_selects(self):
  401. if frappe.flags.in_import:
  402. return
  403. for df in self.meta.get_select_fields():
  404. if df.fieldname=="naming_series" or not (self.get(df.fieldname) and df.options):
  405. continue
  406. options = (df.options or "").split("\n")
  407. # if only empty options
  408. if not filter(None, options):
  409. continue
  410. # strip and set
  411. self.set(df.fieldname, cstr(self.get(df.fieldname)).strip())
  412. value = self.get(df.fieldname)
  413. if value not in options and not (frappe.flags.in_test and value.startswith("_T-")):
  414. # show an elaborate message
  415. prefix = _("Row #{0}:").format(self.idx) if self.get("parentfield") else ""
  416. label = _(self.meta.get_label(df.fieldname))
  417. comma_options = '", "'.join(_(each) for each in options)
  418. frappe.throw(_('{0} {1} cannot be "{2}". It should be one of "{3}"').format(prefix, label,
  419. value, comma_options))
  420. def _validate_constants(self):
  421. if frappe.flags.in_import or self.is_new() or self.flags.ignore_validate_constants:
  422. return
  423. constants = [d.fieldname for d in self.meta.get("fields", {"set_only_once": ('=',1)})]
  424. if constants:
  425. values = frappe.db.get_value(self.doctype, self.name, constants, as_dict=True)
  426. for fieldname in constants:
  427. df = self.meta.get_field(fieldname)
  428. # This conversion to string only when fieldtype is Date
  429. if df.fieldtype == 'Date' or df.fieldtype == 'Datetime':
  430. value = str(values.get(fieldname))
  431. else:
  432. value = values.get(fieldname)
  433. if self.get(fieldname) != value:
  434. frappe.throw(_("Value cannot be changed for {0}").format(self.meta.get_label(fieldname)),
  435. frappe.CannotChangeConstantError)
  436. def _validate_length(self):
  437. if frappe.flags.in_install:
  438. return
  439. for fieldname, value in iteritems(self.get_valid_dict()):
  440. df = self.meta.get_field(fieldname)
  441. if df and df.fieldtype in type_map and type_map[df.fieldtype][0]=="varchar":
  442. max_length = cint(df.get("length")) or cint(varchar_len)
  443. if len(cstr(value)) > max_length:
  444. if self.parentfield and self.idx:
  445. reference = _("{0}, Row {1}").format(_(self.doctype), self.idx)
  446. else:
  447. reference = "{0} {1}".format(_(self.doctype), self.name)
  448. frappe.throw(_("{0}: '{1}' ({3}) will get truncated, as max characters allowed is {2}")\
  449. .format(reference, _(df.label), max_length, value), frappe.CharacterLengthExceededError, title=_('Value too big'))
  450. def _validate_update_after_submit(self):
  451. # get the full doc with children
  452. db_values = frappe.get_doc(self.doctype, self.name).as_dict()
  453. for key in self.as_dict():
  454. df = self.meta.get_field(key)
  455. db_value = db_values.get(key)
  456. if df and not df.allow_on_submit and (self.get(key) or db_value):
  457. if df.fieldtype=="Table":
  458. # just check if the table size has changed
  459. # individual fields will be checked in the loop for children
  460. self_value = len(self.get(key))
  461. db_value = len(db_value)
  462. else:
  463. self_value = self.get_value(key)
  464. if self_value != db_value:
  465. frappe.throw(_("Not allowed to change {0} after submission").format(df.label),
  466. frappe.UpdateAfterSubmitError)
  467. def _sanitize_content(self):
  468. """Sanitize HTML and Email in field values. Used to prevent XSS.
  469. - Ignore if 'Ignore XSS Filter' is checked or fieldtype is 'Code'
  470. """
  471. if frappe.flags.in_install:
  472. return
  473. for fieldname, value in self.get_valid_dict().items():
  474. if not value or not isinstance(value, string_types):
  475. continue
  476. value = frappe.as_unicode(value)
  477. if (u"<" not in value and u">" not in value):
  478. # doesn't look like html so no need
  479. continue
  480. elif "<!-- markdown -->" in value and not ("<script" in value or "javascript:" in value):
  481. # should be handled separately via the markdown converter function
  482. continue
  483. df = self.meta.get_field(fieldname)
  484. sanitized_value = value
  485. if df and df.get("fieldtype") in ("Data", "Code", "Small Text") and df.get("options")=="Email":
  486. sanitized_value = sanitize_email(value)
  487. elif df and (df.get("ignore_xss_filter")
  488. or (df.get("fieldtype")=="Code" and df.get("options")!="Email")
  489. or df.get("fieldtype") in ("Attach", "Attach Image")
  490. # cancelled and submit but not update after submit should be ignored
  491. or self.docstatus==2
  492. or (self.docstatus==1 and not df.get("allow_on_submit"))):
  493. continue
  494. else:
  495. sanitized_value = sanitize_html(value, linkify=df.fieldtype=='Text Editor')
  496. self.set(fieldname, sanitized_value)
  497. def _save_passwords(self):
  498. '''Save password field values in __Auth table'''
  499. if self.flags.ignore_save_passwords:
  500. return
  501. for df in self.meta.get('fields', {'fieldtype': ('=', 'Password')}):
  502. new_password = self.get(df.fieldname)
  503. if new_password and not self.is_dummy_password(new_password):
  504. # is not a dummy password like '*****'
  505. set_encrypted_password(self.doctype, self.name, new_password, df.fieldname)
  506. # set dummy password like '*****'
  507. self.set(df.fieldname, '*'*len(new_password))
  508. def get_password(self, fieldname='password', raise_exception=True):
  509. if self.get(fieldname) and not self.is_dummy_password(self.get(fieldname)):
  510. return self.get(fieldname)
  511. return get_decrypted_password(self.doctype, self.name, fieldname, raise_exception=raise_exception)
  512. def is_dummy_password(self, pwd):
  513. return ''.join(set(pwd))=='*'
  514. def precision(self, fieldname, parentfield=None):
  515. """Returns float precision for a particular field (or get global default).
  516. :param fieldname: Fieldname for which precision is required.
  517. :param parentfield: If fieldname is in child table."""
  518. from frappe.model.meta import get_field_precision
  519. if parentfield and not isinstance(parentfield, string_types):
  520. parentfield = parentfield.parentfield
  521. cache_key = parentfield or "main"
  522. if not hasattr(self, "_precision"):
  523. self._precision = frappe._dict()
  524. if cache_key not in self._precision:
  525. self._precision[cache_key] = frappe._dict()
  526. if fieldname not in self._precision[cache_key]:
  527. self._precision[cache_key][fieldname] = None
  528. doctype = self.meta.get_field(parentfield).options if parentfield else self.doctype
  529. df = frappe.get_meta(doctype).get_field(fieldname)
  530. if df.fieldtype in ("Currency", "Float", "Percent"):
  531. self._precision[cache_key][fieldname] = get_field_precision(df, self)
  532. return self._precision[cache_key][fieldname]
  533. def get_formatted(self, fieldname, doc=None, currency=None, absolute_value=False, translated=False):
  534. from frappe.utils.formatters import format_value
  535. df = self.meta.get_field(fieldname)
  536. if not df and fieldname in default_fields:
  537. from frappe.model.meta import get_default_df
  538. df = get_default_df(fieldname)
  539. val = self.get(fieldname)
  540. if translated:
  541. val = _(val)
  542. if absolute_value and isinstance(val, (int, float)):
  543. val = abs(self.get(fieldname))
  544. if not doc:
  545. doc = getattr(self, "parent_doc", None) or self
  546. return format_value(val, df=df, doc=doc, currency=currency)
  547. def is_print_hide(self, fieldname, df=None, for_print=True):
  548. """Returns true if fieldname is to be hidden for print.
  549. Print Hide can be set via the Print Format Builder or in the controller as a list
  550. of hidden fields. Example
  551. class MyDoc(Document):
  552. def __setup__(self):
  553. self.print_hide = ["field1", "field2"]
  554. :param fieldname: Fieldname to be checked if hidden.
  555. """
  556. meta_df = self.meta.get_field(fieldname)
  557. if meta_df and meta_df.get("__print_hide"):
  558. return True
  559. print_hide = 0
  560. if self.get(fieldname)==0 and not self.meta.istable:
  561. print_hide = ( df and df.print_hide_if_no_value ) or ( meta_df and meta_df.print_hide_if_no_value )
  562. if not print_hide:
  563. if df and df.print_hide is not None:
  564. print_hide = df.print_hide
  565. elif meta_df:
  566. print_hide = meta_df.print_hide
  567. return print_hide
  568. def in_format_data(self, fieldname):
  569. """Returns True if shown via Print Format::`format_data` property.
  570. Called from within standard print format."""
  571. doc = getattr(self, "parent_doc", self)
  572. if hasattr(doc, "format_data_map"):
  573. return fieldname in doc.format_data_map
  574. else:
  575. return True
  576. def reset_values_if_no_permlevel_access(self, has_access_to, high_permlevel_fields):
  577. """If the user does not have permissions at permlevel > 0, then reset the values to original / default"""
  578. to_reset = []
  579. for df in high_permlevel_fields:
  580. if df.permlevel not in has_access_to and df.fieldtype not in display_fieldtypes:
  581. to_reset.append(df)
  582. if to_reset:
  583. if self.is_new():
  584. # if new, set default value
  585. ref_doc = frappe.new_doc(self.doctype)
  586. else:
  587. # get values from old doc
  588. if self.parent:
  589. self.parent_doc.get_latest()
  590. ref_doc = [d for d in self.parent_doc.get(self.parentfield) if d.name == self.name][0]
  591. else:
  592. ref_doc = self.get_latest()
  593. for df in to_reset:
  594. self.set(df.fieldname, ref_doc.get(df.fieldname))
  595. def get_value(self, fieldname):
  596. df = self.meta.get_field(fieldname)
  597. val = self.get(fieldname)
  598. return self.cast(val, df)
  599. def cast(self, val, df):
  600. if df.fieldtype in ("Currency", "Float", "Percent"):
  601. val = flt(val)
  602. elif df.fieldtype in ("Int", "Check"):
  603. val = cint(val)
  604. elif df.fieldtype in ("Data", "Text", "Small Text", "Long Text",
  605. "Text Editor", "Select", "Link", "Dynamic Link"):
  606. val = cstr(val)
  607. elif df.fieldtype == "Date":
  608. val = getdate(val)
  609. elif df.fieldtype == "Datetime":
  610. val = get_datetime(val)
  611. elif df.fieldtype == "Time":
  612. val = to_timedelta(val)
  613. return val
  614. def _extract_images_from_text_editor(self):
  615. from frappe.utils.file_manager import extract_images_from_doc
  616. if self.doctype != "DocType":
  617. for df in self.meta.get("fields", {"fieldtype": ('=', "Text Editor")}):
  618. extract_images_from_doc(self, df.fieldname)
  619. def _filter(data, filters, limit=None):
  620. """pass filters as:
  621. {"key": "val", "key": ["!=", "val"],
  622. "key": ["in", "val"], "key": ["not in", "val"], "key": "^val",
  623. "key" : True (exists), "key": False (does not exist) }"""
  624. out, _filters = [], {}
  625. # setup filters as tuples
  626. if filters:
  627. for f in filters:
  628. fval = filters[f]
  629. if not isinstance(fval, (tuple, list)):
  630. if fval is True:
  631. fval = ("not None", fval)
  632. elif fval is False:
  633. fval = ("None", fval)
  634. elif isinstance(fval, string_types) and fval.startswith("^"):
  635. fval = ("^", fval[1:])
  636. else:
  637. fval = ("=", fval)
  638. _filters[f] = fval
  639. for d in data:
  640. add = True
  641. for f, fval in iteritems(_filters):
  642. if not frappe.compare(getattr(d, f, None), fval[0], fval[1]):
  643. add = False
  644. break
  645. if add:
  646. out.append(d)
  647. if limit and (len(out)-1)==limit:
  648. break
  649. return out