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.
 
 
 
 
 
 

512 lines
14 KiB

  1. // Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
  2. // MIT License. See license.txt
  3. window.get_server_fields = function(method, arg, table_field, doc, dt, dn, allow_edit, call_back) {
  4. console.warn("This function 'get_server_fields' has been deprecated and will be removed soon.");
  5. frappe.dom.freeze();
  6. if($.isPlainObject(arg)) arg = JSON.stringify(arg);
  7. return $c('runserverobj', {'method': method, 'docs': JSON.stringify(doc), 'arg': arg },
  8. function(r, rt) {
  9. frappe.dom.unfreeze();
  10. if (r.message) {
  11. var d = locals[dt][dn];
  12. var field_dict = r.message;
  13. for(var key in field_dict) {
  14. d[key] = field_dict[key];
  15. if (table_field)
  16. refresh_field(key, d.name, table_field);
  17. else
  18. refresh_field(key);
  19. }
  20. }
  21. if(call_back){
  22. doc = locals[doc.doctype][doc.name];
  23. call_back(doc, dt, dn);
  24. }
  25. });
  26. }
  27. window.set_multiple = function (dt, dn, dict, table_field) {
  28. var d = locals[dt][dn];
  29. for(var key in dict) {
  30. d[key] = dict[key];
  31. if (table_field)
  32. refresh_field(key, d.name, table_field);
  33. else
  34. refresh_field(key);
  35. }
  36. }
  37. window.refresh_many = function (flist, dn, table_field) {
  38. for(var i in flist) {
  39. if (table_field)
  40. refresh_field(flist[i], dn, table_field);
  41. else
  42. refresh_field(flist[i]);
  43. }
  44. }
  45. window.set_field_tip = function(n,txt) {
  46. var df = frappe.meta.get_docfield(cur_frm.doctype, n, cur_frm.docname);
  47. if(df)df.description = txt;
  48. if(cur_frm && cur_frm.fields_dict) {
  49. if(cur_frm.fields_dict[n])
  50. cur_frm.fields_dict[n].comment_area.innerHTML = replace_newlines(txt);
  51. else
  52. console.log('[set_field_tip] Unable to set field tip: ' + n);
  53. }
  54. }
  55. refresh_field = function(n, docname, table_field) {
  56. // multiple
  57. if(typeof n==typeof [])
  58. refresh_many(n, docname, table_field);
  59. if (n && typeof n==='string' && table_field){
  60. var grid = cur_frm.fields_dict[table_field].grid,
  61. field = frappe.utils.filter_dict(grid.docfields, {fieldname: n});
  62. if (field && field.length){
  63. field = field[0];
  64. var meta = frappe.meta.get_docfield(field.parent, field.fieldname, docname);
  65. $.extend(field, meta);
  66. if (docname){
  67. cur_frm.fields_dict[table_field].grid.grid_rows_by_docname[docname].refresh_field(n);
  68. } else {
  69. cur_frm.fields_dict[table_field].grid.refresh();
  70. }
  71. }
  72. } else if(cur_frm) {
  73. cur_frm.refresh_field(n)
  74. }
  75. }
  76. window.set_field_options = function(n, txt) {
  77. cur_frm.set_df_property(n, 'options', txt)
  78. }
  79. window.set_field_permlevel = function(n, level) {
  80. cur_frm.set_df_property(n, 'permlevel', level)
  81. }
  82. toggle_field = function(n, hidden) {
  83. var df = frappe.meta.get_docfield(cur_frm.doctype, n, cur_frm.docname);
  84. if(df) {
  85. df.hidden = hidden;
  86. refresh_field(n);
  87. }
  88. else {
  89. console.log((hidden ? "hide_field" : "unhide_field") + " cannot find field " + n);
  90. }
  91. }
  92. hide_field = function(n) {
  93. if(cur_frm) {
  94. if(n.substr) toggle_field(n, 1);
  95. else { for(var i in n) toggle_field(n[i], 1) }
  96. }
  97. }
  98. unhide_field = function(n) {
  99. if(cur_frm) {
  100. if(n.substr) toggle_field(n, 0);
  101. else { for(var i in n) toggle_field(n[i], 0) }
  102. }
  103. }
  104. get_field_obj = function(fn) {
  105. return cur_frm.fields_dict[fn];
  106. }
  107. _f.Frm.prototype.get_doc = function() {
  108. return locals[this.doctype][this.docname];
  109. }
  110. _f.Frm.prototype.set_currency_labels = function(fields_list, currency, parentfield) {
  111. // To set the currency in the label
  112. // For example Total Cost(INR), Total Cost(USD)
  113. var me = this;
  114. var doctype = parentfield ? this.fields_dict[parentfield].grid.doctype : this.doc.doctype;
  115. var field_label_map = {}
  116. var grid_field_label_map = {}
  117. $.each(fields_list, function(i, fname) {
  118. var docfield = frappe.meta.docfield_map[doctype][fname];
  119. if(docfield) {
  120. var label = __(docfield.label || "").replace(/\([^\)]*\)/g, "");
  121. if(parentfield) {
  122. grid_field_label_map[doctype + "-" + fname] =
  123. label.trim() + " (" + __(currency) + ")";
  124. } else {
  125. field_label_map[fname] = label.trim() + " (" + currency + ")";
  126. }
  127. }
  128. });
  129. $.each(field_label_map, function(fname, label) {
  130. me.fields_dict[fname].set_label(label);
  131. });
  132. $.each(grid_field_label_map, function(fname, label) {
  133. fname = fname.split("-");
  134. var df = frappe.meta.get_docfield(fname[0], fname[1], me.doc.name);
  135. if(df) df.label = label;
  136. });
  137. }
  138. _f.Frm.prototype.field_map = function(fnames, fn) {
  139. if(typeof fnames==='string') {
  140. if(fnames == '*') {
  141. fnames = Object.keys(this.fields_dict);
  142. } else {
  143. fnames = [fnames];
  144. }
  145. }
  146. for (var i=0, l=fnames.length; i<l; i++) {
  147. var fieldname = fnames[i];
  148. var field = frappe.meta.get_docfield(cur_frm.doctype, fieldname, this.docname);
  149. if(field) {
  150. fn(field);
  151. this.refresh_field(fieldname);
  152. }
  153. }
  154. }
  155. _f.Frm.prototype.get_docfield = function(fieldname1, fieldname2) {
  156. if(fieldname2) {
  157. // for child
  158. var doctype = this.get_docfield(fieldname1).options;
  159. return frappe.meta.get_docfield(doctype, fieldname2, this.docname);
  160. } else {
  161. // for parent
  162. return frappe.meta.get_docfield(this.doctype, fieldname1, this.docname);
  163. }
  164. }
  165. _f.Frm.prototype.set_df_property = function(fieldname, property, value, docname, table_field) {
  166. if (!docname && !table_field){
  167. var df = this.get_docfield(fieldname);
  168. } else {
  169. var grid = this.fields_dict[table_field].grid,
  170. fname = frappe.utils.filter_dict(grid.docfields, {'fieldname': fieldname});
  171. if (fname && fname.length)
  172. var df = frappe.meta.get_docfield(fname[0].parent, fieldname, docname);
  173. }
  174. if(df && df[property] != value) {
  175. df[property] = value;
  176. refresh_field(fieldname, table_field);
  177. }
  178. }
  179. _f.Frm.prototype.toggle_enable = function(fnames, enable) {
  180. this.field_map(fnames, function(field) {
  181. field.read_only = enable ? 0 : 1; });
  182. }
  183. _f.Frm.prototype.toggle_reqd = function(fnames, mandatory) {
  184. this.field_map(fnames, function(field) { field.reqd = mandatory ? true : false; });
  185. }
  186. _f.Frm.prototype.toggle_display = function(fnames, show) {
  187. this.field_map(fnames, function(field) { field.hidden = show ? 0 : 1; });
  188. }
  189. _f.Frm.prototype.call_server = function(method, args, callback) {
  190. return $c_obj(this.doc, method, args, callback);
  191. }
  192. _f.Frm.prototype.get_files = function() {
  193. return this.attachments
  194. ? frappe.utils.sort(this.attachments.get_attachments(), "file_name", "string")
  195. : [] ;
  196. }
  197. _f.Frm.prototype.set_query = function(fieldname, opt1, opt2) {
  198. if(opt2) {
  199. // on child table
  200. // set_query(fieldname, parent fieldname, query)
  201. this.fields_dict[opt1].grid.get_field(fieldname).get_query = opt2;
  202. } else {
  203. // on parent table
  204. // set_query(fieldname, query)
  205. if(this.fields_dict[fieldname]) {
  206. this.fields_dict[fieldname].get_query = opt1;
  207. }
  208. }
  209. }
  210. _f.Frm.prototype.set_value_if_missing = function(field, value) {
  211. return this.set_value(field, value, true);
  212. }
  213. _f.Frm.prototype.clear_table = function(fieldname) {
  214. frappe.model.clear_table(this.doc, fieldname);
  215. }
  216. _f.Frm.prototype.add_child = function(fieldname, values) {
  217. var doc = frappe.model.add_child(this.doc, frappe.meta.get_docfield(this.doctype, fieldname).options, fieldname);
  218. if(values) {
  219. // Values of unique keys should not be overridden
  220. var d = {};
  221. var unique_keys = ["idx", "name"];
  222. Object.keys(values).map((key) => {
  223. if(!unique_keys.includes(key)) {
  224. d[key] = values[key];
  225. }
  226. });
  227. $.extend(doc, d);
  228. }
  229. return doc;
  230. }
  231. _f.Frm.prototype.set_value = function(field, value, if_missing) {
  232. var me = this;
  233. var _set = function(f, v) {
  234. var fieldobj = me.fields_dict[f];
  235. if(fieldobj) {
  236. if(!if_missing || !frappe.model.has_value(me.doctype, me.doc.name, f)) {
  237. if(fieldobj.df.fieldtype==="Table" && $.isArray(v)) {
  238. frappe.model.clear_table(me.doc, fieldobj.df.fieldname);
  239. for (var i=0, j=v.length; i < j; i++) {
  240. var d = v[i];
  241. var child = frappe.model.add_child(me.doc, fieldobj.df.options,
  242. fieldobj.df.fieldname, i+1);
  243. $.extend(child, d);
  244. }
  245. me.refresh_field(f);
  246. return Promise.resolve();
  247. } else {
  248. return frappe.model.set_value(me.doctype, me.doc.name, f, v);
  249. }
  250. }
  251. } else {
  252. frappe.msgprint(__("Field {0} not found.",[f]));
  253. throw "frm.set_value";
  254. }
  255. }
  256. if(typeof field=="string") {
  257. return _set(field, value)
  258. } else if($.isPlainObject(field)) {
  259. let tasks = [];
  260. for (let f in field) {
  261. let v = field[f];
  262. if(me.get_field(f)) {
  263. tasks.push(() => _set(f, v));
  264. }
  265. }
  266. return frappe.run_serially(tasks);
  267. }
  268. }
  269. _f.Frm.prototype.call = function(opts, args, callback) {
  270. var me = this;
  271. if(typeof opts==='string') {
  272. // called as frm.call('do_this', {with_arg: 'arg'});
  273. opts = {
  274. method: opts,
  275. doc: this.doc,
  276. args: args,
  277. callback: callback
  278. };
  279. }
  280. if(!opts.doc) {
  281. if(opts.method.indexOf(".")===-1)
  282. opts.method = frappe.model.get_server_module_name(me.doctype) + "." + opts.method;
  283. opts.original_callback = opts.callback;
  284. opts.callback = function(r) {
  285. if($.isPlainObject(r.message)) {
  286. if(opts.child) {
  287. // update child doc
  288. opts.child = locals[opts.child.doctype][opts.child.name];
  289. var std_field_list = ["doctype"].concat(frappe.model.std_fields_list);
  290. for (var key in r.message) {
  291. if (std_field_list.indexOf(key)===-1) {
  292. opts.child[key] = r.message[key];
  293. }
  294. }
  295. me.fields_dict[opts.child.parentfield].refresh();
  296. } else {
  297. // update parent doc
  298. me.set_value(r.message);
  299. }
  300. }
  301. opts.original_callback && opts.original_callback(r);
  302. }
  303. } else {
  304. opts.original_callback = opts.callback;
  305. opts.callback = function(r) {
  306. if(!r.exc) me.refresh_fields();
  307. opts.original_callback && opts.original_callback(r);
  308. }
  309. }
  310. return frappe.call(opts);
  311. }
  312. _f.Frm.prototype.get_field = function(field) {
  313. return this.fields_dict[field];
  314. };
  315. _f.Frm.prototype.set_read_only = function() {
  316. var perm = [];
  317. var docperms = frappe.perm.get_perm(this.doc.doctype);
  318. for (var i=0, l=docperms.length; i<l; i++) {
  319. var p = docperms[i];
  320. perm[p.permlevel || 0] = {read:1, print:1, cancel:1};
  321. }
  322. this.perm = perm;
  323. }
  324. _f.Frm.prototype.trigger = function(event) {
  325. return this.script_manager.trigger(event);
  326. };
  327. _f.Frm.prototype.get_formatted = function(fieldname) {
  328. return frappe.format(this.doc[fieldname],
  329. frappe.meta.get_docfield(this.doctype, fieldname, this.docname),
  330. {no_icon:true}, this.doc);
  331. }
  332. _f.Frm.prototype.open_grid_row = function() {
  333. return frappe.ui.form.get_open_grid_form();
  334. }
  335. _f.Frm.prototype.is_new = function() {
  336. return this.doc.__islocal;
  337. }
  338. _f.Frm.prototype.get_title = function() {
  339. if(this.meta.title_field) {
  340. return this.doc[this.meta.title_field];
  341. } else {
  342. return this.doc.name;
  343. }
  344. }
  345. _f.Frm.prototype.get_selected = function() {
  346. // returns list of children that are selected. returns [parentfield, name] for each
  347. var selected = {}, me = this;
  348. frappe.meta.get_table_fields(this.doctype).forEach(function(df) {
  349. var _selected = me.fields_dict[df.fieldname].grid.get_selected();
  350. if(_selected.length) {
  351. selected[df.fieldname] = _selected;
  352. }
  353. });
  354. return selected;
  355. }
  356. _f.Frm.prototype.has_mapper = function() {
  357. // hackalert!
  358. // if open_mapped_doc is mentioned in the custom script, then mapper exists
  359. if(this._has_mapper === undefined) {
  360. this._has_mapper = (this.meta.__js && this.meta.__js.search('open_mapped_doc')!==-1) ?
  361. true: false;
  362. }
  363. return this._has_mapper;
  364. }
  365. _f.Frm.prototype.set_indicator_formatter = function(fieldname, get_color, get_text) {
  366. // get doctype from parent
  367. var doctype;
  368. if(frappe.meta.docfield_map[this.doctype][fieldname]) {
  369. doctype = this.doctype;
  370. } else {
  371. frappe.meta.get_table_fields(this.doctype).every(function(df) {
  372. if(frappe.meta.docfield_map[df.options][fieldname]) {
  373. doctype = df.options;
  374. return false;
  375. } else {
  376. return true;
  377. }
  378. })
  379. }
  380. frappe.meta.docfield_map[doctype][fieldname].formatter =
  381. function(value, df, options, doc) {
  382. if(value) {
  383. return repl('<a class="indicator %(color)s" href="#Form/%(doctype)s/%(name)s">%(label)s</a>', {
  384. color: get_color(doc),
  385. doctype: df.options,
  386. name: value,
  387. label: get_text ? get_text(doc) : value
  388. });
  389. } else {
  390. return '';
  391. }
  392. };
  393. }
  394. _f.Frm.prototype.can_create = function(doctype) {
  395. // return true or false if the user can make a particlar doctype
  396. // will check permission, `can_make_methods` if exists, or will decided on
  397. // basis of whether the document is submittable
  398. if(!frappe.model.can_create(doctype)) {
  399. return false;
  400. }
  401. if(this.custom_make_buttons && this.custom_make_buttons[doctype]) {
  402. // custom buttons are translated and so are the keys
  403. const key = __(this.custom_make_buttons[doctype]);
  404. // if the button is present, then show make
  405. return !!this.custom_buttons[key];
  406. }
  407. if(this.can_make_methods && this.can_make_methods[doctype]) {
  408. return this.can_make_methods[doctype](this);
  409. } else {
  410. if(this.meta.is_submittable && !this.doc.docstatus==1) {
  411. return false;
  412. } else {
  413. return true;
  414. }
  415. }
  416. }
  417. _f.Frm.prototype.make_new = function(doctype) {
  418. // make new doctype from the current form
  419. // will handover to `make_methods` if defined
  420. // or will create and match link fields
  421. var me = this;
  422. if(this.make_methods && this.make_methods[doctype]) {
  423. return this.make_methods[doctype](this);
  424. } else if(this.custom_make_buttons && this.custom_make_buttons[doctype]) {
  425. this.custom_buttons[__(this.custom_make_buttons[doctype])].trigger('click');
  426. } else {
  427. frappe.model.with_doctype(doctype, function() {
  428. var new_doc = frappe.model.get_new_doc(doctype);
  429. // set link fields (if found)
  430. frappe.get_meta(doctype).fields.forEach(function(df) {
  431. if(df.fieldtype==='Link' && df.options===me.doctype) {
  432. new_doc[df.fieldname] = me.doc.name;
  433. }
  434. });
  435. frappe.ui.form.make_quick_entry(doctype, null, null, new_doc);
  436. // frappe.set_route('Form', doctype, new_doc.name);
  437. });
  438. }
  439. }
  440. _f.Frm.prototype.update_in_all_rows = function(table_fieldname, fieldname, value) {
  441. // update the child value in all tables where it is missing
  442. if(!value) return;
  443. var cl = this.doc[table_fieldname] || [];
  444. for(var i = 0; i < cl.length; i++){
  445. if(!cl[i][fieldname]) cl[i][fieldname] = value;
  446. }
  447. refresh_field("items");
  448. }