mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-01 20:48:27 +00:00
* ci: add prettier to pre-commit
(cherry picked from commit 2c16036ef3)
* style: format js files
---------
Co-authored-by: barredterra <14891507+barredterra@users.noreply.github.com>
Co-authored-by: Ankush Menat <ankush@frappe.io>
This commit is contained in:
@@ -1 +1 @@
|
||||
cur_frm.add_fetch('employee', 'employee_name', 'employee_name');
|
||||
cur_frm.add_fetch("employee", "employee_name", "employee_name");
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
frappe.ui.form.on("Activity Type", {
|
||||
onload: function(frm) {
|
||||
frm.set_currency_labels(["billing_rate", "costing_rate"], frappe.defaults.get_global_default('currency'));
|
||||
onload: function (frm) {
|
||||
frm.set_currency_labels(
|
||||
["billing_rate", "costing_rate"],
|
||||
frappe.defaults.get_global_default("currency")
|
||||
);
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
frm.add_custom_button(__("Activity Cost per Employee"), function() {
|
||||
frappe.route_options = {"activity_type": frm.doc.name};
|
||||
refresh: function (frm) {
|
||||
frm.add_custom_button(__("Activity Cost per Employee"), function () {
|
||||
frappe.route_options = { activity_type: frm.doc.name };
|
||||
frappe.set_route("List", "Activity Cost");
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -3,16 +3,16 @@
|
||||
frappe.ui.form.on("Project", {
|
||||
setup(frm) {
|
||||
frm.make_methods = {
|
||||
'Timesheet': () => {
|
||||
Timesheet: () => {
|
||||
open_form(frm, "Timesheet", "Timesheet Detail", "time_logs");
|
||||
},
|
||||
'Purchase Order': () => {
|
||||
"Purchase Order": () => {
|
||||
open_form(frm, "Purchase Order", "Purchase Order Item", "items");
|
||||
},
|
||||
'Purchase Receipt': () => {
|
||||
"Purchase Receipt": () => {
|
||||
open_form(frm, "Purchase Receipt", "Purchase Receipt Item", "items");
|
||||
},
|
||||
'Purchase Invoice': () => {
|
||||
"Purchase Invoice": () => {
|
||||
open_form(frm, "Purchase Invoice", "Purchase Invoice Item", "items");
|
||||
},
|
||||
};
|
||||
@@ -22,31 +22,31 @@ frappe.ui.form.on("Project", {
|
||||
so.get_route_options_for_new_doc = () => {
|
||||
if (frm.is_new()) return {};
|
||||
return {
|
||||
"customer": frm.doc.customer,
|
||||
"project_name": frm.doc.name
|
||||
customer: frm.doc.customer,
|
||||
project_name: frm.doc.name,
|
||||
};
|
||||
};
|
||||
|
||||
frm.set_query('customer', 'erpnext.controllers.queries.customer_query');
|
||||
frm.set_query("customer", "erpnext.controllers.queries.customer_query");
|
||||
|
||||
frm.set_query("user", "users", function () {
|
||||
return {
|
||||
query: "erpnext.projects.doctype.project.project.get_users_for_project"
|
||||
query: "erpnext.projects.doctype.project.project.get_users_for_project",
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query("department", function (doc) {
|
||||
return {
|
||||
filters: {
|
||||
"company": doc.company,
|
||||
}
|
||||
company: doc.company,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
// sales order
|
||||
frm.set_query('sales_order', function () {
|
||||
frm.set_query("sales_order", function () {
|
||||
var filters = {
|
||||
'project': ["in", frm.doc.__islocal ? [""] : [frm.doc.name, ""]]
|
||||
project: ["in", frm.doc.__islocal ? [""] : [frm.doc.name, ""]],
|
||||
};
|
||||
|
||||
if (frm.doc.customer) {
|
||||
@@ -54,7 +54,7 @@ frappe.ui.form.on("Project", {
|
||||
}
|
||||
|
||||
return {
|
||||
filters: filters
|
||||
filters: filters,
|
||||
};
|
||||
});
|
||||
},
|
||||
@@ -65,108 +65,133 @@ frappe.ui.form.on("Project", {
|
||||
} else {
|
||||
frm.add_web_link("/projects?project=" + encodeURIComponent(frm.doc.name));
|
||||
|
||||
frm.trigger('show_dashboard');
|
||||
frm.trigger("show_dashboard");
|
||||
}
|
||||
frm.trigger("set_custom_buttons");
|
||||
},
|
||||
|
||||
set_custom_buttons: function(frm) {
|
||||
set_custom_buttons: function (frm) {
|
||||
if (!frm.is_new()) {
|
||||
frm.add_custom_button(__('Duplicate Project with Tasks'), () => {
|
||||
frm.events.create_duplicate(frm);
|
||||
}, __("Actions"));
|
||||
frm.add_custom_button(
|
||||
__("Duplicate Project with Tasks"),
|
||||
() => {
|
||||
frm.events.create_duplicate(frm);
|
||||
},
|
||||
__("Actions")
|
||||
);
|
||||
|
||||
frm.add_custom_button(__('Update Total Purchase Cost'), () => {
|
||||
frm.events.update_total_purchase_cost(frm);
|
||||
}, __("Actions"));
|
||||
frm.add_custom_button(
|
||||
__("Update Total Purchase Cost"),
|
||||
() => {
|
||||
frm.events.update_total_purchase_cost(frm);
|
||||
},
|
||||
__("Actions")
|
||||
);
|
||||
|
||||
frm.trigger("set_project_status_button");
|
||||
|
||||
|
||||
if (frappe.model.can_read("Task")) {
|
||||
frm.add_custom_button(__("Gantt Chart"), function () {
|
||||
frappe.route_options = {
|
||||
"project": frm.doc.name
|
||||
};
|
||||
frappe.set_route("List", "Task", "Gantt");
|
||||
}, __("View"));
|
||||
frm.add_custom_button(
|
||||
__("Gantt Chart"),
|
||||
function () {
|
||||
frappe.route_options = {
|
||||
project: frm.doc.name,
|
||||
};
|
||||
frappe.set_route("List", "Task", "Gantt");
|
||||
},
|
||||
__("View")
|
||||
);
|
||||
|
||||
frm.add_custom_button(__("Kanban Board"), () => {
|
||||
frappe.call('erpnext.projects.doctype.project.project.create_kanban_board_if_not_exists', {
|
||||
project: frm.doc.name
|
||||
}).then(() => {
|
||||
frappe.set_route('List', 'Task', 'Kanban', frm.doc.project_name);
|
||||
});
|
||||
}, __("View"));
|
||||
frm.add_custom_button(
|
||||
__("Kanban Board"),
|
||||
() => {
|
||||
frappe
|
||||
.call(
|
||||
"erpnext.projects.doctype.project.project.create_kanban_board_if_not_exists",
|
||||
{
|
||||
project: frm.doc.name,
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
frappe.set_route("List", "Task", "Kanban", frm.doc.project_name);
|
||||
});
|
||||
},
|
||||
__("View")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
|
||||
update_total_purchase_cost: function(frm) {
|
||||
update_total_purchase_cost: function (frm) {
|
||||
frappe.call({
|
||||
method: "erpnext.projects.doctype.project.project.recalculate_project_total_purchase_cost",
|
||||
args: {project: frm.doc.name},
|
||||
args: { project: frm.doc.name },
|
||||
freeze: true,
|
||||
freeze_message: __('Recalculating Purchase Cost against this Project...'),
|
||||
callback: function(r) {
|
||||
freeze_message: __("Recalculating Purchase Cost against this Project..."),
|
||||
callback: function (r) {
|
||||
if (r && !r.exc) {
|
||||
frappe.msgprint(__('Total Purchase Cost has been updated'));
|
||||
frappe.msgprint(__("Total Purchase Cost has been updated"));
|
||||
frm.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
set_project_status_button: function(frm) {
|
||||
frm.add_custom_button(__('Set Project Status'), () => {
|
||||
let d = new frappe.ui.Dialog({
|
||||
"title": __("Set Project Status"),
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "status",
|
||||
"fieldtype": "Select",
|
||||
"label": "Status",
|
||||
"reqd": 1,
|
||||
"options": "Completed\nCancelled",
|
||||
set_project_status_button: function (frm) {
|
||||
frm.add_custom_button(
|
||||
__("Set Project Status"),
|
||||
() => {
|
||||
let d = new frappe.ui.Dialog({
|
||||
title: __("Set Project Status"),
|
||||
fields: [
|
||||
{
|
||||
fieldname: "status",
|
||||
fieldtype: "Select",
|
||||
label: "Status",
|
||||
reqd: 1,
|
||||
options: "Completed\nCancelled",
|
||||
},
|
||||
],
|
||||
primary_action: function () {
|
||||
frm.events.set_status(frm, d.get_values().status);
|
||||
d.hide();
|
||||
},
|
||||
],
|
||||
primary_action: function() {
|
||||
frm.events.set_status(frm, d.get_values().status);
|
||||
d.hide();
|
||||
},
|
||||
primary_action_label: __("Set Project Status")
|
||||
}).show();
|
||||
}, __("Actions"));
|
||||
primary_action_label: __("Set Project Status"),
|
||||
}).show();
|
||||
},
|
||||
__("Actions")
|
||||
);
|
||||
},
|
||||
|
||||
create_duplicate: function(frm) {
|
||||
return new Promise(resolve => {
|
||||
frappe.prompt('Project Name', (data) => {
|
||||
frappe.xcall('erpnext.projects.doctype.project.project.create_duplicate_project',
|
||||
{
|
||||
create_duplicate: function (frm) {
|
||||
return new Promise((resolve) => {
|
||||
frappe.prompt("Project Name", (data) => {
|
||||
frappe
|
||||
.xcall("erpnext.projects.doctype.project.project.create_duplicate_project", {
|
||||
prev_doc: frm.doc,
|
||||
project_name: data.value
|
||||
}).then(() => {
|
||||
frappe.set_route('Form', "Project", data.value);
|
||||
frappe.show_alert(__("Duplicate project has been created"));
|
||||
});
|
||||
project_name: data.value,
|
||||
})
|
||||
.then(() => {
|
||||
frappe.set_route("Form", "Project", data.value);
|
||||
frappe.show_alert(__("Duplicate project has been created"));
|
||||
});
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
set_status: function(frm, status) {
|
||||
frappe.confirm(__('Set Project and all Tasks to status {0}?', [status.bold()]), () => {
|
||||
frappe.xcall('erpnext.projects.doctype.project.project.set_project_status',
|
||||
{project: frm.doc.name, status: status}).then(() => {
|
||||
frm.reload_doc();
|
||||
});
|
||||
set_status: function (frm, status) {
|
||||
frappe.confirm(__("Set Project and all Tasks to status {0}?", [status.bold()]), () => {
|
||||
frappe
|
||||
.xcall("erpnext.projects.doctype.project.project.set_project_status", {
|
||||
project: frm.doc.name,
|
||||
status: status,
|
||||
})
|
||||
.then(() => {
|
||||
frm.reload_doc();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
function open_form(frm, doctype, child_doctype, parentfield) {
|
||||
@@ -184,5 +209,4 @@ function open_form(frm, doctype, child_doctype, parentfield) {
|
||||
|
||||
frappe.ui.form.make_quick_entry(doctype, null, null, new_doc);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
frappe.listview_settings['Project'] = {
|
||||
frappe.listview_settings["Project"] = {
|
||||
add_fields: ["status", "priority", "is_active", "percent_complete", "expected_end_date", "project_name"],
|
||||
filters:[["status","=", "Open"]],
|
||||
get_indicator: function(doc) {
|
||||
if(doc.status=="Open" && doc.percent_complete) {
|
||||
filters: [["status", "=", "Open"]],
|
||||
get_indicator: function (doc) {
|
||||
if (doc.status == "Open" && doc.percent_complete) {
|
||||
return [__("{0}%", [cint(doc.percent_complete)]), "orange", "percent_complete,>,0|status,=,Open"];
|
||||
} else {
|
||||
return [__(doc.status), frappe.utils.guess_colour(doc.status), "status,=," + doc.status];
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,53 +1,63 @@
|
||||
|
||||
QUnit.test("test project", function(assert) {
|
||||
QUnit.test("test project", function (assert) {
|
||||
assert.expect(6);
|
||||
let done = assert.async();
|
||||
var task_title = ["Documentation","Implementation","Testing"];
|
||||
var task_title = ["Documentation", "Implementation", "Testing"];
|
||||
|
||||
// To create a timesheet with different tasks and costs
|
||||
let timesheet = (title,start_time,end_time,bill_rate,cost_rate) => {
|
||||
let timesheet = (title, start_time, end_time, bill_rate, cost_rate) => {
|
||||
return frappe.run_serially([
|
||||
() => frappe.db.get_value('Task', {'subject': title}, 'name'),
|
||||
() => frappe.db.get_value("Task", { subject: title }, "name"),
|
||||
(task) => {
|
||||
// Creating timesheet for a project
|
||||
return frappe.tests.make('Timesheet', [
|
||||
{time_logs:[
|
||||
[
|
||||
{activity_type: 'Communication'},
|
||||
{from_time: start_time},
|
||||
{to_time: end_time},
|
||||
{hours: 2},
|
||||
{project: 'Test App'},
|
||||
{task: task.name},
|
||||
{billable: '1'},
|
||||
{billing_rate: bill_rate},
|
||||
{costing_rate: cost_rate}
|
||||
]
|
||||
]}
|
||||
return frappe.tests.make("Timesheet", [
|
||||
{
|
||||
time_logs: [
|
||||
[
|
||||
{ activity_type: "Communication" },
|
||||
{ from_time: start_time },
|
||||
{ to_time: end_time },
|
||||
{ hours: 2 },
|
||||
{ project: "Test App" },
|
||||
{ task: task.name },
|
||||
{ billable: "1" },
|
||||
{ billing_rate: bill_rate },
|
||||
{ costing_rate: cost_rate },
|
||||
],
|
||||
],
|
||||
},
|
||||
]);
|
||||
},
|
||||
// To check if a correct billable and costing amount is calculated for every task
|
||||
() => {
|
||||
if(title=== 'Documentation')
|
||||
{
|
||||
assert.ok(cur_frm.get_field('total_billable_amount').get_value()==20,
|
||||
'Billable amount for Documentation task is correctly calculated');
|
||||
assert.ok(cur_frm.get_field('total_costing_amount').get_value()==16,
|
||||
'Costing amount for Documentation task is correctly calculated');
|
||||
if (title === "Documentation") {
|
||||
assert.ok(
|
||||
cur_frm.get_field("total_billable_amount").get_value() == 20,
|
||||
"Billable amount for Documentation task is correctly calculated"
|
||||
);
|
||||
assert.ok(
|
||||
cur_frm.get_field("total_costing_amount").get_value() == 16,
|
||||
"Costing amount for Documentation task is correctly calculated"
|
||||
);
|
||||
}
|
||||
if(title=== 'Implementation')
|
||||
{
|
||||
assert.ok(cur_frm.get_field('total_billable_amount').get_value()==40,
|
||||
'Billable amount for Implementation task is correctly calculated');
|
||||
assert.ok(cur_frm.get_field('total_costing_amount').get_value()==32,
|
||||
'Costing amount for Implementation task is correctly calculated');
|
||||
if (title === "Implementation") {
|
||||
assert.ok(
|
||||
cur_frm.get_field("total_billable_amount").get_value() == 40,
|
||||
"Billable amount for Implementation task is correctly calculated"
|
||||
);
|
||||
assert.ok(
|
||||
cur_frm.get_field("total_costing_amount").get_value() == 32,
|
||||
"Costing amount for Implementation task is correctly calculated"
|
||||
);
|
||||
}
|
||||
if(title=== 'Testing')
|
||||
{
|
||||
assert.ok(cur_frm.get_field('total_billable_amount').get_value()==60,
|
||||
'Billable amount for Testing task correctly calculated');
|
||||
assert.ok(cur_frm.get_field('total_costing_amount').get_value()==50,
|
||||
'Costing amount for Testing task is correctly calculated');
|
||||
if (title === "Testing") {
|
||||
assert.ok(
|
||||
cur_frm.get_field("total_billable_amount").get_value() == 60,
|
||||
"Billable amount for Testing task correctly calculated"
|
||||
);
|
||||
assert.ok(
|
||||
cur_frm.get_field("total_costing_amount").get_value() == 50,
|
||||
"Costing amount for Testing task is correctly calculated"
|
||||
);
|
||||
}
|
||||
},
|
||||
]);
|
||||
@@ -55,37 +65,39 @@ QUnit.test("test project", function(assert) {
|
||||
frappe.run_serially([
|
||||
() => {
|
||||
// Creating project with task
|
||||
return frappe.tests.make('Project', [
|
||||
{ project_name: 'Test App'},
|
||||
{ expected_start_date: '2017-07-22'},
|
||||
{ expected_end_date: '2017-09-22'},
|
||||
{ estimated_costing: '10,000.00'},
|
||||
{ tasks:[
|
||||
[
|
||||
{title: 'Documentation'},
|
||||
{start_date: '2017-07-24'},
|
||||
{end_date: '2017-07-31'},
|
||||
{description: 'To make a proper documentation defining requirements etc'}
|
||||
return frappe.tests.make("Project", [
|
||||
{ project_name: "Test App" },
|
||||
{ expected_start_date: "2017-07-22" },
|
||||
{ expected_end_date: "2017-09-22" },
|
||||
{ estimated_costing: "10,000.00" },
|
||||
{
|
||||
tasks: [
|
||||
[
|
||||
{ title: "Documentation" },
|
||||
{ start_date: "2017-07-24" },
|
||||
{ end_date: "2017-07-31" },
|
||||
{ description: "To make a proper documentation defining requirements etc" },
|
||||
],
|
||||
[
|
||||
{ title: "Implementation" },
|
||||
{ start_date: "2017-08-01" },
|
||||
{ end_date: "2017-08-01" },
|
||||
{ description: "Writing algorithms and to code the functionalities" },
|
||||
],
|
||||
[
|
||||
{ title: "Testing" },
|
||||
{ start_date: "2017-08-01" },
|
||||
{ end_date: "2017-08-15" },
|
||||
{ description: "To make the test cases and test the functionalities" },
|
||||
],
|
||||
],
|
||||
[
|
||||
{title: 'Implementation'},
|
||||
{start_date: '2017-08-01'},
|
||||
{end_date: '2017-08-01'},
|
||||
{description: 'Writing algorithms and to code the functionalities'}
|
||||
],
|
||||
[
|
||||
{title: 'Testing'},
|
||||
{start_date: '2017-08-01'},
|
||||
{end_date: '2017-08-15'},
|
||||
{description: 'To make the test cases and test the functionalities'}
|
||||
]
|
||||
]}
|
||||
},
|
||||
]);
|
||||
},
|
||||
// Creating Timesheet with different tasks
|
||||
() => timesheet(task_title[0],'2017-07-24 13:00:00','2017-07-24 13:00:00',10,8),
|
||||
() => timesheet(task_title[1],'2017-07-25 13:00:00','2017-07-25 15:00:00',20,16),
|
||||
() => timesheet(task_title[2],'2017-07-26 13:00:00','2017-07-26 15:00:00',30,25),
|
||||
() => done()
|
||||
() => timesheet(task_title[0], "2017-07-24 13:00:00", "2017-07-24 13:00:00", 10, 8),
|
||||
() => timesheet(task_title[1], "2017-07-25 13:00:00", "2017-07-25 15:00:00", 20, 16),
|
||||
() => timesheet(task_title[2], "2017-07-26 13:00:00", "2017-07-26 15:00:00", 30, 25),
|
||||
() => done(),
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Project Template', {
|
||||
frappe.ui.form.on("Project Template", {
|
||||
// refresh: function(frm) {
|
||||
|
||||
// }
|
||||
@@ -9,19 +9,19 @@ frappe.ui.form.on('Project Template', {
|
||||
frm.set_query("task", "tasks", function () {
|
||||
return {
|
||||
filters: {
|
||||
"is_template": 1
|
||||
}
|
||||
is_template: 1,
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
frappe.ui.form.on('Project Template Task', {
|
||||
frappe.ui.form.on("Project Template Task", {
|
||||
task: function (frm, cdt, cdn) {
|
||||
var row = locals[cdt][cdn];
|
||||
frappe.db.get_value("Task", row.task, "subject", (value) => {
|
||||
row.subject = value.subject;
|
||||
refresh_field("tasks");
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Project Type', {
|
||||
|
||||
});
|
||||
frappe.ui.form.on("Project Type", {});
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Project Update', {
|
||||
refresh: function() {
|
||||
|
||||
},
|
||||
frappe.ui.form.on("Project Update", {
|
||||
refresh: function () {},
|
||||
|
||||
onload: function (frm) {
|
||||
frm.set_value("naming_series", "UPDATE-.project.-.YY.MM.DD.-.####");
|
||||
@@ -13,5 +11,5 @@ frappe.ui.form.on('Project Update', {
|
||||
validate: function (frm) {
|
||||
frm.set_value("time", frappe.datetime.now_time());
|
||||
frm.set_value("date", frappe.datetime.nowdate());
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Projects Settings', {
|
||||
refresh: function(frm) {
|
||||
|
||||
}
|
||||
frappe.ui.form.on("Projects Settings", {
|
||||
refresh: function (frm) {},
|
||||
});
|
||||
|
||||
@@ -6,33 +6,34 @@ frappe.provide("erpnext.projects");
|
||||
frappe.ui.form.on("Task", {
|
||||
setup: function (frm) {
|
||||
frm.make_methods = {
|
||||
'Timesheet': () => frappe.model.open_mapped_doc({
|
||||
method: 'erpnext.projects.doctype.task.task.make_timesheet',
|
||||
frm: frm
|
||||
})
|
||||
}
|
||||
Timesheet: () =>
|
||||
frappe.model.open_mapped_doc({
|
||||
method: "erpnext.projects.doctype.task.task.make_timesheet",
|
||||
frm: frm,
|
||||
}),
|
||||
};
|
||||
},
|
||||
|
||||
onload: function (frm) {
|
||||
frm.set_query("task", "depends_on", function () {
|
||||
let filters = {
|
||||
name: ["!=", frm.doc.name]
|
||||
name: ["!=", frm.doc.name],
|
||||
};
|
||||
if (frm.doc.project) filters["project"] = frm.doc.project;
|
||||
return {
|
||||
filters: filters
|
||||
filters: filters,
|
||||
};
|
||||
})
|
||||
});
|
||||
|
||||
frm.set_query("parent_task", function () {
|
||||
let filters = {
|
||||
"is_group": 1,
|
||||
"name": ["!=", frm.doc.name]
|
||||
is_group: 1,
|
||||
name: ["!=", frm.doc.name],
|
||||
};
|
||||
if (frm.doc.project) filters["project"] = frm.doc.project;
|
||||
return {
|
||||
filters: filters
|
||||
}
|
||||
filters: filters,
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
@@ -40,22 +41,22 @@ frappe.ui.form.on("Task", {
|
||||
frappe.call({
|
||||
method: "erpnext.projects.doctype.task.task.check_if_child_exists",
|
||||
args: {
|
||||
name: frm.doc.name
|
||||
name: frm.doc.name,
|
||||
},
|
||||
callback: function (r) {
|
||||
if (r.message.length > 0) {
|
||||
let message = __('Cannot convert Task to non-group because the following child Tasks exist: {0}.',
|
||||
let message = __(
|
||||
"Cannot convert Task to non-group because the following child Tasks exist: {0}.",
|
||||
[r.message.join(", ")]
|
||||
);
|
||||
frappe.msgprint(message);
|
||||
frm.reload_doc();
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
validate: function (frm) {
|
||||
frm.doc.project && frappe.model.remove_from_locals("Project",
|
||||
frm.doc.project);
|
||||
}
|
||||
frm.doc.project && frappe.model.remove_from_locals("Project", frm.doc.project);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -3,21 +3,21 @@
|
||||
|
||||
frappe.views.calendar["Task"] = {
|
||||
field_map: {
|
||||
"start": "exp_start_date",
|
||||
"end": "exp_end_date",
|
||||
"id": "name",
|
||||
"title": "subject",
|
||||
"allDay": "allDay",
|
||||
"progress": "progress"
|
||||
start: "exp_start_date",
|
||||
end: "exp_end_date",
|
||||
id: "name",
|
||||
title: "subject",
|
||||
allDay: "allDay",
|
||||
progress: "progress",
|
||||
},
|
||||
gantt: true,
|
||||
filters: [
|
||||
{
|
||||
"fieldtype": "Link",
|
||||
"fieldname": "project",
|
||||
"options": "Project",
|
||||
"label": __("Project")
|
||||
}
|
||||
fieldtype: "Link",
|
||||
fieldname: "project",
|
||||
options: "Project",
|
||||
label: __("Project"),
|
||||
},
|
||||
],
|
||||
get_events_method: "frappe.desk.calendar.get_events"
|
||||
}
|
||||
get_events_method: "frappe.desk.calendar.get_events",
|
||||
};
|
||||
|
||||
@@ -1,28 +1,36 @@
|
||||
frappe.listview_settings['Task'] = {
|
||||
add_fields: ["project", "status", "priority", "exp_start_date",
|
||||
"exp_end_date", "subject", "progress", "depends_on_tasks"],
|
||||
frappe.listview_settings["Task"] = {
|
||||
add_fields: [
|
||||
"project",
|
||||
"status",
|
||||
"priority",
|
||||
"exp_start_date",
|
||||
"exp_end_date",
|
||||
"subject",
|
||||
"progress",
|
||||
"depends_on_tasks",
|
||||
],
|
||||
filters: [["status", "=", "Open"]],
|
||||
onload: function(listview) {
|
||||
onload: function (listview) {
|
||||
var method = "erpnext.projects.doctype.task.task.set_multiple_status";
|
||||
|
||||
listview.page.add_menu_item(__("Set as Open"), function() {
|
||||
listview.call_for_selected_items(method, {"status": "Open"});
|
||||
listview.page.add_menu_item(__("Set as Open"), function () {
|
||||
listview.call_for_selected_items(method, { status: "Open" });
|
||||
});
|
||||
|
||||
listview.page.add_menu_item(__("Set as Completed"), function() {
|
||||
listview.call_for_selected_items(method, {"status": "Completed"});
|
||||
listview.page.add_menu_item(__("Set as Completed"), function () {
|
||||
listview.call_for_selected_items(method, { status: "Completed" });
|
||||
});
|
||||
},
|
||||
get_indicator: function(doc) {
|
||||
get_indicator: function (doc) {
|
||||
var colors = {
|
||||
"Open": "orange",
|
||||
"Overdue": "red",
|
||||
Open: "orange",
|
||||
Overdue: "red",
|
||||
"Pending Review": "orange",
|
||||
"Working": "orange",
|
||||
"Completed": "green",
|
||||
"Cancelled": "dark grey",
|
||||
"Template": "blue"
|
||||
}
|
||||
Working: "orange",
|
||||
Completed: "green",
|
||||
Cancelled: "dark grey",
|
||||
Template: "blue",
|
||||
};
|
||||
return [__(doc.status), colors[doc.status], "status,=," + doc.status];
|
||||
},
|
||||
gantt_custom_popup_html: function (ganttobj, task) {
|
||||
|
||||
@@ -1,84 +1,88 @@
|
||||
frappe.provide("frappe.treeview_settings");
|
||||
|
||||
frappe.treeview_settings['Task'] = {
|
||||
frappe.treeview_settings["Task"] = {
|
||||
get_tree_nodes: "erpnext.projects.doctype.task.task.get_children",
|
||||
add_tree_node: "erpnext.projects.doctype.task.task.add_node",
|
||||
filters: [
|
||||
{
|
||||
fieldname: "project",
|
||||
fieldtype:"Link",
|
||||
fieldtype: "Link",
|
||||
options: "Project",
|
||||
label: __("Project"),
|
||||
},
|
||||
{
|
||||
fieldname: "task",
|
||||
fieldtype:"Link",
|
||||
fieldtype: "Link",
|
||||
options: "Task",
|
||||
label: __("Task"),
|
||||
get_query: function() {
|
||||
var me = frappe.treeview_settings['Task'];
|
||||
get_query: function () {
|
||||
var me = frappe.treeview_settings["Task"];
|
||||
var project = me.page.fields_dict.project.get_value();
|
||||
var args = [["Task", 'is_group', '=', 1]];
|
||||
if(project){
|
||||
args.push(["Task", 'project', "=", project]);
|
||||
var args = [["Task", "is_group", "=", 1]];
|
||||
if (project) {
|
||||
args.push(["Task", "project", "=", project]);
|
||||
}
|
||||
return {
|
||||
filters: args
|
||||
filters: args,
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
breadcrumb: "Projects",
|
||||
get_tree_root: false,
|
||||
root_label: "All Tasks",
|
||||
ignore_fields: ["parent_task"],
|
||||
onload: function(me) {
|
||||
frappe.treeview_settings['Task'].page = {};
|
||||
$.extend(frappe.treeview_settings['Task'].page, me.page);
|
||||
onload: function (me) {
|
||||
frappe.treeview_settings["Task"].page = {};
|
||||
$.extend(frappe.treeview_settings["Task"].page, me.page);
|
||||
me.make_tree();
|
||||
},
|
||||
toolbar: [
|
||||
{
|
||||
label:__("Add Multiple"),
|
||||
condition: function(node) {
|
||||
label: __("Add Multiple"),
|
||||
condition: function (node) {
|
||||
return node.expandable;
|
||||
},
|
||||
click: function(node) {
|
||||
click: function (node) {
|
||||
this.data = [];
|
||||
const dialog = new frappe.ui.Dialog({
|
||||
title: __("Add Multiple Tasks"),
|
||||
fields: [
|
||||
{
|
||||
fieldname: "multiple_tasks", fieldtype: "Table",
|
||||
in_place_edit: true, data: this.data,
|
||||
fieldname: "multiple_tasks",
|
||||
fieldtype: "Table",
|
||||
in_place_edit: true,
|
||||
data: this.data,
|
||||
get_data: () => {
|
||||
return this.data;
|
||||
},
|
||||
fields: [{
|
||||
fieldtype:'Data',
|
||||
fieldname:"subject",
|
||||
in_list_view: 1,
|
||||
reqd: 1,
|
||||
label: __("Subject")
|
||||
}]
|
||||
fields: [
|
||||
{
|
||||
fieldtype: "Data",
|
||||
fieldname: "subject",
|
||||
in_list_view: 1,
|
||||
reqd: 1,
|
||||
label: __("Subject"),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
primary_action: function() {
|
||||
primary_action: function () {
|
||||
dialog.hide();
|
||||
return frappe.call({
|
||||
method: "erpnext.projects.doctype.task.task.add_multiple_tasks",
|
||||
args: {
|
||||
data: dialog.get_values()["multiple_tasks"],
|
||||
parent: node.data.value
|
||||
parent: node.data.value,
|
||||
},
|
||||
callback: function() { }
|
||||
callback: function () {},
|
||||
});
|
||||
},
|
||||
primary_action_label: __('Create')
|
||||
primary_action_label: __("Create"),
|
||||
});
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
extend_toolbar: true
|
||||
extend_toolbar: true,
|
||||
};
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Task Type', {
|
||||
frappe.ui.form.on("Task Type", {
|
||||
// refresh: function(frm) {
|
||||
|
||||
// }
|
||||
});
|
||||
|
||||
@@ -2,39 +2,39 @@
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.ui.form.on("Timesheet", {
|
||||
setup: function(frm) {
|
||||
setup: function (frm) {
|
||||
frappe.require("/assets/erpnext/js/projects/timer.js");
|
||||
|
||||
frm.ignore_doctypes_on_cancel_all = ['Sales Invoice'];
|
||||
frm.ignore_doctypes_on_cancel_all = ["Sales Invoice"];
|
||||
|
||||
frm.fields_dict.employee.get_query = function() {
|
||||
frm.fields_dict.employee.get_query = function () {
|
||||
return {
|
||||
filters:{
|
||||
'status': 'Active'
|
||||
}
|
||||
filters: {
|
||||
status: "Active",
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
frm.fields_dict['time_logs'].grid.get_field('task').get_query = function(frm, cdt, cdn) {
|
||||
frm.fields_dict["time_logs"].grid.get_field("task").get_query = function (frm, cdt, cdn) {
|
||||
var child = locals[cdt][cdn];
|
||||
return{
|
||||
return {
|
||||
filters: {
|
||||
'project': child.project,
|
||||
'status': ["!=", "Cancelled"]
|
||||
}
|
||||
project: child.project,
|
||||
status: ["!=", "Cancelled"],
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
frm.fields_dict['time_logs'].grid.get_field('project').get_query = function() {
|
||||
return{
|
||||
frm.fields_dict["time_logs"].grid.get_field("project").get_query = function () {
|
||||
return {
|
||||
filters: {
|
||||
'company': frm.doc.company
|
||||
}
|
||||
company: frm.doc.company,
|
||||
},
|
||||
};
|
||||
};
|
||||
},
|
||||
|
||||
onload: function(frm) {
|
||||
onload: function (frm) {
|
||||
if (frm.doc.__islocal && frm.doc.time_logs) {
|
||||
calculate_time_and_amount(frm);
|
||||
}
|
||||
@@ -44,33 +44,32 @@ frappe.ui.form.on("Timesheet", {
|
||||
}
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
refresh: function (frm) {
|
||||
if (frm.doc.docstatus == 1) {
|
||||
if (
|
||||
(frm.doc.per_billed < 100)
|
||||
&& (frm.doc.total_billable_hours)
|
||||
&& (frm.doc.total_billable_hours > frm.doc.total_billed_hours)
|
||||
frm.doc.per_billed < 100 &&
|
||||
frm.doc.total_billable_hours &&
|
||||
frm.doc.total_billable_hours > frm.doc.total_billed_hours
|
||||
) {
|
||||
frm.add_custom_button(__("Create Sales Invoice"), function() {
|
||||
frm.add_custom_button(__("Create Sales Invoice"), function () {
|
||||
frm.trigger("make_invoice");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (frm.doc.docstatus < 1) {
|
||||
|
||||
let button = 'Start Timer';
|
||||
$.each(frm.doc.time_logs || [], function(i, row) {
|
||||
if ((row.from_time <= frappe.datetime.now_datetime()) && !row.completed) {
|
||||
button = 'Resume Timer';
|
||||
let button = "Start Timer";
|
||||
$.each(frm.doc.time_logs || [], function (i, row) {
|
||||
if (row.from_time <= frappe.datetime.now_datetime() && !row.completed) {
|
||||
button = "Resume Timer";
|
||||
}
|
||||
});
|
||||
|
||||
frm.add_custom_button(__(button), function() {
|
||||
frm.add_custom_button(__(button), function () {
|
||||
var flag = true;
|
||||
$.each(frm.doc.time_logs || [], function(i, row) {
|
||||
$.each(frm.doc.time_logs || [], function (i, row) {
|
||||
// Fetch the row for which from_time is not present
|
||||
if (flag && row.activity_type && !row.from_time){
|
||||
if (flag && row.activity_type && !row.from_time) {
|
||||
erpnext.timesheet.timer(frm, row);
|
||||
row.from_time = frappe.datetime.now_datetime();
|
||||
frm.refresh_fields("time_logs");
|
||||
@@ -79,7 +78,10 @@ frappe.ui.form.on("Timesheet", {
|
||||
}
|
||||
// Fetch the row for timer where activity is not completed and from_time is before now_time
|
||||
if (flag && row.from_time <= frappe.datetime.now_datetime() && !row.completed) {
|
||||
let timestamp = moment(frappe.datetime.now_datetime()).diff(moment(row.from_time),"seconds");
|
||||
let timestamp = moment(frappe.datetime.now_datetime()).diff(
|
||||
moment(row.from_time),
|
||||
"seconds"
|
||||
);
|
||||
erpnext.timesheet.timer(frm, row, timestamp);
|
||||
flag = false;
|
||||
}
|
||||
@@ -90,152 +92,177 @@ frappe.ui.form.on("Timesheet", {
|
||||
}
|
||||
}).addClass("btn-primary");
|
||||
}
|
||||
if(frm.doc.per_billed > 0) {
|
||||
if (frm.doc.per_billed > 0) {
|
||||
frm.fields_dict["time_logs"].grid.toggle_enable("billing_hours", false);
|
||||
frm.fields_dict["time_logs"].grid.toggle_enable("is_billable", false);
|
||||
}
|
||||
|
||||
let filters = {
|
||||
"status": "Open"
|
||||
status: "Open",
|
||||
};
|
||||
|
||||
if (frm.doc.customer) {
|
||||
filters["customer"] = frm.doc.customer;
|
||||
}
|
||||
|
||||
frm.set_query('parent_project', function(doc) {
|
||||
frm.set_query("parent_project", function (doc) {
|
||||
return {
|
||||
filters: filters
|
||||
filters: filters,
|
||||
};
|
||||
});
|
||||
|
||||
frm.trigger('setup_filters');
|
||||
frm.trigger('set_dynamic_field_label');
|
||||
frm.trigger('set_route_options_for_new_task');
|
||||
frm.trigger("setup_filters");
|
||||
frm.trigger("set_dynamic_field_label");
|
||||
frm.trigger("set_route_options_for_new_task");
|
||||
},
|
||||
|
||||
customer: function(frm) {
|
||||
frm.set_query('project', 'time_logs', function(doc) {
|
||||
customer: function (frm) {
|
||||
frm.set_query("project", "time_logs", function (doc) {
|
||||
return {
|
||||
filters: {
|
||||
"customer": doc.customer
|
||||
}
|
||||
customer: doc.customer,
|
||||
},
|
||||
};
|
||||
});
|
||||
frm.refresh();
|
||||
},
|
||||
|
||||
currency: function(frm) {
|
||||
let base_currency = frappe.defaults.get_global_default('currency');
|
||||
if (frm.doc.currency && (base_currency != frm.doc.currency)) {
|
||||
currency: function (frm) {
|
||||
let base_currency = frappe.defaults.get_global_default("currency");
|
||||
if (frm.doc.currency && base_currency != frm.doc.currency) {
|
||||
frappe.call({
|
||||
method: "erpnext.setup.utils.get_exchange_rate",
|
||||
args: {
|
||||
from_currency: frm.doc.currency,
|
||||
to_currency: base_currency
|
||||
to_currency: base_currency,
|
||||
},
|
||||
callback: function(r) {
|
||||
callback: function (r) {
|
||||
if (r.message) {
|
||||
frm.set_value('exchange_rate', flt(r.message));
|
||||
frm.set_df_property("exchange_rate", "description", "1 " + frm.doc.currency + " = [?] " + base_currency);
|
||||
frm.set_value("exchange_rate", flt(r.message));
|
||||
frm.set_df_property(
|
||||
"exchange_rate",
|
||||
"description",
|
||||
"1 " + frm.doc.currency + " = [?] " + base_currency
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
frm.trigger('set_dynamic_field_label');
|
||||
frm.trigger("set_dynamic_field_label");
|
||||
},
|
||||
|
||||
exchange_rate: function(frm) {
|
||||
$.each(frm.doc.time_logs, function(i, d) {
|
||||
exchange_rate: function (frm) {
|
||||
$.each(frm.doc.time_logs, function (i, d) {
|
||||
calculate_billing_costing_amount(frm, d.doctype, d.name);
|
||||
});
|
||||
calculate_time_and_amount(frm);
|
||||
},
|
||||
|
||||
set_dynamic_field_label: function(frm) {
|
||||
let base_currency = frappe.defaults.get_global_default('currency');
|
||||
frm.set_currency_labels(["base_total_costing_amount", "base_total_billable_amount", "base_total_billed_amount"], base_currency);
|
||||
frm.set_currency_labels(["total_costing_amount", "total_billable_amount", "total_billed_amount"], frm.doc.currency);
|
||||
set_dynamic_field_label: function (frm) {
|
||||
let base_currency = frappe.defaults.get_global_default("currency");
|
||||
frm.set_currency_labels(
|
||||
["base_total_costing_amount", "base_total_billable_amount", "base_total_billed_amount"],
|
||||
base_currency
|
||||
);
|
||||
frm.set_currency_labels(
|
||||
["total_costing_amount", "total_billable_amount", "total_billed_amount"],
|
||||
frm.doc.currency
|
||||
);
|
||||
|
||||
frm.toggle_display(["base_total_costing_amount", "base_total_billable_amount", "base_total_billed_amount"],
|
||||
frm.doc.currency != base_currency);
|
||||
frm.toggle_display(
|
||||
["base_total_costing_amount", "base_total_billable_amount", "base_total_billed_amount"],
|
||||
frm.doc.currency != base_currency
|
||||
);
|
||||
|
||||
if (frm.doc.time_logs.length > 0) {
|
||||
frm.set_currency_labels(["base_billing_rate", "base_billing_amount", "base_costing_rate", "base_costing_amount"], base_currency, "time_logs");
|
||||
frm.set_currency_labels(["billing_rate", "billing_amount", "costing_rate", "costing_amount"], frm.doc.currency, "time_logs");
|
||||
frm.set_currency_labels(
|
||||
["base_billing_rate", "base_billing_amount", "base_costing_rate", "base_costing_amount"],
|
||||
base_currency,
|
||||
"time_logs"
|
||||
);
|
||||
frm.set_currency_labels(
|
||||
["billing_rate", "billing_amount", "costing_rate", "costing_amount"],
|
||||
frm.doc.currency,
|
||||
"time_logs"
|
||||
);
|
||||
|
||||
let time_logs_grid = frm.fields_dict.time_logs.grid;
|
||||
$.each(["base_billing_rate", "base_billing_amount", "base_costing_rate", "base_costing_amount"], function(i, d) {
|
||||
if (frappe.meta.get_docfield(time_logs_grid.doctype, d))
|
||||
time_logs_grid.set_column_disp(d, frm.doc.currency != base_currency);
|
||||
});
|
||||
$.each(
|
||||
["base_billing_rate", "base_billing_amount", "base_costing_rate", "base_costing_amount"],
|
||||
function (i, d) {
|
||||
if (frappe.meta.get_docfield(time_logs_grid.doctype, d))
|
||||
time_logs_grid.set_column_disp(d, frm.doc.currency != base_currency);
|
||||
}
|
||||
);
|
||||
}
|
||||
frm.refresh_fields();
|
||||
},
|
||||
|
||||
set_route_options_for_new_task: (frm) => {
|
||||
let task_field = frm.get_docfield('time_logs', 'task');
|
||||
let task_field = frm.get_docfield("time_logs", "task");
|
||||
|
||||
if (task_field) {
|
||||
task_field.get_route_options_for_new_doc = (row) => ({'project': row.doc.project});
|
||||
task_field.get_route_options_for_new_doc = (row) => ({ project: row.doc.project });
|
||||
}
|
||||
},
|
||||
|
||||
make_invoice: function(frm) {
|
||||
let fields = [{
|
||||
"fieldtype": "Link",
|
||||
"label": __("Item Code"),
|
||||
"fieldname": "item_code",
|
||||
"options": "Item"
|
||||
}];
|
||||
make_invoice: function (frm) {
|
||||
let fields = [
|
||||
{
|
||||
fieldtype: "Link",
|
||||
label: __("Item Code"),
|
||||
fieldname: "item_code",
|
||||
options: "Item",
|
||||
},
|
||||
];
|
||||
|
||||
if (!frm.doc.customer) {
|
||||
fields.push({
|
||||
"fieldtype": "Link",
|
||||
"label": __("Customer"),
|
||||
"fieldname": "customer",
|
||||
"options": "Customer",
|
||||
"default": frm.doc.customer
|
||||
fieldtype: "Link",
|
||||
label: __("Customer"),
|
||||
fieldname: "customer",
|
||||
options: "Customer",
|
||||
default: frm.doc.customer,
|
||||
});
|
||||
}
|
||||
|
||||
let dialog = new frappe.ui.Dialog({
|
||||
title: __("Create Sales Invoice"),
|
||||
fields: fields
|
||||
fields: fields,
|
||||
});
|
||||
|
||||
dialog.set_primary_action(__('Create Sales Invoice'), () => {
|
||||
dialog.set_primary_action(__("Create Sales Invoice"), () => {
|
||||
var args = dialog.get_values();
|
||||
if(!args) return;
|
||||
if (!args) return;
|
||||
dialog.hide();
|
||||
return frappe.call({
|
||||
type: "GET",
|
||||
method: "erpnext.projects.doctype.timesheet.timesheet.make_sales_invoice",
|
||||
args: {
|
||||
"source_name": frm.doc.name,
|
||||
"item_code": args.item_code,
|
||||
"customer": frm.doc.customer || args.customer,
|
||||
"currency": frm.doc.currency
|
||||
source_name: frm.doc.name,
|
||||
item_code: args.item_code,
|
||||
customer: frm.doc.customer || args.customer,
|
||||
currency: frm.doc.currency,
|
||||
},
|
||||
freeze: true,
|
||||
callback: function(r) {
|
||||
if(!r.exc) {
|
||||
callback: function (r) {
|
||||
if (!r.exc) {
|
||||
frappe.model.sync(r.message);
|
||||
frappe.set_route("Form", r.message.doctype, r.message.name);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
dialog.show();
|
||||
},
|
||||
|
||||
parent_project: function(frm) {
|
||||
parent_project: function (frm) {
|
||||
set_project_in_timelog(frm);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Timesheet Detail", {
|
||||
time_logs_remove: function(frm) {
|
||||
time_logs_remove: function (frm) {
|
||||
calculate_time_and_amount(frm);
|
||||
},
|
||||
|
||||
@@ -248,47 +275,47 @@ frappe.ui.form.on("Timesheet Detail", {
|
||||
}
|
||||
},
|
||||
|
||||
from_time: function(frm, cdt, cdn) {
|
||||
from_time: function (frm, cdt, cdn) {
|
||||
calculate_end_time(frm, cdt, cdn);
|
||||
},
|
||||
|
||||
to_time: function(frm, cdt, cdn) {
|
||||
to_time: function (frm, cdt, cdn) {
|
||||
var child = locals[cdt][cdn];
|
||||
|
||||
if(frm._setting_hours) return;
|
||||
if (frm._setting_hours) return;
|
||||
|
||||
var hours = moment(child.to_time).diff(moment(child.from_time), "seconds") / 3600;
|
||||
frappe.model.set_value(cdt, cdn, "hours", hours);
|
||||
},
|
||||
|
||||
time_logs_add: function(frm, cdt, cdn) {
|
||||
if(frm.doc.parent_project) {
|
||||
frappe.model.set_value(cdt, cdn, 'project', frm.doc.parent_project);
|
||||
time_logs_add: function (frm, cdt, cdn) {
|
||||
if (frm.doc.parent_project) {
|
||||
frappe.model.set_value(cdt, cdn, "project", frm.doc.parent_project);
|
||||
}
|
||||
},
|
||||
|
||||
hours: function(frm, cdt, cdn) {
|
||||
hours: function (frm, cdt, cdn) {
|
||||
calculate_end_time(frm, cdt, cdn);
|
||||
calculate_billing_costing_amount(frm, cdt, cdn);
|
||||
calculate_time_and_amount(frm);
|
||||
},
|
||||
|
||||
billing_hours: function(frm, cdt, cdn) {
|
||||
billing_hours: function (frm, cdt, cdn) {
|
||||
calculate_billing_costing_amount(frm, cdt, cdn);
|
||||
calculate_time_and_amount(frm);
|
||||
},
|
||||
|
||||
billing_rate: function(frm, cdt, cdn) {
|
||||
billing_rate: function (frm, cdt, cdn) {
|
||||
calculate_billing_costing_amount(frm, cdt, cdn);
|
||||
calculate_time_and_amount(frm);
|
||||
},
|
||||
|
||||
costing_rate: function(frm, cdt, cdn) {
|
||||
costing_rate: function (frm, cdt, cdn) {
|
||||
calculate_billing_costing_amount(frm, cdt, cdn);
|
||||
calculate_time_and_amount(frm);
|
||||
},
|
||||
|
||||
is_billable: function(frm, cdt, cdn) {
|
||||
is_billable: function (frm, cdt, cdn) {
|
||||
update_billing_hours(frm, cdt, cdn);
|
||||
update_time_rates(frm, cdt, cdn);
|
||||
calculate_billing_costing_amount(frm, cdt, cdn);
|
||||
@@ -303,7 +330,7 @@ frappe.ui.form.on("Timesheet Detail", {
|
||||
args: {
|
||||
employee: frm.doc.employee,
|
||||
activity_type: frm.selected_doc.activity_type,
|
||||
currency: frm.doc.currency
|
||||
currency: frm.doc.currency,
|
||||
},
|
||||
callback: function (r) {
|
||||
if (r.message) {
|
||||
@@ -311,72 +338,71 @@ frappe.ui.form.on("Timesheet Detail", {
|
||||
frappe.model.set_value(cdt, cdn, "costing_rate", r.message["costing_rate"]);
|
||||
calculate_billing_costing_amount(frm, cdt, cdn);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
var calculate_end_time = function(frm, cdt, cdn) {
|
||||
var calculate_end_time = function (frm, cdt, cdn) {
|
||||
let child = locals[cdt][cdn];
|
||||
|
||||
if(!child.from_time) {
|
||||
if (!child.from_time) {
|
||||
// if from_time value is not available then set the current datetime
|
||||
frappe.model.set_value(cdt, cdn, "from_time", frappe.datetime.get_datetime_as_string());
|
||||
}
|
||||
|
||||
let d = moment(child.from_time);
|
||||
if(child.hours) {
|
||||
if (child.hours) {
|
||||
d.add(child.hours, "hours");
|
||||
frm._setting_hours = true;
|
||||
frappe.model.set_value(cdt, cdn, "to_time",
|
||||
d.format(frappe.defaultDatetimeFormat)).then(() => {
|
||||
frappe.model.set_value(cdt, cdn, "to_time", d.format(frappe.defaultDatetimeFormat)).then(() => {
|
||||
frm._setting_hours = false;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var update_billing_hours = function(frm, cdt, cdn) {
|
||||
var update_billing_hours = function (frm, cdt, cdn) {
|
||||
let child = frappe.get_doc(cdt, cdn);
|
||||
if (!child.is_billable) {
|
||||
frappe.model.set_value(cdt, cdn, 'billing_hours', 0.0);
|
||||
frappe.model.set_value(cdt, cdn, "billing_hours", 0.0);
|
||||
} else {
|
||||
// bill all hours by default
|
||||
frappe.model.set_value(cdt, cdn, "billing_hours", child.hours);
|
||||
}
|
||||
};
|
||||
|
||||
var update_time_rates = function(frm, cdt, cdn) {
|
||||
var update_time_rates = function (frm, cdt, cdn) {
|
||||
let child = frappe.get_doc(cdt, cdn);
|
||||
if (!child.is_billable) {
|
||||
frappe.model.set_value(cdt, cdn, 'billing_rate', 0.0);
|
||||
frappe.model.set_value(cdt, cdn, "billing_rate", 0.0);
|
||||
}
|
||||
};
|
||||
|
||||
var calculate_billing_costing_amount = function(frm, cdt, cdn) {
|
||||
var calculate_billing_costing_amount = function (frm, cdt, cdn) {
|
||||
let row = frappe.get_doc(cdt, cdn);
|
||||
let billing_amount = 0.0;
|
||||
let base_billing_amount = 0.0;
|
||||
let exchange_rate = flt(frm.doc.exchange_rate);
|
||||
frappe.model.set_value(cdt, cdn, 'base_billing_rate', flt(row.billing_rate) * exchange_rate);
|
||||
frappe.model.set_value(cdt, cdn, 'base_costing_rate', flt(row.costing_rate) * exchange_rate);
|
||||
frappe.model.set_value(cdt, cdn, "base_billing_rate", flt(row.billing_rate) * exchange_rate);
|
||||
frappe.model.set_value(cdt, cdn, "base_costing_rate", flt(row.costing_rate) * exchange_rate);
|
||||
if (row.billing_hours && row.is_billable) {
|
||||
base_billing_amount = flt(row.billing_hours) * flt(row.base_billing_rate);
|
||||
billing_amount = flt(row.billing_hours) * flt(row.billing_rate);
|
||||
}
|
||||
|
||||
frappe.model.set_value(cdt, cdn, 'base_billing_amount', base_billing_amount);
|
||||
frappe.model.set_value(cdt, cdn, 'base_costing_amount', flt(row.base_costing_rate) * flt(row.hours));
|
||||
frappe.model.set_value(cdt, cdn, 'billing_amount', billing_amount);
|
||||
frappe.model.set_value(cdt, cdn, 'costing_amount', flt(row.costing_rate) * flt(row.hours));
|
||||
frappe.model.set_value(cdt, cdn, "base_billing_amount", base_billing_amount);
|
||||
frappe.model.set_value(cdt, cdn, "base_costing_amount", flt(row.base_costing_rate) * flt(row.hours));
|
||||
frappe.model.set_value(cdt, cdn, "billing_amount", billing_amount);
|
||||
frappe.model.set_value(cdt, cdn, "costing_amount", flt(row.costing_rate) * flt(row.hours));
|
||||
};
|
||||
|
||||
var calculate_time_and_amount = function(frm) {
|
||||
var calculate_time_and_amount = function (frm) {
|
||||
let tl = frm.doc.time_logs || [];
|
||||
let total_working_hr = 0;
|
||||
let total_billing_hr = 0;
|
||||
let total_billable_amount = 0;
|
||||
let total_costing_amount = 0;
|
||||
for(var i=0; i<tl.length; i++) {
|
||||
for (var i = 0; i < tl.length; i++) {
|
||||
if (tl[i].hours) {
|
||||
total_working_hr += tl[i].hours;
|
||||
total_billable_amount += tl[i].billing_amount;
|
||||
@@ -395,10 +421,10 @@ var calculate_time_and_amount = function(frm) {
|
||||
};
|
||||
|
||||
// set employee (and company) to the one that's currently logged in
|
||||
const set_employee_and_company = function(frm) {
|
||||
const set_employee_and_company = function (frm) {
|
||||
const options = { user_id: frappe.session.user };
|
||||
const fields = ['name', 'company'];
|
||||
frappe.db.get_value('Employee', options, fields).then(({ message }) => {
|
||||
const fields = ["name", "company"];
|
||||
frappe.db.get_value("Employee", options, fields).then(({ message }) => {
|
||||
if (message) {
|
||||
// there is an employee with the currently logged in user_id
|
||||
frm.set_value("employee", message.name);
|
||||
@@ -408,8 +434,8 @@ const set_employee_and_company = function(frm) {
|
||||
};
|
||||
|
||||
function set_project_in_timelog(frm) {
|
||||
if(frm.doc.parent_project) {
|
||||
$.each(frm.doc.time_logs || [], function(i, item) {
|
||||
if (frm.doc.parent_project) {
|
||||
$.each(frm.doc.time_logs || [], function (i, item) {
|
||||
frappe.model.set_value(item.doctype, item.name, "project", frm.doc.parent_project);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
frappe.views.calendar["Timesheet"] = {
|
||||
field_map: {
|
||||
"start": "start_date",
|
||||
"end": "end_date",
|
||||
"name": "parent",
|
||||
"id": "name",
|
||||
"allDay": "allDay",
|
||||
"child_name": "name",
|
||||
"title": "title"
|
||||
start: "start_date",
|
||||
end: "end_date",
|
||||
name: "parent",
|
||||
id: "name",
|
||||
allDay: "allDay",
|
||||
child_name: "name",
|
||||
title: "title",
|
||||
},
|
||||
style_map: {
|
||||
"0": "info",
|
||||
"1": "standard",
|
||||
"2": "danger"
|
||||
0: "info",
|
||||
1: "standard",
|
||||
2: "danger",
|
||||
},
|
||||
gantt: true,
|
||||
filters: [
|
||||
{
|
||||
"fieldtype": "Link",
|
||||
"fieldname": "project",
|
||||
"options": "Project",
|
||||
"label": __("Project")
|
||||
fieldtype: "Link",
|
||||
fieldname: "project",
|
||||
options: "Project",
|
||||
label: __("Project"),
|
||||
},
|
||||
{
|
||||
"fieldtype": "Link",
|
||||
"fieldname": "employee",
|
||||
"options": "Employee",
|
||||
"label": __("Employee")
|
||||
}
|
||||
fieldtype: "Link",
|
||||
fieldname: "employee",
|
||||
options: "Employee",
|
||||
label: __("Employee"),
|
||||
},
|
||||
],
|
||||
get_events_method: "erpnext.projects.doctype.timesheet.timesheet.get_events"
|
||||
}
|
||||
get_events_method: "erpnext.projects.doctype.timesheet.timesheet.get_events",
|
||||
};
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
frappe.listview_settings['Timesheet'] = {
|
||||
frappe.listview_settings["Timesheet"] = {
|
||||
add_fields: ["status", "total_hours", "start_date", "end_date"],
|
||||
get_indicator: function(doc) {
|
||||
if (doc.status== "Billed") {
|
||||
return [__("Billed"), "green", "status,=," + "Billed"]
|
||||
get_indicator: function (doc) {
|
||||
if (doc.status == "Billed") {
|
||||
return [__("Billed"), "green", "status,=," + "Billed"];
|
||||
}
|
||||
|
||||
if (doc.status== "Payslip") {
|
||||
return [__("Payslip"), "green", "status,=," + "Payslip"]
|
||||
if (doc.status == "Payslip") {
|
||||
return [__("Payslip"), "green", "status,=," + "Payslip"];
|
||||
}
|
||||
|
||||
if (doc.status== "Completed") {
|
||||
return [__("Completed"), "green", "status,=," + "Completed"]
|
||||
if (doc.status == "Completed") {
|
||||
return [__("Completed"), "green", "status,=," + "Completed"];
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -2,18 +2,18 @@
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.query_reports["Daily Timesheet Summary"] = {
|
||||
"filters": [
|
||||
filters: [
|
||||
{
|
||||
"fieldname":"from_date",
|
||||
"label": __("From Date"),
|
||||
"fieldtype": "Date",
|
||||
"default": frappe.datetime.get_today()
|
||||
fieldname: "from_date",
|
||||
label: __("From Date"),
|
||||
fieldtype: "Date",
|
||||
default: frappe.datetime.get_today(),
|
||||
},
|
||||
{
|
||||
"fieldname":"to_date",
|
||||
"label": __("To Date"),
|
||||
"fieldtype": "Date",
|
||||
"default": frappe.datetime.get_today()
|
||||
fieldname: "to_date",
|
||||
label: __("To Date"),
|
||||
fieldtype: "Date",
|
||||
default: frappe.datetime.get_today(),
|
||||
},
|
||||
]
|
||||
}
|
||||
],
|
||||
};
|
||||
|
||||
@@ -1,33 +1,32 @@
|
||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
|
||||
frappe.query_reports["Delayed Tasks Summary"] = {
|
||||
"filters": [
|
||||
filters: [
|
||||
{
|
||||
"fieldname": "from_date",
|
||||
"label": __("From Date"),
|
||||
"fieldtype": "Date"
|
||||
fieldname: "from_date",
|
||||
label: __("From Date"),
|
||||
fieldtype: "Date",
|
||||
},
|
||||
{
|
||||
"fieldname": "to_date",
|
||||
"label": __("To Date"),
|
||||
"fieldtype": "Date"
|
||||
fieldname: "to_date",
|
||||
label: __("To Date"),
|
||||
fieldtype: "Date",
|
||||
},
|
||||
{
|
||||
"fieldname": "priority",
|
||||
"label": __("Priority"),
|
||||
"fieldtype": "Select",
|
||||
"options": ["", "Low", "Medium", "High", "Urgent"]
|
||||
fieldname: "priority",
|
||||
label: __("Priority"),
|
||||
fieldtype: "Select",
|
||||
options: ["", "Low", "Medium", "High", "Urgent"],
|
||||
},
|
||||
{
|
||||
"fieldname": "status",
|
||||
"label": __("Status"),
|
||||
"fieldtype": "Select",
|
||||
"options": ["", "Open", "Working","Pending Review","Overdue","Completed"]
|
||||
fieldname: "status",
|
||||
label: __("Status"),
|
||||
fieldtype: "Select",
|
||||
options: ["", "Open", "Working", "Pending Review", "Overdue", "Completed"],
|
||||
},
|
||||
],
|
||||
"formatter": function(value, row, column, data, default_formatter) {
|
||||
formatter: function (value, row, column, data, default_formatter) {
|
||||
value = default_formatter(value, row, column, data);
|
||||
if (column.id == "delay") {
|
||||
if (data["delay"] > 0) {
|
||||
@@ -36,6 +35,6 @@ frappe.query_reports["Delayed Tasks Summary"] = {
|
||||
value = `<p style="color: green; font-weight: bold">${value}</p>`;
|
||||
}
|
||||
}
|
||||
return value
|
||||
}
|
||||
return value;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,34 +1,33 @@
|
||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
|
||||
frappe.query_reports["Employee Billing Summary"] = {
|
||||
"filters": [
|
||||
filters: [
|
||||
{
|
||||
fieldname: "employee",
|
||||
label: __("Employee"),
|
||||
fieldtype: "Link",
|
||||
options: "Employee",
|
||||
reqd: 1
|
||||
reqd: 1,
|
||||
},
|
||||
{
|
||||
fieldname:"from_date",
|
||||
fieldname: "from_date",
|
||||
label: __("From Date"),
|
||||
fieldtype: "Date",
|
||||
default: frappe.datetime.add_months(frappe.datetime.month_start(), -1),
|
||||
reqd: 1
|
||||
reqd: 1,
|
||||
},
|
||||
{
|
||||
fieldname:"to_date",
|
||||
fieldname: "to_date",
|
||||
label: __("To Date"),
|
||||
fieldtype: "Date",
|
||||
default: frappe.datetime.add_days(frappe.datetime.month_start(), -1),
|
||||
reqd: 1
|
||||
reqd: 1,
|
||||
},
|
||||
{
|
||||
fieldname:"include_draft_timesheets",
|
||||
fieldname: "include_draft_timesheets",
|
||||
label: __("Include Timesheets in Draft Status"),
|
||||
fieldtype: "Check",
|
||||
},
|
||||
]
|
||||
}
|
||||
],
|
||||
};
|
||||
|
||||
@@ -1,34 +1,33 @@
|
||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
|
||||
frappe.query_reports["Project Billing Summary"] = {
|
||||
"filters": [
|
||||
filters: [
|
||||
{
|
||||
fieldname: "project",
|
||||
label: __("Project"),
|
||||
fieldtype: "Link",
|
||||
options: "Project",
|
||||
reqd: 1
|
||||
reqd: 1,
|
||||
},
|
||||
{
|
||||
fieldname:"from_date",
|
||||
fieldname: "from_date",
|
||||
label: __("From Date"),
|
||||
fieldtype: "Date",
|
||||
default: frappe.datetime.add_months(frappe.datetime.month_start(), -1),
|
||||
reqd: 1
|
||||
reqd: 1,
|
||||
},
|
||||
{
|
||||
fieldname:"to_date",
|
||||
fieldname: "to_date",
|
||||
label: __("To Date"),
|
||||
fieldtype: "Date",
|
||||
default: frappe.datetime.add_days(frappe.datetime.month_start(),-1),
|
||||
reqd: 1
|
||||
default: frappe.datetime.add_days(frappe.datetime.month_start(), -1),
|
||||
reqd: 1,
|
||||
},
|
||||
{
|
||||
fieldname:"include_draft_timesheets",
|
||||
fieldname: "include_draft_timesheets",
|
||||
label: __("Include Timesheets in Draft Status"),
|
||||
fieldtype: "Check",
|
||||
},
|
||||
]
|
||||
}
|
||||
],
|
||||
};
|
||||
|
||||
@@ -1,42 +1,41 @@
|
||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
|
||||
frappe.query_reports["Project Summary"] = {
|
||||
"filters": [
|
||||
filters: [
|
||||
{
|
||||
"fieldname": "company",
|
||||
"label": __("Company"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Company",
|
||||
"default": frappe.defaults.get_user_default("Company"),
|
||||
"reqd": 1
|
||||
fieldname: "company",
|
||||
label: __("Company"),
|
||||
fieldtype: "Link",
|
||||
options: "Company",
|
||||
default: frappe.defaults.get_user_default("Company"),
|
||||
reqd: 1,
|
||||
},
|
||||
{
|
||||
"fieldname": "is_active",
|
||||
"label": __("Is Active"),
|
||||
"fieldtype": "Select",
|
||||
"options": "\nYes\nNo",
|
||||
"default": "Yes",
|
||||
fieldname: "is_active",
|
||||
label: __("Is Active"),
|
||||
fieldtype: "Select",
|
||||
options: "\nYes\nNo",
|
||||
default: "Yes",
|
||||
},
|
||||
{
|
||||
"fieldname": "status",
|
||||
"label": __("Status"),
|
||||
"fieldtype": "Select",
|
||||
"options": "\nOpen\nCompleted\nCancelled",
|
||||
"default": "Open"
|
||||
fieldname: "status",
|
||||
label: __("Status"),
|
||||
fieldtype: "Select",
|
||||
options: "\nOpen\nCompleted\nCancelled",
|
||||
default: "Open",
|
||||
},
|
||||
{
|
||||
"fieldname": "project_type",
|
||||
"label": __("Project Type"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Project Type"
|
||||
fieldname: "project_type",
|
||||
label: __("Project Type"),
|
||||
fieldtype: "Link",
|
||||
options: "Project Type",
|
||||
},
|
||||
{
|
||||
"fieldname": "priority",
|
||||
"label": __("Priority"),
|
||||
"fieldtype": "Select",
|
||||
"options": "\nLow\nMedium\nHigh"
|
||||
}
|
||||
]
|
||||
fieldname: "priority",
|
||||
label: __("Priority"),
|
||||
fieldtype: "Select",
|
||||
options: "\nLow\nMedium\nHigh",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -2,7 +2,5 @@
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.query_reports["Project wise Stock Tracking"] = {
|
||||
"filters": [
|
||||
|
||||
]
|
||||
}
|
||||
filters: [],
|
||||
};
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
frappe.ready(function() {
|
||||
frappe.ready(function () {
|
||||
// bind events here
|
||||
})
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user