feat: add tax and charges in expense claim

This commit is contained in:
Mangesh-Khairnar 2019-06-11 14:25:44 +05:30
parent 74f502cfa6
commit ac9a4fe03c
6 changed files with 227 additions and 3 deletions

View File

@ -157,6 +157,14 @@ frappe.ui.form.on("Expense Claim", {
}
};
});
// frm.set_query("taxes", "account_head", function(doc) {
// return {
// filters: [
// ['docstatus', '=', 1],
// ['company', '=', doc.company]
// ]
// };
// });
},
onload: function(frm) {
@ -259,6 +267,18 @@ frappe.ui.form.on("Expense Claim", {
frm.events.get_advances(frm);
},
get_taxes: function(frm) {
if(frm.doc.taxes) {
frappe.call({
method: "calculate_taxes",
doc: frm.doc,
callback: (r) => {
refresh_field("taxes");
}
});
}
},
get_advances: function(frm) {
frappe.model.clear_table(frm.doc, "advances");
if (frm.doc.employee) {
@ -298,6 +318,7 @@ frappe.ui.form.on("Expense Claim Detail", {
sanctioned_amount: function(frm, cdt, cdn) {
var doc = frm.doc;
cur_frm.cscript.calculate_total(doc,cdt,cdn);
frm.trigger("get_taxes");
}
});
@ -332,6 +353,47 @@ frappe.ui.form.on("Expense Claim Advance", {
}
});
frappe.ui.form.on("Expense Taxes and Charges", {
account_head: function(frm, cdt, cdn) {
var child = locals[cdt][cdn];
if(child.account_head && !child.description && !child.rate) {
// set description from account head
child.description = child.account_head.split(' - ').slice(0, -1).join(' - ');
// set the tax rate from account head
frappe.db.get_value("Account", child.account_head, "tax_rate").then((r) => {
if(r.message) {
frappe.model.set_value(cdt, cdn, 'rate', r.message.tax_rate);
}
});
refresh_field("taxes");
}
},
calculate_total: function(frm, cdt, cdn) {
var child = locals[cdt][cdn];
child.total = flt(frm.doc.total_sanctioned_amount) + flt(child.tax_amount);
refresh_field("taxes");
},
rate: function(frm, cdt, cdn) {
var child = locals[cdt][cdn];
if(!child.amount) {
child.tax_amount = flt(frm.doc.total_sanctioned_amount) * (flt(child.rate)/100);
refresh_field("taxes");
}
frm.trigger("calculate_total", cdt, cdn)
},
tax_amount: function(frm, cdt, cdn) {
var child = locals[cdt][cdn];
child.rate = flt(child.tax_amount/frm.doc.total_sanctioned_amount) * 100;
frm.trigger("calculate_total", cdt, cdn)
refresh_field("taxes");
}
});
cur_frm.fields_dict['task'].get_query = function(doc) {
return {
filters:{

View File

@ -4,6 +4,7 @@
"creation": "2013-01-10 16:34:14",
"doctype": "DocType",
"document_type": "Setup",
"engine": "InnoDB",
"field_order": [
"naming_series",
"employee",
@ -18,6 +19,9 @@
"expense_details",
"expenses",
"sb1",
"taxes",
"net_total",
"section_break_16",
"posting_date",
"vehicle_log",
"task",
@ -315,12 +319,28 @@
{
"fieldname": "dimension_col_break",
"fieldtype": "Column Break"
},
{
"fieldname": "taxes",
"fieldtype": "Table",
"label": "Expense Taxes and Charges",
"options": "Expense Taxes and Charges"
},
{
"fieldname": "section_break_16",
"fieldtype": "Section Break"
},
{
"fieldname": "net_total",
"fieldtype": "Currency",
"label": "Net Total",
"read_only": 1
}
],
"icon": "fa fa-money",
"idx": 1,
"is_submittable": 1,
"modified": "2019-05-25 22:53:31.682151",
"modified": "2019-06-11 13:21:42.386420",
"modified_by": "Administrator",
"module": "HR",
"name": "Expense Claim",

View File

@ -12,6 +12,7 @@ from erpnext.accounts.general_ledger import make_gl_entries
from erpnext.accounts.doctype.sales_invoice.sales_invoice import get_bank_cash_account
from erpnext.controllers.accounts_controller import AccountsController
from frappe.utils.csvutils import getlink
from erpnext.accounts.utils import get_account_currency
class InvalidExpenseApproverError(frappe.ValidationError): pass
class ExpenseApproverIdentityError(frappe.ValidationError): pass
@ -29,6 +30,7 @@ class ExpenseClaim(AccountsController):
self.set_expense_account(validate=True)
self.set_payable_account()
self.set_cost_center()
self.calculate_taxes()
self.set_status()
if self.task and not self.project:
self.project = frappe.db.get_value("Task", self.task, "project")
@ -93,7 +95,7 @@ class ExpenseClaim(AccountsController):
elif self.project:
frappe.get_doc("Project", self.project).update_project()
def make_gl_entries(self, cancel = False):
def make_gl_entries(self, cancel=False):
if flt(self.total_sanctioned_amount) > 0:
gl_entries = self.get_gl_entries()
make_gl_entries(gl_entries, cancel)
@ -102,7 +104,7 @@ class ExpenseClaim(AccountsController):
gl_entry = []
self.validate_account_details()
payable_amount = flt(self.total_sanctioned_amount) - flt(self.total_advance_amount)
payable_amount = flt(self.net_total) - flt(self.total_advance_amount)
# payable entry
if payable_amount:
@ -170,8 +172,26 @@ class ExpenseClaim(AccountsController):
})
)
gl_entry = self.make_tax_gl_entries(gl_entry)
return gl_entry
def make_tax_gl_entries(self, gl_entries):
# tax table gl entries
for tax in self.get("taxes"):
account_currency = get_account_currency(tax.account_head)
gl_entries.append(
self.get_gl_dict({
"account": tax.account_head,
"debit": tax.tax_amount,
"against": self.employee,
"cost_center": self.cost_center,
"against_voucher_type": self.doctype,
"against_voucher": self.name
}, account_currency)
)
return gl_entries
def validate_account_details(self):
if not self.cost_center:
frappe.throw(_("Cost center is required to book an expense claim"))
@ -193,6 +213,15 @@ class ExpenseClaim(AccountsController):
self.total_claimed_amount += flt(d.claim_amount)
self.total_sanctioned_amount += flt(d.sanctioned_amount)
def calculate_taxes(self):
for tax in self.taxes:
if tax.rate:
tax.tax_amount = flt(self.total_sanctioned_amount) * flt(tax.rate/100)
if tax.tax_amount:
tax.rate = flt(tax.tax_amount)/flt(self.total_sanctioned_amount) * 100
tax.total = flt(tax.tax_amount) + flt(self.total_sanctioned_amount)
self.net_total += tax.total
def update_task(self):
task = frappe.get_doc("Task", self.task)
task.update_total_expense_claim()

View File

@ -0,0 +1,103 @@
{
"autoname": "hash",
"creation": "2019-06-03 11:42:33.123976",
"doctype": "DocType",
"document_type": "Setup",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"account_head",
"cost_center",
"col_break1",
"rate",
"description",
"section_break_6",
"tax_amount",
"column_break_8",
"total"
],
"fields": [
{
"fieldname": "col_break1",
"fieldtype": "Column Break"
},
{
"columns": 2,
"fieldname": "account_head",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Account Head",
"oldfieldname": "account_head",
"oldfieldtype": "Link",
"options": "Account",
"reqd": 1
},
{
"default": ":Company",
"fieldname": "cost_center",
"fieldtype": "Link",
"label": "Cost Center",
"oldfieldname": "cost_center",
"oldfieldtype": "Link",
"options": "Cost Center"
},
{
"fieldname": "description",
"fieldtype": "Small Text",
"label": "Description",
"oldfieldname": "description",
"oldfieldtype": "Small Text",
"print_width": "300px",
"reqd": 1,
"width": "300px"
},
{
"columns": 2,
"fieldname": "rate",
"fieldtype": "Float",
"in_list_view": 1,
"label": "Rate",
"oldfieldname": "rate",
"oldfieldtype": "Currency"
},
{
"columns": 2,
"fieldname": "tax_amount",
"fieldtype": "Currency",
"in_list_view": 1,
"label": "Amount",
"oldfieldname": "tax_amount",
"oldfieldtype": "Currency",
"options": "currency"
},
{
"columns": 2,
"fieldname": "total",
"fieldtype": "Currency",
"in_list_view": 1,
"label": "Total",
"oldfieldname": "total",
"oldfieldtype": "Currency",
"options": "currency",
"read_only": 1
},
{
"fieldname": "section_break_6",
"fieldtype": "Section Break"
},
{
"fieldname": "column_break_8",
"fieldtype": "Column Break"
}
],
"istable": 1,
"modified": "2019-06-11 14:19:34.780611",
"modified_by": "Administrator",
"module": "HR",
"name": "Expense Taxes and Charges",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "ASC",
"track_changes": 1
}

View File

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
# import frappe
from frappe.model.document import Document
class ExpenseTaxesandCharges(Document):
pass