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.

пре 11 година
пре 8 година
пре 8 година
пре 8 година
пре 10 година
пре 11 година
пре 8 година
пре 11 година
пре 11 година
пре 8 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 12 година
пре 11 година
пре 11 година
пре 12 година
пре 11 година
пре 8 година
пре 11 година
пре 11 година
пре 11 година
пре 8 година
пре 11 година
пре 8 година
пре 11 година
пре 11 година
пре 8 година
пре 11 година
пре 11 година
пре 11 година
пре 8 година
пре 11 година
пре 8 година
пре 11 година
пре 11 година
пре 11 година
пре 12 година
пре 8 година
пре 11 година
пре 12 година
пре 11 година
пре 12 година
пре 11 година
пре 11 година
пре 12 година
пре 11 година
пре 11 година
пре 8 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 8 година
пре 11 година
пре 8 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 8 година
пре 11 година
пре 11 година
пре 8 година
пре 11 година
пре 9 година
пре 8 година
пре 9 година
пре 9 година
пре 9 година
пре 9 година
пре 9 година
пре 11 година
пре 9 година
пре 9 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
  2. # MIT License. See license.txt
  3. from __future__ import unicode_literals
  4. import frappe
  5. from frappe import _
  6. import frappe.model
  7. import frappe.utils
  8. import json, os
  9. from six import iteritems
  10. '''
  11. Handle RESTful requests that are mapped to the `/api/resource` route.
  12. Requests via FrappeClient are also handled here.
  13. '''
  14. @frappe.whitelist()
  15. def get_list(doctype, fields=None, filters=None, order_by=None,
  16. limit_start=None, limit_page_length=20):
  17. '''Returns a list of records by filters, fields, ordering and limit
  18. :param doctype: DocType of the data to be queried
  19. :param fields: fields to be returned. Default is `name`
  20. :param filters: filter list by this dict
  21. :param order_by: Order by this fieldname
  22. :param limit_start: Start at this index
  23. :param limit_page_length: Number of records to be returned (default 20)'''
  24. return frappe.get_list(doctype, fields=fields, filters=filters, order_by=order_by,
  25. limit_start=limit_start, limit_page_length=limit_page_length, ignore_permissions=False)
  26. @frappe.whitelist()
  27. def get(doctype, name=None, filters=None):
  28. '''Returns a document by name or filters
  29. :param doctype: DocType of the document to be returned
  30. :param name: return document of this `name`
  31. :param filters: If name is not set, filter by these values and return the first match'''
  32. if filters and not name:
  33. name = frappe.db.get_value(doctype, json.loads(filters))
  34. if not name:
  35. frappe.throw(_("No document found for given filters"))
  36. doc = frappe.get_doc(doctype, name)
  37. if not doc.has_permission("read"):
  38. raise frappe.PermissionError
  39. return frappe.get_doc(doctype, name).as_dict()
  40. @frappe.whitelist()
  41. def get_value(doctype, fieldname, filters=None, as_dict=True, debug=False):
  42. '''Returns a value form a document
  43. :param doctype: DocType to be queried
  44. :param fieldname: Field to be returned (default `name`)
  45. :param filters: dict or string for identifying the record'''
  46. if not frappe.has_permission(doctype):
  47. frappe.throw(_("Not permitted"), frappe.PermissionError)
  48. try:
  49. filters = json.loads(filters)
  50. except (TypeError, ValueError):
  51. # filters are not passesd, not json
  52. pass
  53. try:
  54. fieldname = json.loads(fieldname)
  55. except (TypeError, ValueError):
  56. # name passed, not json
  57. fieldname = "name"
  58. pass
  59. # check whether the used filters were really parseable and usable
  60. # and did not just result in an empty string or dict
  61. if not filters:
  62. filters = None
  63. return frappe.db.get_value(doctype, filters, fieldname, as_dict=as_dict, debug=debug)
  64. @frappe.whitelist()
  65. def set_value(doctype, name, fieldname, value=None):
  66. '''Set a value using get_doc, group of values
  67. :param doctype: DocType of the document
  68. :param name: name of the document
  69. :param fieldname: fieldname string or JSON / dict with key value pair
  70. :param value: value if fieldname is JSON / dict'''
  71. if fieldname!="idx" and fieldname in frappe.model.default_fields:
  72. frappe.throw(_("Cannot edit standard fields"))
  73. if not value:
  74. values = fieldname
  75. if isinstance(fieldname, basestring):
  76. try:
  77. values = json.loads(fieldname)
  78. except ValueError:
  79. values = {fieldname: ''}
  80. else:
  81. values = {fieldname: value}
  82. doc = frappe.db.get_value(doctype, name, ["parenttype", "parent"], as_dict=True)
  83. if doc and doc.parent and doc.parenttype:
  84. doc = frappe.get_doc(doc.parenttype, doc.parent)
  85. child = doc.getone({"doctype": doctype, "name": name})
  86. child.update(values)
  87. else:
  88. doc = frappe.get_doc(doctype, name)
  89. doc.update(values)
  90. doc.save()
  91. return doc.as_dict()
  92. @frappe.whitelist()
  93. def insert(doc=None):
  94. '''Insert a document
  95. :param doc: JSON or dict object to be inserted'''
  96. if isinstance(doc, basestring):
  97. doc = json.loads(doc)
  98. if doc.get("parent") and doc.get("parenttype"):
  99. # inserting a child record
  100. parent = frappe.get_doc(doc.get("parenttype"), doc.get("parent"))
  101. parent.append(doc.get("parentfield"), doc)
  102. parent.save()
  103. return parent.as_dict()
  104. else:
  105. doc = frappe.get_doc(doc).insert()
  106. return doc.as_dict()
  107. @frappe.whitelist()
  108. def insert_many(docs=None):
  109. '''Insert multiple documents
  110. :param docs: JSON or list of dict objects to be inserted in one request'''
  111. if isinstance(docs, basestring):
  112. docs = json.loads(docs)
  113. out = []
  114. if len(docs) > 200:
  115. frappe.throw(_('Only 200 inserts allowed in one request'))
  116. for doc in docs:
  117. if doc.get("parent") and doc.get("parenttype"):
  118. # inserting a child record
  119. parent = frappe.get_doc(doc.get("parenttype"), doc.get("parent"))
  120. parent.append(doc.get("parentfield"), doc)
  121. parent.save()
  122. out.append(parent.name)
  123. else:
  124. doc = frappe.get_doc(doc).insert()
  125. out.append(doc.name)
  126. return out
  127. @frappe.whitelist()
  128. def save(doc):
  129. '''Update (save) an existing document
  130. :param doc: JSON or dict object with the properties of the document to be updated'''
  131. if isinstance(doc, basestring):
  132. doc = json.loads(doc)
  133. doc = frappe.get_doc(doc).save()
  134. return doc.as_dict()
  135. @frappe.whitelist()
  136. def rename_doc(doctype, old_name, new_name, merge=False):
  137. '''Rename document
  138. :param doctype: DocType of the document to be renamed
  139. :param old_name: Current `name` of the document to be renamed
  140. :param new_name: New `name` to be set'''
  141. new_name = frappe.rename_doc(doctype, old_name, new_name, merge=merge)
  142. return new_name
  143. @frappe.whitelist()
  144. def submit(doc):
  145. '''Submit a document
  146. :param doc: JSON or dict object to be submitted remotely'''
  147. if isinstance(doc, basestring):
  148. doc = json.loads(doc)
  149. doc = frappe.get_doc(doc)
  150. doc.submit()
  151. return doc.as_dict()
  152. @frappe.whitelist()
  153. def cancel(doctype, name):
  154. '''Cancel a document
  155. :param doctype: DocType of the document to be cancelled
  156. :param name: name of the document to be cancelled'''
  157. wrapper = frappe.get_doc(doctype, name)
  158. wrapper.cancel()
  159. return wrapper.as_dict()
  160. @frappe.whitelist()
  161. def delete(doctype, name):
  162. '''Delete a remote document
  163. :param doctype: DocType of the document to be deleted
  164. :param name: name of the document to be deleted'''
  165. frappe.delete_doc(doctype, name)
  166. @frappe.whitelist()
  167. def set_default(key, value, parent=None):
  168. """set a user default value"""
  169. frappe.db.set_default(key, value, parent or frappe.session.user)
  170. frappe.clear_cache(user=frappe.session.user)
  171. @frappe.whitelist()
  172. def make_width_property_setter(doc):
  173. '''Set width Property Setter
  174. :param doc: Property Setter document with `width` property'''
  175. if isinstance(doc, basestring):
  176. doc = json.loads(doc)
  177. if doc["doctype"]=="Property Setter" and doc["property"]=="width":
  178. frappe.get_doc(doc).insert(ignore_permissions = True)
  179. @frappe.whitelist()
  180. def bulk_update(docs):
  181. '''Bulk update documents
  182. :param docs: JSON list of documents to be updated remotely. Each document must have `docname` property'''
  183. docs = json.loads(docs)
  184. failed_docs = []
  185. for doc in docs:
  186. try:
  187. ddoc = {key: val for key, val in iteritems(doc) if key not in ['doctype', 'docname']}
  188. doctype = doc['doctype']
  189. docname = doc['docname']
  190. doc = frappe.get_doc(doctype, docname)
  191. doc.update(ddoc)
  192. doc.save()
  193. except:
  194. failed_docs.append({
  195. 'doc': doc,
  196. 'exc': frappe.utils.get_traceback()
  197. })
  198. return {'failed_docs': failed_docs}
  199. @frappe.whitelist()
  200. def has_permission(doctype, docname, perm_type="read"):
  201. '''Returns a JSON with data whether the document has the requested permission
  202. :param doctype: DocType of the document to be checked
  203. :param docname: `name` of the document to be checked
  204. :param perm_type: one of `read`, `write`, `create`, `submit`, `cancel`, `report`. Default is `read`'''
  205. # perm_type can be one of read, write, create, submit, cancel, report
  206. return {"has_permission": frappe.has_permission(doctype, perm_type.lower(), docname)}
  207. @frappe.whitelist()
  208. def get_password(doctype, name, fieldname):
  209. '''Return a password type property. Only applicable for System Managers
  210. :param doctype: DocType of the document that holds the password
  211. :param name: `name` of the document that holds the password
  212. :param fieldname: `fieldname` of the password property
  213. '''
  214. frappe.only_for("System Manager")
  215. return frappe.get_doc(doctype, name).get_password(fieldname)
  216. @frappe.whitelist()
  217. def get_js(items):
  218. '''Load JS code files. Will also append translations
  219. and extend `frappe._messages`
  220. :param items: JSON list of paths of the js files to be loaded.'''
  221. items = json.loads(items)
  222. out = []
  223. for src in items:
  224. src = src.strip("/").split("/")
  225. if ".." in src or src[0] != "assets":
  226. frappe.throw(_("Invalid file path: {0}").format("/".join(src)))
  227. contentpath = os.path.join(frappe.local.sites_path, *src)
  228. with open(contentpath, "r") as srcfile:
  229. code = frappe.utils.cstr(srcfile.read())
  230. if frappe.local.lang != "en":
  231. messages = frappe.get_lang_dict("jsfile", contentpath)
  232. messages = json.dumps(messages)
  233. code += "\n\n$.extend(frappe._messages, {})".format(messages)
  234. out.append(code)
  235. return out