[Enhancement] Booking of an employee's expense claim (#7267)

* [Enhancement] Auto book of an employee's expense claim

* test cases

* documentation

* fixes and changes

* removed payable from employee and added into the company

* Added party in account, patch to update party type for customer and supplier accounts

* added party type in erpnext, fix patch

* fixed travis
This commit is contained in:
rohitwaghchaure
2017-02-01 12:02:08 +05:30
committed by Rushabh Mehta
parent 99ce531beb
commit ea092a7b24
35 changed files with 943 additions and 169 deletions

View File

@@ -86,9 +86,9 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
};
});
me.frm.set_query("party_type", "accounts", function(doc, cdt, cdn) {
return {
filters: {"name": ["in", ["Customer", "Supplier"]]}
me.frm.set_query("party_type", "accounts", function() {
return{
query: "erpnext.setup.doctype.party_type.party_type.get_party_type"
}
});

View File

@@ -9,6 +9,7 @@ from erpnext.controllers.accounts_controller import AccountsController
from erpnext.accounts.utils import get_balance_on, get_account_currency
from erpnext.setup.utils import get_company_currency
from erpnext.accounts.party import get_party_account
from erpnext.hr.doctype.expense_claim.expense_claim import update_reimbursed_amount
class JournalEntry(AccountsController):
def __init__(self, arg1, arg2=None):
@@ -375,7 +376,7 @@ class JournalEntry(AccountsController):
bank_amount = party_amount = total_amount = 0.0
currency = bank_account_currency = party_account_currency = pay_to_recd_from= None
for d in self.get('accounts'):
if d.party_type and d.party:
if d.party_type in ['Customer', 'Supplier'] and d.party:
if not pay_to_recd_from:
pay_to_recd_from = frappe.db.get_value(d.party_type, d.party,
"customer_name" if d.party_type=="Customer" else "supplier_name")
@@ -503,11 +504,9 @@ class JournalEntry(AccountsController):
def update_expense_claim(self):
for d in self.accounts:
if d.reference_type=="Expense Claim":
amt = frappe.db.sql("""select sum(debit) as amt from `tabJournal Entry Account`
where reference_type = "Expense Claim" and
reference_name = %s and docstatus = 1""", d.reference_name ,as_dict=1)[0].amt
frappe.db.set_value("Expense Claim", d.reference_name , "total_amount_reimbursed", amt)
if d.reference_type=="Expense Claim" and d.party:
doc = frappe.get_doc("Expense Claim", d.reference_name)
update_reimbursed_amount(doc)
def validate_expense_claim(self):
for d in self.accounts:

View File

@@ -26,6 +26,12 @@ frappe.ui.form.on('Payment Entry', {
}
});
frm.set_query("party_type", function() {
return{
query: "erpnext.setup.doctype.party_type.party_type.get_party_type"
}
});
frm.set_query("paid_to", function() {
var account_types = in_list(["Receive", "Internal Transfer"], frm.doc.payment_type) ?
["Bank", "Cash"] : party_account_type;

View File

@@ -104,7 +104,7 @@
"columns": 0,
"depends_on": "eval:in_list([\"Receive\", \"Pay\"], doc.payment_type)",
"fieldname": "party_type",
"fieldtype": "Select",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -114,7 +114,7 @@
"label": "Party Type",
"length": 0,
"no_copy": 0,
"options": "Customer\nSupplier",
"options": "DocType",
"permlevel": 0,
"precision": "",
"print_hide": 1,
@@ -1561,7 +1561,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2016-11-07 05:33:40.371480",
"modified": "2016-12-26 14:32:36.900576",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry",

View File

@@ -6,12 +6,10 @@ frappe.provide("erpnext.accounts");
erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.extend({
onload: function() {
var me = this
this.frm.set_query('party_type', function() {
return {
filters: {
"name": ["in", ["Customer", "Supplier"]]
}
};
this.frm.set_query("party_type", function() {
return{
query: "erpnext.setup.doctype.party_type.party_type.get_party_type"
}
});
this.frm.set_query('receivable_payable_account', function() {

View File

@@ -171,13 +171,13 @@ def get_party_account(party_type, party, company):
account = frappe.db.get_value("Party Account",
{"parenttype": party_type, "parent": party, "company": company}, "account")
if not account:
if not account and party_type in ['Customer', 'Supplier']:
party_group_doctype = "Customer Group" if party_type=="Customer" else "Supplier Type"
group = frappe.db.get_value(party_type, party, scrub(party_group_doctype))
account = frappe.db.get_value("Party Account",
{"parenttype": party_group_doctype, "parent": group, "company": company}, "account")
if not account:
if not account and party_type in ['Customer', 'Supplier']:
default_account_name = "default_receivable_account" \
if party_type=="Customer" else "default_payable_account"
account = frappe.db.get_value("Company", company, default_account_name)
@@ -249,7 +249,7 @@ def validate_party_accounts(doc):
if existing_gle_currency and party_account_currency != existing_gle_currency:
frappe.throw(_("Accounting entries have already been made in currency {0} for company {1}. Please select a receivable or payable account with currency {0}.").format(existing_gle_currency, account.company))
if doc.default_currency and party_account_currency and company_default_currency:
if doc.get("default_currency") and party_account_currency and company_default_currency:
if doc.default_currency != party_account_currency and doc.default_currency != company_default_currency:
frappe.throw(_("Billing currency must be equal to either default comapany's currency or party account currency"))

View File

@@ -59,8 +59,8 @@ frappe.query_reports["General Ledger"] = {
{
"fieldname":"party_type",
"label": __("Party Type"),
"fieldtype": "Select",
"options": ["", "Customer", "Supplier"],
"fieldtype": "Link",
"options": "Party Type",
"default": ""
},
{

View File

@@ -0,0 +1,12 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.query_reports["Unpaid Expense Claim"] = {
"filters": [
{
"fieldname":"employee",
"label": __("Employee"),
"fieldtype": "Link"
}
]
}

View File

@@ -0,0 +1,18 @@
{
"add_total_row": 0,
"apply_user_permissions": 1,
"creation": "2017-01-04 16:26:18.309717",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"modified": "2017-01-04 16:26:18.309717",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Unpaid Expense Claim",
"owner": "Administrator",
"ref_doctype": "Expense Claim",
"report_name": "Unpaid Expense Claim",
"report_type": "Script Report"
}

View File

@@ -0,0 +1,34 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe import _
def execute(filters=None):
columns, data = [], []
columns = get_columns()
data = get_unclaimed_expese_claims(filters)
return columns, data
def get_columns():
return [_("Employee") + ":Link/Employee:120", _("Employee Name") + "::120",_("Expense Claim") + ":Link/Expense Claim:120",
_("Sanctioned Amount") + ":Currency:120", _("Paid Amount") + ":Currency:120", _("Outstanding Amount") + ":Currency:150"]
def get_unclaimed_expese_claims(filters):
cond = "1=1"
if filters.get("employee"):
cond = "ec.employee = %(employee)s"
return frappe.db.sql("""
select
ec.employee, ec.employee_name, ec.name, ec.total_sanctioned_amount, ec.total_amount_reimbursed,
sum(gle.credit_in_account_currency - gle.debit_in_account_currency) as outstanding_amt
from
`tabExpense Claim` ec, `tabGL Entry` gle
where
gle.against_voucher_type = "Expense Claim" and gle.against_voucher = ec.name
and gle.party is not null and ec.docstatus = 1 and ec.is_paid = 0 and {cond} group by ec.name
having
outstanding_amt > 0
""".format(cond=cond), filters, as_list=1)