Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 
 
 

200 linhas
6.4 KiB

  1. // Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com)
  2. //
  3. // MIT License (MIT)
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a
  6. // copy of this software and associated documentation files (the "Software"),
  7. // to deal in the Software without restriction, including without limitation
  8. // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9. // and/or sell copies of the Software, and to permit persons to whom the
  10. // Software is furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  16. // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  17. // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  18. // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  19. // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
  20. // OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. //
  22. wn.ui.form.States = Class.extend({
  23. init: function(opts) {
  24. $.extend(this, opts);
  25. this.state_fieldname = wn.workflow.get_state_fieldname(this.frm.doctype);
  26. // no workflow?
  27. if(!this.state_fieldname)
  28. return;
  29. this.update_fields = wn.workflow.get_update_fields(this.frm.doctype);
  30. var me = this;
  31. $(this.frm.wrapper).bind("render_complete", function() {
  32. me.refresh();
  33. })
  34. },
  35. make: function() {
  36. var parent = this.frm.appframe.$w.find(".title-button-area");
  37. this.workflow_button = $('<button class="btn dropdown-toggle">\
  38. <i class="icon-small"></i> <span class="state-text"></span>\
  39. <span class="caret"></span></button>')
  40. .appendTo(parent).dropdown();
  41. this.dropdown = $('<ul class="dropdown-menu">').insertAfter(this.workflow_button);
  42. this.help_btn = $('<button class="btn"><i class="icon-question-sign"></i></button').
  43. insertBefore(this.workflow_button);
  44. this.setup_help();
  45. this.bind_action();
  46. },
  47. setup_help: function() {
  48. var me = this;
  49. this.help_btn.click(function() {
  50. wn.workflow.setup(me.frm.doctype);
  51. var state = me.get_state();
  52. var d = new wn.ui.Dialog({
  53. title: "Workflow: "
  54. + wn.workflow.workflows[me.frm.doctype].name
  55. })
  56. var next_html = $.map(wn.workflow.get_transitions(me.frm.doctype, state),
  57. function(d) {
  58. return d.action.bold() + wn._(" by Role ") + d.allowed;
  59. }).join(", ") || wn._("None: End of Workflow").bold();
  60. $(d.body).html("<p>"+wn._("Current status")+": " + state.bold() + "</p>"
  61. + "<p>"+wn._("Document is only editable by users of role")+": "
  62. + wn.workflow.get_document_state(me.frm.doctype,
  63. state).allow_edit.bold() + "</p>"
  64. + "<p>"+wn._("Next actions")+": "+ next_html +"</p>"
  65. + (me.frm.doc.__islocal ? ("<div class='alert'>"
  66. +wn._("Workflow will start after saving.")+"</div>") : "")
  67. + "<p class='help'>"+wn._("Note: Other permission rules may also apply")+"</p>"
  68. ).css({padding: '15px'});
  69. d.show();
  70. });
  71. },
  72. refresh: function() {
  73. // hide if its not yet saved
  74. if(this.frm.doc.__islocal) {
  75. this.set_default_state();
  76. return;
  77. }
  78. this.make();
  79. // state text
  80. var state = this.get_state();
  81. if(state) {
  82. // show current state on the button
  83. this.workflow_button.find(".state-text").text(state);
  84. var state_doc = wn.model.get("Workflow State", {name:state})[0];
  85. // set the icon
  86. this.workflow_button.find('i').removeClass()
  87. .addClass("icon-white")
  88. .addClass("icon-" + state_doc.icon);
  89. // set the style
  90. this.workflow_button.removeClass().addClass("btn dropdown-toggle")
  91. if(state_doc && state_doc.style)
  92. this.workflow_button.addClass("btn-" + state_doc.style.toLowerCase());
  93. // show actions from that state
  94. this.show_actions(state);
  95. if(this.frm.doc.__islocal) {
  96. this.workflow_button.attr('disabled', true);
  97. }
  98. }
  99. },
  100. show_actions: function(state) {
  101. var $ul = this.dropdown;
  102. $ul.empty();
  103. $.each(wn.workflow.get_transitions(this.frm.doctype, state), function(i, d) {
  104. if(in_list(user_roles, d.allowed)) {
  105. d.icon = wn.model.get("Workflow State", {name:d.next_state})[0].icon;
  106. $(repl('<li><a href="#" data-action="%(action)s">\
  107. <i class="icon icon-%(icon)s"></i> %(action)s</a></li>', d))
  108. .appendTo($ul);
  109. }
  110. });
  111. // disable the button if user cannot change state
  112. this.workflow_button
  113. .attr('disabled', $ul.find("li").length ? false : true);
  114. },
  115. set_default_state: function() {
  116. var default_state = wn.workflow.get_default_state(this.frm.doctype);
  117. if(default_state) {
  118. this.frm.set_value(this.state_fieldname, default_state);
  119. }
  120. },
  121. get_state: function() {
  122. if(!this.frm.doc[this.state_fieldname]) {
  123. this.set_default_state();
  124. }
  125. return this.frm.doc[this.state_fieldname];
  126. },
  127. bind_action: function() {
  128. var me = this;
  129. this.dropdown.on("click", "[data-action]", function() {
  130. var action = $(this).attr("data-action");
  131. // capture current state
  132. var doc_before_action = copy_dict(me.frm.doc);
  133. // set new state
  134. var next_state = wn.workflow.get_next_state(me.frm.doctype,
  135. me.frm.doc[me.state_fieldname], action);
  136. me.frm.doc[me.state_fieldname] = next_state;
  137. var new_state = wn.workflow.get_document_state(me.frm.doctype, next_state);
  138. var new_docstatus = cint(new_state.doc_status);
  139. // update field and value
  140. if(new_state.update_field) {
  141. me.frm.set_value(new_state.update_field, new_state.update_value);
  142. }
  143. // revert state on error
  144. var on_error = function() {
  145. // reset in locals
  146. locals[me.frm.doctype][me.frm.docname] = doc_before_action;
  147. me.frm.refresh();
  148. }
  149. if(new_docstatus==1 && me.frm.doc.docstatus==0) {
  150. me.frm.savesubmit(null, on_error);
  151. } else if(new_docstatus==0 && me.frm.doc.docstatus==0) {
  152. me.frm.save("Save", null, null, on_error);
  153. } else if(new_docstatus==1 && me.frm.doc.docstatus==1) {
  154. me.frm.save("Update", null, null, on_error);
  155. } else if(new_docstatus==2 && me.frm.doc.docstatus==1) {
  156. me.frm.savecancel(null, on_error);
  157. } else {
  158. msgprint(wn._("Document Status transition from ") + me.frm.doc.docstatus + " "
  159. + wn._("to") +
  160. new_docstatus + " " + wn._("is not allowed."));
  161. return false;
  162. }
  163. // hide dropdown
  164. $(this).parents(".dropdown-menu:first").prev().dropdown('toggle');
  165. return false;
  166. })
  167. }
  168. });