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.
 
 
 
 
 
 

292 line
6.2 KiB

  1. """
  2. Model utilities, unclassified functions
  3. """
  4. def expand(docs):
  5. """
  6. Expand a doclist sent from the client side. (Internally used by the request handler)
  7. """
  8. def xzip(a,b):
  9. d = {}
  10. for i in range(len(a)):
  11. d[a[i]] = b[i]
  12. return d
  13. from webnotes.utils import load_json
  14. docs = load_json(docs)
  15. clist = []
  16. for d in docs['_vl']:
  17. doc = xzip(docs['_kl'][d[0]], d);
  18. clist.append(doc)
  19. return clist
  20. def compress(doclist):
  21. """
  22. Compress a doclist before sending it to the client side. (Internally used by the request handler)
  23. """
  24. if doclist and hasattr(doclist[0],'fields'):
  25. docs = [d.fields for d in doclist]
  26. else:
  27. docs = doclist
  28. kl, vl = {}, []
  29. for d in docs:
  30. dt = d['doctype']
  31. if not (dt in kl.keys()):
  32. fl = d.keys()
  33. forbidden = ['server_code_compiled']
  34. nl = ['doctype','localname','__oldparent','__unsaved']
  35. # add client script for doctype, doctype due to ambiguity
  36. if dt=='DocType': nl.append('__client_script')
  37. for f in fl:
  38. if not (f in nl) and not (f in forbidden):
  39. nl.append(f)
  40. kl[dt] = nl
  41. ## values
  42. fl = kl[dt]
  43. nl = []
  44. for f in fl:
  45. v = d.get(f)
  46. if type(v)==long:
  47. v=int(v)
  48. nl.append(v)
  49. vl.append(nl)
  50. #errprint(str({'_vl':vl,'_kl':kl}))
  51. return {'_vl':vl,'_kl':kl}
  52. def getlist(doclist, field):
  53. """
  54. Filter a list of records for a specific field from the full doclist
  55. Example::
  56. # find all phone call details
  57. dl = getlist(self.doclist, 'contact_updates')
  58. pl = []
  59. for d in dl:
  60. if d.type=='Phone':
  61. pl.append(d)
  62. """
  63. from webnotes.utils import cint
  64. l = []
  65. for d in doclist:
  66. if d.parent and (not d.parent.lower().startswith('old_parent:')) and d.parentfield == field:
  67. l.append(d)
  68. l.sort(lambda a, b: cint(a.idx) - cint(b.idx))
  69. return l
  70. # Copy doclist
  71. # ------------
  72. def copy_doclist(doclist, no_copy = []):
  73. """
  74. Save & return a copy of the given doclist
  75. Pass fields that are not to be copied in `no_copy`
  76. """
  77. from webnotes.model.doc import Document
  78. cl = []
  79. # main doc
  80. c = Document(fielddata = doclist[0].fields.copy())
  81. # clear no_copy fields
  82. for f in no_copy:
  83. if c.fields.has_key(f):
  84. c.fields[f] = None
  85. c.name = None
  86. c.save(1)
  87. cl.append(c)
  88. # new parent name
  89. parent = c.name
  90. # children
  91. for d in doclist[1:]:
  92. c = Document(fielddata = d.fields.copy())
  93. c.name = None
  94. # clear no_copy fields
  95. for f in no_copy:
  96. if c.fields.has_key(f):
  97. c.fields[f] = None
  98. c.parent = parent
  99. c.save(1)
  100. cl.append(c)
  101. return cl
  102. def getvaluelist(doclist, fieldname):
  103. """
  104. Returns a list of values of a particualr fieldname from all Document object in a doclist
  105. """
  106. l = []
  107. for d in doclist:
  108. l.append(d.fields[fieldname])
  109. return l
  110. def _make_html(doc, link_list):
  111. from webnotes.utils import cstr
  112. out = '<table class="simpletable">'
  113. for k in doc.fields.keys():
  114. if k!='server_code_compiled':
  115. v = cstr(doc.fields[k])
  116. # link field
  117. if v and (k in link_list.keys()):
  118. dt = link_list[k]
  119. if type(dt)==str and dt.startswith('link:'):
  120. dt = dt[5:]
  121. v = '<a href="index.cgi?page=Form/%s/%s">%s</a>' % (dt, v, v)
  122. out += '\t<tr><td>%s</td><td>%s</td></tr>\n' % (cstr(k), v)
  123. out += '</table>'
  124. return out
  125. def to_html(doclist):
  126. """
  127. Return a simple HTML format of the doclist
  128. """
  129. out = ''
  130. link_lists = {}
  131. for d in doclist:
  132. if not link_lists.get(d.doctype):
  133. link_lists[d.doctype] = d.make_link_list()
  134. out += _make_html(d, link_lists[d.doctype])
  135. return out
  136. def commonify_doclist(doclist, with_comments=1):
  137. """
  138. Makes a doclist more readable by extracting common properties.
  139. This is used for printing Documents in files
  140. """
  141. from webnotes.utils import get_common_dict, get_diff_dict
  142. def make_common(doclist):
  143. c = {}
  144. if with_comments:
  145. c['##comment'] = 'These values are common in all dictionaries'
  146. for k in common_keys:
  147. c[k] = doclist[0][k]
  148. return c
  149. def strip_common_and_idx(d):
  150. for k in common_keys:
  151. if k in d: del d[k]
  152. if 'idx' in d: del d['idx']
  153. return d
  154. def make_common_dicts(doclist):
  155. common_dict = {} # one per doctype
  156. # make common dicts for all records
  157. for d in doclist:
  158. if not d['doctype'] in common_dict:
  159. d1 = d.copy()
  160. del d1['name']
  161. common_dict[d['doctype']] = d1
  162. else:
  163. common_dict[d['doctype']] = get_common_dict(common_dict[d['doctype']], d)
  164. return common_dict
  165. common_keys = ['owner','docstatus','creation','modified','modified_by']
  166. common_dict = make_common_dicts(doclist)
  167. # make docs
  168. final = []
  169. for d in doclist:
  170. f = strip_common_and_idx(get_diff_dict(common_dict[d['doctype']], d))
  171. f['doctype'] = d['doctype'] # keep doctype!
  172. # strip name for child records (only an auto generated number!)
  173. if f['doctype'] != doclist[0]['doctype']:
  174. del f['name']
  175. if with_comments:
  176. f['##comment'] = d['doctype'] + ('name' in f and (', ' + f['name']) or '')
  177. final.append(f)
  178. # add commons
  179. commons = []
  180. for d in common_dict.values():
  181. d['name']='__common__'
  182. if with_comments:
  183. d['##comment'] = 'These values are common for all ' + d['doctype']
  184. commons.append(strip_common_and_idx(d))
  185. common_values = make_common(doclist)
  186. return [common_values]+commons+final
  187. def uncommonify_doclist(dl):
  188. """
  189. Expands an commonified doclist
  190. """
  191. # first one has common values
  192. common_values = dl[0]
  193. common_dict = {}
  194. final = []
  195. idx_dict = {}
  196. for d in dl[1:]:
  197. if 'name' in d and d['name']=='__common__':
  198. # common for a doctype -
  199. del d['name']
  200. common_dict[d['doctype']] = d
  201. else:
  202. dt = d['doctype']
  203. if not dt in idx_dict: idx_dict[dt] = 0;
  204. d1 = common_values.copy()
  205. # update from common and global
  206. d1.update(common_dict[dt])
  207. d1.update(d)
  208. # idx by sequence
  209. d1['idx'] = idx_dict[dt]
  210. # increment idx
  211. idx_dict[dt] += 1
  212. final.append(d1)
  213. return final
  214. def pprint_doclist(doclist, with_comments = 1):
  215. """
  216. Pretty Prints a doclist with common keys separated and comments
  217. """
  218. from webnotes.utils import pprint_dict
  219. dictlist =[pprint_dict(d) for d in commonify_doclist(doclist, with_comments)]
  220. title = '# '+doclist[0]['doctype']+', '+doclist[0]['name']
  221. return title + '\n[\n' + ',\n'.join(dictlist) + '\n]'
  222. def peval_doclist(txt):
  223. """
  224. Restore a pretty printed doclist
  225. """
  226. if txt.startswith('#'):
  227. return uncommonify_doclist(eval(txt))
  228. else:
  229. return eval(txt)
  230. return uncommonify_doclist(eval(txt))