added multi-currency fields
This commit is contained in:
parent
42d2f663fa
commit
9bd779401d
@ -1,4 +1,8 @@
|
|||||||
frappe.ui.form.on("Activity Type", {
|
frappe.ui.form.on("Activity Type", {
|
||||||
|
onload: function(frm) {
|
||||||
|
frm.set_currency_labels(["billing_rate", "costing_rate"], frappe.defaults.get_global_default('currency'));
|
||||||
|
},
|
||||||
|
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
frm.add_custom_button(__("Activity Cost per Employee"), function() {
|
frm.add_custom_button(__("Activity Cost per Employee"), function() {
|
||||||
frappe.route_options = {"activity_type": frm.doc.name};
|
frappe.route_options = {"activity_type": frm.doc.name};
|
||||||
|
@ -93,6 +93,7 @@ frappe.ui.form.on("Timesheet", {
|
|||||||
frm.fields_dict["time_logs"].grid.toggle_enable("is_billable", false);
|
frm.fields_dict["time_logs"].grid.toggle_enable("is_billable", false);
|
||||||
}
|
}
|
||||||
frm.trigger('setup_filters');
|
frm.trigger('setup_filters');
|
||||||
|
frm.trigger('set_dynamic_field_label');
|
||||||
},
|
},
|
||||||
|
|
||||||
customer: function(frm) {
|
customer: function(frm) {
|
||||||
@ -113,6 +114,48 @@ frappe.ui.form.on("Timesheet", {
|
|||||||
frm.refresh();
|
frm.refresh();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
currency: function(frm) {
|
||||||
|
let base_currency = frappe.defaults.get_global_default('currency');
|
||||||
|
if (base_currency != frm.doc.company) {
|
||||||
|
frappe.call({
|
||||||
|
method: "erpnext.setup.utils.get_exchange_rate",
|
||||||
|
args: {
|
||||||
|
from_currency: frm.doc.currency,
|
||||||
|
to_currency: base_currency
|
||||||
|
},
|
||||||
|
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.trigger('set_dynamic_field_label');
|
||||||
|
},
|
||||||
|
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
frm.refresh_fields();
|
||||||
|
},
|
||||||
|
|
||||||
make_invoice: function(frm) {
|
make_invoice: function(frm) {
|
||||||
let fields = [{
|
let fields = [{
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
@ -204,35 +247,34 @@ frappe.ui.form.on("Timesheet Detail", {
|
|||||||
if(frm.doc.parent_project) {
|
if(frm.doc.parent_project) {
|
||||||
frappe.model.set_value(cdt, cdn, 'project', frm.doc.parent_project);
|
frappe.model.set_value(cdt, cdn, 'project', frm.doc.parent_project);
|
||||||
}
|
}
|
||||||
|
|
||||||
var $trigger_again = $('.form-grid').find('.grid-row').find('.btn-open-row');
|
|
||||||
$trigger_again.on('click', () => {
|
|
||||||
$('.form-grid')
|
|
||||||
.find('[data-fieldname="timer"]')
|
|
||||||
.append(frappe.render_template("timesheet"));
|
|
||||||
frm.trigger("control_timer");
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
hours: function(frm, cdt, cdn) {
|
hours: function(frm, cdt, cdn) {
|
||||||
calculate_end_time(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_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_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_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_billing_hours(frm, cdt, cdn);
|
||||||
update_time_rates(frm, cdt, cdn);
|
update_time_rates(frm, cdt, cdn);
|
||||||
calculate_billing_costing_amount(frm, cdt, cdn);
|
calculate_billing_costing_amount(frm, cdt, cdn);
|
||||||
|
calculate_time_and_amount(frm);
|
||||||
},
|
},
|
||||||
|
|
||||||
activity_type: function(frm, cdt, cdn) {
|
activity_type: function(frm, cdt, cdn) {
|
||||||
@ -240,7 +282,8 @@ frappe.ui.form.on("Timesheet Detail", {
|
|||||||
method: "erpnext.projects.doctype.timesheet.timesheet.get_activity_cost",
|
method: "erpnext.projects.doctype.timesheet.timesheet.get_activity_cost",
|
||||||
args: {
|
args: {
|
||||||
employee: frm.doc.employee,
|
employee: frm.doc.employee,
|
||||||
activity_type: frm.selected_doc.activity_type
|
activity_type: frm.selected_doc.activity_type,
|
||||||
|
currency: frm.doc.currency
|
||||||
},
|
},
|
||||||
callback: function(r){
|
callback: function(r){
|
||||||
if(r.message){
|
if(r.message){
|
||||||
@ -290,17 +333,21 @@ var update_time_rates = function(frm, cdt, cdn) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var calculate_billing_costing_amount = function(frm, cdt, cdn) {
|
var calculate_billing_costing_amount = function(frm, cdt, cdn) {
|
||||||
let child = frappe.get_doc(cdt, cdn);
|
let row = frappe.get_doc(cdt, cdn);
|
||||||
let billing_amount = 0.0;
|
let billing_amount = 0.0;
|
||||||
let costing_amount = 0.0;
|
let base_billing_amount = 0.0;
|
||||||
|
let exchange_rate = flt(frm.doc.exchange_rate);
|
||||||
if (child.billing_hours && child.is_billable) {
|
frappe.model.set_value(cdt, cdn, 'base_billing_rate', flt(row.billing_rate) * exchange_rate);
|
||||||
billing_amount = (child.billing_hours * child.billing_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);
|
||||||
}
|
}
|
||||||
costing_amount = flt(child.costing_rate * child.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, 'billing_amount', billing_amount);
|
||||||
frappe.model.set_value(cdt, cdn, 'costing_amount', costing_amount);
|
frappe.model.set_value(cdt, cdn, 'costing_amount', flt(row.costing_rate) * flt(row.hours));
|
||||||
calculate_time_and_amount(frm);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var calculate_time_and_amount = function(frm) {
|
var calculate_time_and_amount = function(frm) {
|
||||||
|
@ -14,6 +14,7 @@ from frappe.model.document import Document
|
|||||||
from erpnext.manufacturing.doctype.workstation.workstation import (check_if_within_operating_hours,
|
from erpnext.manufacturing.doctype.workstation.workstation import (check_if_within_operating_hours,
|
||||||
WorkstationHolidayError)
|
WorkstationHolidayError)
|
||||||
from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import get_mins_between_operations
|
from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import get_mins_between_operations
|
||||||
|
from erpnext.setup.utils import get_exchange_rate
|
||||||
|
|
||||||
class OverlapError(frappe.ValidationError): pass
|
class OverlapError(frappe.ValidationError): pass
|
||||||
class OverWorkLoggedError(frappe.ValidationError): pass
|
class OverWorkLoggedError(frappe.ValidationError): pass
|
||||||
@ -37,9 +38,9 @@ class Timesheet(Document):
|
|||||||
self.total_hours = 0.0
|
self.total_hours = 0.0
|
||||||
self.total_billable_hours = 0.0
|
self.total_billable_hours = 0.0
|
||||||
self.total_billed_hours = 0.0
|
self.total_billed_hours = 0.0
|
||||||
self.total_billable_amount = 0.0
|
self.total_billable_amount = self.base_total_billable_amount = 0.0
|
||||||
self.total_costing_amount = 0.0
|
self.total_costing_amount = self.base_total_costing_amount = 0.0
|
||||||
self.total_billed_amount = 0.0
|
self.total_billed_amount = self.base_total_billed_amount = 0.0
|
||||||
|
|
||||||
for d in self.get("time_logs"):
|
for d in self.get("time_logs"):
|
||||||
self.update_billing_hours(d)
|
self.update_billing_hours(d)
|
||||||
@ -47,10 +48,13 @@ class Timesheet(Document):
|
|||||||
|
|
||||||
self.total_hours += flt(d.hours)
|
self.total_hours += flt(d.hours)
|
||||||
self.total_costing_amount += flt(d.costing_amount)
|
self.total_costing_amount += flt(d.costing_amount)
|
||||||
|
self.base_total_costing_amount += flt(d.base_costing_amount)
|
||||||
if d.is_billable:
|
if d.is_billable:
|
||||||
self.total_billable_hours += flt(d.billing_hours)
|
self.total_billable_hours += flt(d.billing_hours)
|
||||||
self.total_billable_amount += flt(d.billing_amount)
|
self.total_billable_amount += flt(d.billing_amount)
|
||||||
|
self.base_total_billable_amount += flt(d.base_billing_amount)
|
||||||
self.total_billed_amount += flt(d.billing_amount) if d.sales_invoice else 0.0
|
self.total_billed_amount += flt(d.billing_amount) if d.sales_invoice else 0.0
|
||||||
|
self.base_total_billed_amount += flt(d.base_billing_amount) if d.sales_invoice else 0.0
|
||||||
self.total_billed_hours += flt(d.billing_hours) if d.sales_invoice else 0.0
|
self.total_billed_hours += flt(d.billing_hours) if d.sales_invoice else 0.0
|
||||||
|
|
||||||
def calculate_percentage_billed(self):
|
def calculate_percentage_billed(self):
|
||||||
@ -330,12 +334,17 @@ def set_missing_values(time_sheet, target):
|
|||||||
})
|
})
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_activity_cost(employee=None, activity_type=None):
|
def get_activity_cost(employee=None, activity_type=None, currency=None):
|
||||||
|
base_currency = frappe.defaults.get_global_default('currency')
|
||||||
rate = frappe.db.get_values("Activity Cost", {"employee": employee,
|
rate = frappe.db.get_values("Activity Cost", {"employee": employee,
|
||||||
"activity_type": activity_type}, ["costing_rate", "billing_rate"], as_dict=True)
|
"activity_type": activity_type}, ["costing_rate", "billing_rate"], as_dict=True)
|
||||||
if not rate:
|
if not rate:
|
||||||
rate = frappe.db.get_values("Activity Type", {"activity_type": activity_type},
|
rate = frappe.db.get_values("Activity Type", {"activity_type": activity_type},
|
||||||
["costing_rate", "billing_rate"], as_dict=True)
|
["costing_rate", "billing_rate"], as_dict=True)
|
||||||
|
if rate and currency and currency!=base_currency:
|
||||||
|
exchnage_rate = get_exchange_rate(base_currency, currency)
|
||||||
|
rate[0]["costing_rate"] = rate[0]["costing_rate"] * exchnage_rate
|
||||||
|
rate[0]["billing_rate"] = rate[0]["billing_rate"] * exchnage_rate
|
||||||
|
|
||||||
return rate[0] if rate else {}
|
return rate[0] if rate else {}
|
||||||
|
|
||||||
|
@ -31,9 +31,13 @@
|
|||||||
"column_break_8",
|
"column_break_8",
|
||||||
"billing_hours",
|
"billing_hours",
|
||||||
"section_break_11",
|
"section_break_11",
|
||||||
|
"base_billing_rate",
|
||||||
|
"base_billing_amount",
|
||||||
|
"base_costing_rate",
|
||||||
|
"base_costing_amount",
|
||||||
|
"column_break_14",
|
||||||
"billing_rate",
|
"billing_rate",
|
||||||
"billing_amount",
|
"billing_amount",
|
||||||
"column_break_14",
|
|
||||||
"costing_rate",
|
"costing_rate",
|
||||||
"costing_amount"
|
"costing_amount"
|
||||||
],
|
],
|
||||||
@ -230,12 +234,40 @@
|
|||||||
"fieldname": "description",
|
"fieldname": "description",
|
||||||
"fieldtype": "Small Text",
|
"fieldtype": "Small Text",
|
||||||
"label": "Description"
|
"label": "Description"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "base_billing_rate",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Billing Rate",
|
||||||
|
"print_hide": 1,
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "base_billing_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Billing Amount",
|
||||||
|
"print_hide": 1,
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "base_costing_rate",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Costing Rate",
|
||||||
|
"print_hide": 1,
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "base_costing_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Costing Amount",
|
||||||
|
"print_hide": 1,
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-05-15 16:16:10.688694",
|
"modified": "2021-05-18 12:19:33.205940",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Projects",
|
"module": "Projects",
|
||||||
"name": "Timesheet Detail",
|
"name": "Timesheet Detail",
|
||||||
|
Loading…
Reference in New Issue
Block a user