Merge pull request #9957 from hrwX/multiple_assignments
This commit is contained in:
commit
38ffe0d016
7 changed files with 178 additions and 124 deletions
|
|
@ -44,7 +44,7 @@ class AssignmentRule(Document):
|
|||
user = self.get_user()
|
||||
|
||||
assign_to.add(dict(
|
||||
assign_to = user,
|
||||
assign_to = [user],
|
||||
doctype = doc.get('doctype'),
|
||||
name = doc.get('name'),
|
||||
description = frappe.render_template(self.description, doc),
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ class TestEvent(unittest.TestCase):
|
|||
ev = frappe.get_doc(self.test_records[0]).insert()
|
||||
|
||||
add({
|
||||
"assign_to": "test@example.com",
|
||||
"assign_to": ["test@example.com"],
|
||||
"doctype": "Event",
|
||||
"name": ev.name,
|
||||
"description": "Test Assignment"
|
||||
|
|
@ -83,7 +83,7 @@ class TestEvent(unittest.TestCase):
|
|||
|
||||
# add another one
|
||||
add({
|
||||
"assign_to": self.test_user,
|
||||
"assign_to": [self.test_user],
|
||||
"doctype": "Event",
|
||||
"name": ev.name,
|
||||
"description": "Test Assignment"
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ class TestNotificationLog(unittest.TestCase):
|
|||
user = get_user()
|
||||
|
||||
assign_task({
|
||||
"assign_to": user,
|
||||
"assign_to": [user],
|
||||
"doctype": 'ToDo',
|
||||
"name": todo.name,
|
||||
"description": todo.description
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ from frappe.desk.doctype.notification_log.notification_log import enqueue_create
|
|||
get_title, get_title_html
|
||||
import frappe.utils
|
||||
import frappe.share
|
||||
import json
|
||||
|
||||
class DuplicateToDoError(frappe.ValidationError): pass
|
||||
|
||||
|
|
@ -19,17 +20,17 @@ def get(args=None):
|
|||
if not args:
|
||||
args = frappe.local.form_dict
|
||||
|
||||
return frappe.get_all('ToDo', fields = ['owner', 'description'], filters = dict(
|
||||
return frappe.get_all('ToDo', fields=['owner', 'name'], filters=dict(
|
||||
reference_type = args.get('doctype'),
|
||||
reference_name = args.get('name'),
|
||||
status = ('!=', 'Cancelled')
|
||||
), limit = 5)
|
||||
), limit=5)
|
||||
|
||||
@frappe.whitelist()
|
||||
def add(args=None):
|
||||
"""add in someone's to do list
|
||||
args = {
|
||||
"assign_to": ,
|
||||
"assign_to": [],
|
||||
"doctype": ,
|
||||
"name": ,
|
||||
"description": ,
|
||||
|
|
@ -40,56 +41,68 @@ def add(args=None):
|
|||
if not args:
|
||||
args = frappe.local.form_dict
|
||||
|
||||
if frappe.db.sql("""SELECT `owner`
|
||||
FROM `tabToDo`
|
||||
WHERE `reference_type`=%(doctype)s
|
||||
AND `reference_name`=%(name)s
|
||||
AND `status`='Open'
|
||||
AND `owner`=%(assign_to)s""", args):
|
||||
frappe.throw(_("Already in user's To Do list"), DuplicateToDoError)
|
||||
else:
|
||||
from frappe.utils import nowdate
|
||||
users_with_duplicate_todo = []
|
||||
shared_with_users = []
|
||||
|
||||
if not args.get('description'):
|
||||
args['description'] = _('Assignment for {0} {1}').format(args['doctype'], args['name'])
|
||||
|
||||
d = frappe.get_doc({
|
||||
"doctype":"ToDo",
|
||||
"owner": args['assign_to'],
|
||||
for assign_to in frappe.parse_json(args.get("assign_to")):
|
||||
filters = {
|
||||
"reference_type": args['doctype'],
|
||||
"reference_name": args['name'],
|
||||
"description": args.get('description'),
|
||||
"priority": args.get("priority", "Medium"),
|
||||
"status": "Open",
|
||||
"date": args.get('date', nowdate()),
|
||||
"assigned_by": args.get('assigned_by', frappe.session.user),
|
||||
'assignment_rule': args.get('assignment_rule')
|
||||
}).insert(ignore_permissions=True)
|
||||
"owner": assign_to
|
||||
}
|
||||
|
||||
# set assigned_to if field exists
|
||||
if frappe.get_meta(args['doctype']).get_field("assigned_to"):
|
||||
frappe.db.set_value(args['doctype'], args['name'], "assigned_to", args['assign_to'])
|
||||
if frappe.get_all("ToDo", filters=filters):
|
||||
users_with_duplicate_todo.append(assign_to)
|
||||
else:
|
||||
from frappe.utils import nowdate
|
||||
|
||||
doc = frappe.get_doc(args['doctype'], args['name'])
|
||||
if not args.get('description'):
|
||||
args['description'] = _('Assignment for {0} {1}').format(args['doctype'], args['name'])
|
||||
|
||||
# if assignee does not have permissions, share
|
||||
if not frappe.has_permission(doc=doc, user=args['assign_to']):
|
||||
frappe.share.add(doc.doctype, doc.name, args['assign_to'])
|
||||
frappe.msgprint(_('Shared with user {0} with read access').format(args['assign_to']), alert=True)
|
||||
d = frappe.get_doc({
|
||||
"doctype": "ToDo",
|
||||
"owner": assign_to,
|
||||
"reference_type": args['doctype'],
|
||||
"reference_name": args['name'],
|
||||
"description": args.get('description'),
|
||||
"priority": args.get("priority", "Medium"),
|
||||
"status": "Open",
|
||||
"date": args.get('date', nowdate()),
|
||||
"assigned_by": args.get('assigned_by', frappe.session.user),
|
||||
'assignment_rule': args.get('assignment_rule')
|
||||
}).insert(ignore_permissions=True)
|
||||
|
||||
# make this document followed by assigned user
|
||||
follow_document(args['doctype'], args['name'], args['assign_to'])
|
||||
# set assigned_to if field exists
|
||||
if frappe.get_meta(args['doctype']).get_field("assigned_to"):
|
||||
frappe.db.set_value(args['doctype'], args['name'], "assigned_to", assign_to)
|
||||
|
||||
# notify
|
||||
notify_assignment(d.assigned_by, d.owner, d.reference_type, d.reference_name, action='ASSIGN',\
|
||||
description=args.get("description"))
|
||||
doc = frappe.get_doc(args['doctype'], args['name'])
|
||||
|
||||
# if assignee does not have permissions, share
|
||||
if not frappe.has_permission(doc=doc, user=assign_to):
|
||||
frappe.share.add(doc.doctype, doc.name, assign_to)
|
||||
shared_with_users.append(assign_to)
|
||||
|
||||
# make this document followed by assigned user
|
||||
follow_document(args['doctype'], args['name'], assign_to)
|
||||
|
||||
# notify
|
||||
notify_assignment(d.assigned_by, d.owner, d.reference_type, d.reference_name, action='ASSIGN',
|
||||
description=args.get("description"))
|
||||
|
||||
if shared_with_users:
|
||||
user_list = format_message_for_assign_to(shared_with_users)
|
||||
frappe.msgprint(_("Shared with the following Users with Read access:{0}").format(user_list, alert=True))
|
||||
|
||||
if users_with_duplicate_todo:
|
||||
user_list = format_message_for_assign_to(users_with_duplicate_todo)
|
||||
frappe.msgprint(_("Already in the following Users ToDo list:{0}").format(user_list, alert=True))
|
||||
|
||||
return get(args)
|
||||
|
||||
@frappe.whitelist()
|
||||
def add_multiple(args=None):
|
||||
import json
|
||||
|
||||
if not args:
|
||||
args = frappe.local.form_dict
|
||||
|
||||
|
|
@ -183,3 +196,5 @@ def notify_assignment(assigned_by, owner, doc_type, doc_name, action='CLOSE',
|
|||
|
||||
enqueue_create_notification(owner, notification_doc)
|
||||
|
||||
def format_message_for_assign_to(users):
|
||||
return "<br><br>" + "<br>".join(users)
|
||||
|
|
@ -87,23 +87,17 @@ frappe.ui.form.AssignTo = Class.extend({
|
|||
|
||||
if(!me.assign_to) {
|
||||
me.assign_to = new frappe.ui.form.AssignToDialog({
|
||||
obj: me,
|
||||
method: 'frappe.desk.form.assign_to.add',
|
||||
method: "frappe.desk.form.assign_to.add",
|
||||
doctype: me.frm.doctype,
|
||||
docname: me.frm.docname,
|
||||
callback: function(r) {
|
||||
frm: me.frm,
|
||||
callback: function (r) {
|
||||
me.render(r.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
me.assign_to.dialog.clear();
|
||||
|
||||
if(me.frm.meta.title_field) {
|
||||
me.assign_to.dialog.set_value("description", me.frm.doc[me.frm.meta.title_field])
|
||||
}
|
||||
|
||||
me.assign_to.dialog.show();
|
||||
me.assign_to = null;
|
||||
},
|
||||
remove: function(owner) {
|
||||
var me = this;
|
||||
|
|
@ -130,81 +124,126 @@ frappe.ui.form.AssignTo = Class.extend({
|
|||
|
||||
frappe.ui.form.AssignToDialog = Class.extend({
|
||||
init: function(opts){
|
||||
var me = this
|
||||
var dialog = new frappe.ui.Dialog({
|
||||
title: __('Add to To Do'),
|
||||
fields: [
|
||||
{ fieldtype: 'Link', fieldname: 'assign_to', options: 'User', label: __("Assign To"), reqd: true, filters: { 'user_type': 'System User' }},
|
||||
{ fieldtype: 'Check', fieldname: 'myself', label: __("Assign to me"), "default": 0 },
|
||||
{ fieldtype: 'Small Text', fieldname: 'description', label: __("Comment") },
|
||||
{ fieldtype: 'Section Break' },
|
||||
{ fieldtype: 'Column Break' },
|
||||
{ fieldtype: 'Date', fieldname: 'date', label: __("Complete By") },
|
||||
{ fieldtype: 'Column Break' },
|
||||
{ fieldtype: 'Select', fieldname: 'priority', label: __("Priority"),
|
||||
options: [
|
||||
{ value: 'Low', label: __('Low') },
|
||||
{ value: 'Medium', label: __('Medium') },
|
||||
{ value: 'High', label: __('High') }
|
||||
],
|
||||
// Pick up priority from the source document, if it exists and is available in ToDo
|
||||
'default': ["Low", "Medium", "High"].includes(opts.obj.frm && opts.obj.frm.doc.priority
|
||||
? opts.obj.frm.doc.priority : 'Medium')
|
||||
},
|
||||
],
|
||||
primary_action: function() { frappe.ui.add_assignment(opts, this) },
|
||||
primary_action_label: __("Add")
|
||||
})
|
||||
$.extend(me, dialog);
|
||||
$.extend(this, opts);
|
||||
|
||||
me.dialog = dialog;
|
||||
|
||||
me.dialog.fields_dict.assign_to.get_query = "frappe.core.doctype.user.user.user_query";
|
||||
|
||||
var myself = me.dialog.get_input("myself").on("click", function() {
|
||||
me.toggle_myself(this);
|
||||
});
|
||||
me.toggle_myself(myself);
|
||||
},
|
||||
toggle_myself: function(myself) {
|
||||
var me = this;
|
||||
if($(myself).prop("checked")) {
|
||||
me.dialog.set_value("assign_to", frappe.session.user);
|
||||
me.dialog.get_field("notify").$wrapper.toggle(false);
|
||||
me.dialog.get_field("assign_to").$wrapper.toggle(false);
|
||||
} else {
|
||||
me.dialog.set_value("assign_to", "");
|
||||
me.dialog.get_field("assign_to").$wrapper.toggle(true);
|
||||
}
|
||||
this.make();
|
||||
this.set_description_from_doc();
|
||||
},
|
||||
make: function() {
|
||||
let me = this;
|
||||
|
||||
});
|
||||
me.dialog = new frappe.ui.Dialog({
|
||||
title: __('Add to ToDo'),
|
||||
fields: me.get_fields(),
|
||||
primary_action_label: __("Add"),
|
||||
primary_action: function() {
|
||||
let args = me.dialog.get_values();
|
||||
|
||||
frappe.ui.add_assignment = function(opts, dialog) {
|
||||
var assign_to = dialog.fields_dict.assign_to.get_value();
|
||||
var args = dialog.get_values();
|
||||
if(args && assign_to) {
|
||||
dialog.set_message('Assigning...');
|
||||
return frappe.call({
|
||||
method: opts.method,
|
||||
args: $.extend(args, {
|
||||
doctype: opts.doctype,
|
||||
name: opts.docname,
|
||||
assign_to: assign_to,
|
||||
bulk_assign: opts.bulk_assign || false,
|
||||
re_assign: opts.re_assign || false
|
||||
}),
|
||||
btn: dialog.get_primary_btn(),
|
||||
callback: function(r) {
|
||||
if(!r.exc) {
|
||||
if(opts.callback){
|
||||
opts.callback(r);
|
||||
}
|
||||
dialog && dialog.hide();
|
||||
} else {
|
||||
dialog.clear_message();
|
||||
if (args && args.assign_to) {
|
||||
me.dialog.set_message("Assigning...");
|
||||
|
||||
frappe.call({
|
||||
method: me.method,
|
||||
args: $.extend(args, {
|
||||
doctype: me.doctype,
|
||||
name: me.docname,
|
||||
assign_to: args.assign_to,
|
||||
bulk_assign: me.bulk_assign || false,
|
||||
re_assign: me.re_assign || false
|
||||
}),
|
||||
btn: me.dialog.get_primary_btn(),
|
||||
callback: function(r) {
|
||||
if (!r.exc) {
|
||||
if (me.callback) {
|
||||
me.callback(r);
|
||||
}
|
||||
me.dialog && me.dialog.hide();
|
||||
} else {
|
||||
me.dialog.clear_message();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
assign_to_me: function() {
|
||||
let me = this;
|
||||
let assign_to = [];
|
||||
|
||||
if (me.dialog.get_value("assign_to_me")) {
|
||||
assign_to.push(frappe.session.user);
|
||||
}
|
||||
|
||||
me.dialog.set_value("assign_to", assign_to);
|
||||
},
|
||||
set_description_from_doc: function() {
|
||||
let me = this;
|
||||
|
||||
if (me.frm && me.frm.meta.title_field) {
|
||||
me.dialog.set_value("description", me.frm.doc[me.frm.meta.title_field]);
|
||||
}
|
||||
},
|
||||
get_fields: function() {
|
||||
let me = this;
|
||||
|
||||
return [
|
||||
{
|
||||
fieldtype: 'MultiSelectPills',
|
||||
fieldname: 'assign_to',
|
||||
label: __("Assign To"),
|
||||
reqd: true,
|
||||
get_data: function(txt) {
|
||||
return frappe.db.get_link_options("User", txt, {user_type: "System User", enabled: 1});
|
||||
}
|
||||
},
|
||||
{
|
||||
label: __("Assign to me"),
|
||||
fieldtype: 'Check',
|
||||
fieldname: 'assign_to_me',
|
||||
default: 0,
|
||||
onchange: () => me.assign_to_me()
|
||||
},
|
||||
{
|
||||
label: __("Comment"),
|
||||
fieldtype: 'Small Text',
|
||||
fieldname: 'description'
|
||||
},
|
||||
{
|
||||
fieldtype: 'Section Break'
|
||||
},
|
||||
{
|
||||
fieldtype: 'Column Break'
|
||||
},
|
||||
{
|
||||
label: __("Complete By"),
|
||||
fieldtype: 'Date',
|
||||
fieldname: 'date'
|
||||
},
|
||||
{
|
||||
fieldtype: 'Column Break'
|
||||
},
|
||||
{
|
||||
label: __("Priority"),
|
||||
fieldtype: 'Select',
|
||||
fieldname: 'priority',
|
||||
options: [
|
||||
{
|
||||
value: 'Low',
|
||||
label: __('Low')
|
||||
},
|
||||
{
|
||||
value: 'Medium',
|
||||
label: __('Medium')
|
||||
},
|
||||
{
|
||||
value: 'High',
|
||||
label: __('High')
|
||||
}
|
||||
],
|
||||
// Pick up priority from the source document, if it exists and is available in ToDo
|
||||
default: ["Low", "Medium", "High"].includes(me.frm && me.frm.doc.priority ? me.frm.doc.priority : 'Medium')
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -306,7 +306,7 @@ def get_points(user, point_type='energy_points'):
|
|||
def assign_users_to_todo(todo_name, users):
|
||||
for user in users:
|
||||
assign_to({
|
||||
'assign_to': user,
|
||||
'assign_to': [user],
|
||||
'doctype': 'ToDo',
|
||||
'name': todo_name
|
||||
})
|
||||
|
|
@ -60,7 +60,7 @@ class TestAssign(unittest.TestCase):
|
|||
|
||||
def assign(doc, user):
|
||||
return frappe.desk.form.assign_to.add({
|
||||
"assign_to": user,
|
||||
"assign_to": [user],
|
||||
"doctype": doc.doctype,
|
||||
"name": doc.name,
|
||||
"description": 'test',
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue