Add Payment Entry for Expenses
This commit is contained in:
parent
316477b422
commit
118ceda46f
@ -28,7 +28,7 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
frm.set_query("party_type", function() {
|
frm.set_query("party_type", function() {
|
||||||
return{
|
return{
|
||||||
"filters": {
|
"filters": {
|
||||||
"name": ["in",["Customer","Supplier"]],
|
"name": ["in",["Customer","Supplier", "Employee"]],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -70,6 +70,8 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
var doctypes = ["Sales Order", "Sales Invoice", "Journal Entry"];
|
var doctypes = ["Sales Order", "Sales Invoice", "Journal Entry"];
|
||||||
} else if (frm.doc.party_type=="Supplier") {
|
} else if (frm.doc.party_type=="Supplier") {
|
||||||
var doctypes = ["Purchase Order", "Purchase Invoice", "Journal Entry"];
|
var doctypes = ["Purchase Order", "Purchase Invoice", "Journal Entry"];
|
||||||
|
} else if (frm.doc.party_type=="Employee") {
|
||||||
|
var doctypes = ["Expense Claim"];
|
||||||
} else {
|
} else {
|
||||||
var doctypes = ["Journal Entry"];
|
var doctypes = ["Journal Entry"];
|
||||||
}
|
}
|
||||||
@ -82,7 +84,7 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
frm.set_query("reference_name", "references", function(doc, cdt, cdn) {
|
frm.set_query("reference_name", "references", function(doc, cdt, cdn) {
|
||||||
child = locals[cdt][cdn];
|
child = locals[cdt][cdn];
|
||||||
filters = {"docstatus": 1, "company": doc.company};
|
filters = {"docstatus": 1, "company": doc.company};
|
||||||
party_type_doctypes = ['Sales Invoice', 'Sales Order', 'Purchase Invoice', 'Purchase Order'];
|
party_type_doctypes = ['Sales Invoice', 'Sales Order', 'Purchase Invoice', 'Purchase Order', 'Expense Claim'];
|
||||||
|
|
||||||
if (in_list(party_type_doctypes, child.reference_doctype)) {
|
if (in_list(party_type_doctypes, child.reference_doctype)) {
|
||||||
filters[doc.party_type.toLowerCase()] = doc.party;
|
filters[doc.party_type.toLowerCase()] = doc.party;
|
||||||
@ -200,9 +202,15 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if(!frm.doc.party)
|
if(!frm.doc.party)
|
||||||
frm.set_value("party_type", frm.doc.payment_type=="Receive" ? "Customer" : "Supplier");
|
{
|
||||||
|
if (frm.doc.payment_type=="Receive"){
|
||||||
|
frm.set_value("party_type", "Customer");
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
frm.events.party(frm);
|
frm.events.party(frm);
|
||||||
|
}
|
||||||
|
|
||||||
if(frm.doc.mode_of_payment)
|
if(frm.doc.mode_of_payment)
|
||||||
frm.events.mode_of_payment(frm);
|
frm.events.mode_of_payment(frm);
|
||||||
@ -487,7 +495,7 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
c.reference_name = d.voucher_no;
|
c.reference_name = d.voucher_no;
|
||||||
c.total_amount = d.invoice_amount;
|
c.total_amount = d.invoice_amount;
|
||||||
c.outstanding_amount = d.outstanding_amount;
|
c.outstanding_amount = d.outstanding_amount;
|
||||||
if(!in_list(["Sales Order", "Purchase Order"], d.voucher_type)) {
|
if(!in_list(["Sales Order", "Purchase Order", "Expense Claim"], d.voucher_type)) {
|
||||||
if(flt(d.outstanding_amount) > 0)
|
if(flt(d.outstanding_amount) > 0)
|
||||||
total_positive_outstanding += flt(d.outstanding_amount);
|
total_positive_outstanding += flt(d.outstanding_amount);
|
||||||
else
|
else
|
||||||
@ -502,14 +510,15 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
} else {
|
} else {
|
||||||
c.exchange_rate = 1;
|
c.exchange_rate = 1;
|
||||||
}
|
}
|
||||||
if (in_list(['Sales Invoice', 'Purchase Invoice'], d.reference_doctype)){
|
if (in_list(['Sales Invoice', 'Purchase Invoice', "Expense Claim"], d.reference_doctype)){
|
||||||
c.due_date = d.due_date;
|
c.due_date = d.due_date;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if(
|
if(
|
||||||
(frm.doc.payment_type=="Receive" && frm.doc.party_type=="Customer") ||
|
(frm.doc.payment_type=="Receive" && frm.doc.party_type=="Customer") ||
|
||||||
(frm.doc.payment_type=="Pay" && frm.doc.party_type=="Supplier")
|
(frm.doc.payment_type=="Pay" && frm.doc.party_type=="Supplier") ||
|
||||||
|
(frm.doc.payment_type=="Pay" && frm.doc.party_type=="Employee")
|
||||||
) {
|
) {
|
||||||
if(total_positive_outstanding > total_negative_outstanding)
|
if(total_positive_outstanding > total_negative_outstanding)
|
||||||
frm.set_value("paid_amount",
|
frm.set_value("paid_amount",
|
||||||
@ -554,7 +563,8 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
|
|
||||||
var allocated_negative_outstanding = 0;
|
var allocated_negative_outstanding = 0;
|
||||||
if((frm.doc.payment_type=="Receive" && frm.doc.party_type=="Customer") ||
|
if((frm.doc.payment_type=="Receive" && frm.doc.party_type=="Customer") ||
|
||||||
(frm.doc.payment_type=="Pay" && frm.doc.party_type=="Supplier")) {
|
(frm.doc.payment_type=="Pay" && frm.doc.party_type=="Supplier") ||
|
||||||
|
(frm.doc.payment_type=="Pay" && frm.doc.party_type=="Employee")) {
|
||||||
if(total_positive_outstanding_including_order > paid_amount) {
|
if(total_positive_outstanding_including_order > paid_amount) {
|
||||||
var remaining_outstanding = total_positive_outstanding_including_order - paid_amount;
|
var remaining_outstanding = total_positive_outstanding_including_order - paid_amount;
|
||||||
allocated_negative_outstanding = total_negative_outstanding < remaining_outstanding ?
|
allocated_negative_outstanding = total_negative_outstanding < remaining_outstanding ?
|
||||||
@ -695,6 +705,14 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
frappe.msgprint(__("Row #{0}: Reference Document Type must be one of Purchase Order, Purchase Invoice or Journal Entry", [row.idx]));
|
frappe.msgprint(__("Row #{0}: Reference Document Type must be one of Purchase Order, Purchase Invoice or Journal Entry", [row.idx]));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(frm.doc.party_type=="Employee" &&
|
||||||
|
!in_list(["Expense Claim", "Journal Entry"], row.reference_doctype)
|
||||||
|
) {
|
||||||
|
frappe.model.set_value(row.doctype, row.name, "against_voucher_type", null);
|
||||||
|
frappe.msgprint(__("Row #{0}: Reference Document Type must be one of Expense Claim or Journal Entry", [row.idx]));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (row) {
|
if (row) {
|
||||||
|
@ -12,7 +12,7 @@ from erpnext.accounts.doctype.journal_entry.journal_entry \
|
|||||||
import get_average_exchange_rate, get_default_bank_cash_account
|
import get_average_exchange_rate, get_default_bank_cash_account
|
||||||
from erpnext.setup.utils import get_exchange_rate
|
from erpnext.setup.utils import get_exchange_rate
|
||||||
from erpnext.accounts.general_ledger import make_gl_entries
|
from erpnext.accounts.general_ledger import make_gl_entries
|
||||||
|
from erpnext.hr.doctype.expense_claim.expense_claim import update_reimbursed_amount
|
||||||
from erpnext.controllers.accounts_controller import AccountsController
|
from erpnext.controllers.accounts_controller import AccountsController
|
||||||
|
|
||||||
class InvalidPaymentEntry(ValidationError): pass
|
class InvalidPaymentEntry(ValidationError): pass
|
||||||
@ -57,11 +57,13 @@ class PaymentEntry(AccountsController):
|
|||||||
frappe.throw(_("Difference Amount must be zero"))
|
frappe.throw(_("Difference Amount must be zero"))
|
||||||
self.make_gl_entries()
|
self.make_gl_entries()
|
||||||
self.update_advance_paid()
|
self.update_advance_paid()
|
||||||
|
self.update_expense_claim()
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
self.setup_party_account_field()
|
self.setup_party_account_field()
|
||||||
self.make_gl_entries(cancel=1)
|
self.make_gl_entries(cancel=1)
|
||||||
self.update_advance_paid()
|
self.update_advance_paid()
|
||||||
|
self.update_expense_claim()
|
||||||
self.delink_advance_entry_references()
|
self.delink_advance_entry_references()
|
||||||
|
|
||||||
def validate_duplicate_entry(self):
|
def validate_duplicate_entry(self):
|
||||||
@ -182,8 +184,10 @@ class PaymentEntry(AccountsController):
|
|||||||
def validate_reference_documents(self):
|
def validate_reference_documents(self):
|
||||||
if self.party_type == "Customer":
|
if self.party_type == "Customer":
|
||||||
valid_reference_doctypes = ("Sales Order", "Sales Invoice", "Journal Entry")
|
valid_reference_doctypes = ("Sales Order", "Sales Invoice", "Journal Entry")
|
||||||
else:
|
elif self.party_type == "Supplier":
|
||||||
valid_reference_doctypes = ("Purchase Order", "Purchase Invoice", "Journal Entry")
|
valid_reference_doctypes = ("Purchase Order", "Purchase Invoice", "Journal Entry")
|
||||||
|
elif self.party_type == "Employee":
|
||||||
|
valid_reference_doctypes = ("Expense Claim", "Journal Entry")
|
||||||
|
|
||||||
for d in self.get("references"):
|
for d in self.get("references"):
|
||||||
if not d.allocated_amount:
|
if not d.allocated_amount:
|
||||||
@ -205,12 +209,17 @@ class PaymentEntry(AccountsController):
|
|||||||
else:
|
else:
|
||||||
self.validate_journal_entry()
|
self.validate_journal_entry()
|
||||||
|
|
||||||
if d.reference_doctype in ("Sales Invoice", "Purchase Invoice"):
|
if d.reference_doctype in ("Sales Invoice", "Purchase Invoice", "Expense Claim"):
|
||||||
ref_party_account = ref_doc.debit_to \
|
if self.party_type=="Customer":
|
||||||
if self.party_type=="Customer" else ref_doc.credit_to
|
ref_party_account = ref_doc.debit_to
|
||||||
|
elif self.party_type=="Supplier":
|
||||||
|
ref_party_account = ref_doc.credit_to
|
||||||
|
elif self.party_type=="Employee":
|
||||||
|
ref_party_account = ref_doc.payable_account
|
||||||
|
|
||||||
if ref_party_account != self.party_account:
|
if ref_party_account != self.party_account:
|
||||||
frappe.throw(_("{0} {1} does not associated with Party Account {2}")
|
frappe.throw(_("{0} {1} is associated with {2}, but Party Account is {3}")
|
||||||
.format(d.reference_doctype, d.reference_name, self.party_account))
|
.format(d.reference_doctype, d.reference_name, ref_party_account, self.party_account))
|
||||||
|
|
||||||
if ref_doc.docstatus != 1:
|
if ref_doc.docstatus != 1:
|
||||||
frappe.throw(_("{0} {1} must be submitted")
|
frappe.throw(_("{0} {1} must be submitted")
|
||||||
@ -473,6 +482,13 @@ class PaymentEntry(AccountsController):
|
|||||||
if d.allocated_amount and d.reference_doctype in ("Sales Order", "Purchase Order"):
|
if d.allocated_amount and d.reference_doctype in ("Sales Order", "Purchase Order"):
|
||||||
frappe.get_doc(d.reference_doctype, d.reference_name).set_total_advance_paid()
|
frappe.get_doc(d.reference_doctype, d.reference_name).set_total_advance_paid()
|
||||||
|
|
||||||
|
def update_expense_claim(self):
|
||||||
|
if self.payment_type in ("Pay") and self.party:
|
||||||
|
for d in self.get("references"):
|
||||||
|
if d.reference_doctype=="Expense Claim" and d.reference_name:
|
||||||
|
doc = frappe.get_doc("Expense Claim", d.reference_name)
|
||||||
|
update_reimbursed_amount(doc)
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_outstanding_reference_documents(args):
|
def get_outstanding_reference_documents(args):
|
||||||
args = json.loads(args)
|
args = json.loads(args)
|
||||||
@ -493,7 +509,7 @@ def get_outstanding_reference_documents(args):
|
|||||||
for d in outstanding_invoices:
|
for d in outstanding_invoices:
|
||||||
d["exchange_rate"] = 1
|
d["exchange_rate"] = 1
|
||||||
if party_account_currency != company_currency:
|
if party_account_currency != company_currency:
|
||||||
if d.voucher_type in ("Sales Invoice", "Purchase Invoice"):
|
if d.voucher_type in ("Sales Invoice", "Purchase Invoice", "Expense Claim"):
|
||||||
d["exchange_rate"] = frappe.db.get_value(d.voucher_type, d.voucher_no, "conversion_rate")
|
d["exchange_rate"] = frappe.db.get_value(d.voucher_type, d.voucher_no, "conversion_rate")
|
||||||
elif d.voucher_type == "Journal Entry":
|
elif d.voucher_type == "Journal Entry":
|
||||||
d["exchange_rate"] = get_exchange_rate(
|
d["exchange_rate"] = get_exchange_rate(
|
||||||
@ -507,8 +523,15 @@ def get_outstanding_reference_documents(args):
|
|||||||
return negative_outstanding_invoices + outstanding_invoices + orders_to_be_billed
|
return negative_outstanding_invoices + outstanding_invoices + orders_to_be_billed
|
||||||
|
|
||||||
def get_orders_to_be_billed(posting_date, party_type, party, party_account_currency, company_currency):
|
def get_orders_to_be_billed(posting_date, party_type, party, party_account_currency, company_currency):
|
||||||
voucher_type = 'Sales Order' if party_type == "Customer" else 'Purchase Order'
|
if party_type == "Customer":
|
||||||
|
voucher_type = 'Sales Order'
|
||||||
|
elif party_type == "Supplier":
|
||||||
|
voucher_type = 'Purchase Order'
|
||||||
|
elif party_type == "Employee":
|
||||||
|
voucher_type = None
|
||||||
|
|
||||||
|
orders = []
|
||||||
|
if voucher_type:
|
||||||
ref_field = "base_grand_total" if party_account_currency == company_currency else "grand_total"
|
ref_field = "base_grand_total" if party_account_currency == company_currency else "grand_total"
|
||||||
|
|
||||||
orders = frappe.db.sql("""
|
orders = frappe.db.sql("""
|
||||||
@ -544,6 +567,7 @@ def get_orders_to_be_billed(posting_date, party_type, party, party_account_curre
|
|||||||
return order_list
|
return order_list
|
||||||
|
|
||||||
def get_negative_outstanding_invoices(party_type, party, party_account, total_field):
|
def get_negative_outstanding_invoices(party_type, party, party_account, total_field):
|
||||||
|
if party_type != "Employee":
|
||||||
voucher_type = "Sales Invoice" if party_type == "Customer" else "Purchase Invoice"
|
voucher_type = "Sales Invoice" if party_type == "Customer" else "Purchase Invoice"
|
||||||
return frappe.db.sql("""
|
return frappe.db.sql("""
|
||||||
select
|
select
|
||||||
@ -562,6 +586,8 @@ def get_negative_outstanding_invoices(party_type, party, party_account, total_fi
|
|||||||
"party_type": scrub(party_type),
|
"party_type": scrub(party_type),
|
||||||
"party_account": "debit_to" if party_type=="Customer" else "credit_to"
|
"party_account": "debit_to" if party_type=="Customer" else "credit_to"
|
||||||
}), (party, party_account), as_dict = True)
|
}), (party, party_account), as_dict = True)
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_party_details(company, party_type, party, date):
|
def get_party_details(company, party_type, party, date):
|
||||||
@ -609,6 +635,9 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre
|
|||||||
|
|
||||||
if reference_doctype != "Journal Entry":
|
if reference_doctype != "Journal Entry":
|
||||||
if party_account_currency == ref_doc.company_currency:
|
if party_account_currency == ref_doc.company_currency:
|
||||||
|
if ref_doc.doctype == "Expense Claim":
|
||||||
|
total_amount = ref_doc.total_sanctioned_amount
|
||||||
|
else:
|
||||||
total_amount = ref_doc.base_grand_total
|
total_amount = ref_doc.base_grand_total
|
||||||
exchange_rate = 1
|
exchange_rate = 1
|
||||||
else:
|
else:
|
||||||
@ -620,7 +649,7 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre
|
|||||||
get_exchange_rate(party_account_currency, ref_doc.company_currency, ref_doc.posting_date)
|
get_exchange_rate(party_account_currency, ref_doc.company_currency, ref_doc.posting_date)
|
||||||
|
|
||||||
outstanding_amount = ref_doc.get("outstanding_amount") \
|
outstanding_amount = ref_doc.get("outstanding_amount") \
|
||||||
if reference_doctype in ("Sales Invoice", "Purchase Invoice") \
|
if reference_doctype in ("Sales Invoice", "Purchase Invoice", "Expense Claim") \
|
||||||
else flt(total_amount) - flt(ref_doc.advance_paid)
|
else flt(total_amount) - flt(ref_doc.advance_paid)
|
||||||
else:
|
else:
|
||||||
# Get the exchange rate based on the posting date of the ref doc
|
# Get the exchange rate based on the posting date of the ref doc
|
||||||
@ -641,7 +670,12 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=
|
|||||||
if dt in ("Sales Order", "Purchase Order") and flt(doc.per_billed, 2) > 0:
|
if dt in ("Sales Order", "Purchase Order") and flt(doc.per_billed, 2) > 0:
|
||||||
frappe.throw(_("Can only make payment against unbilled {0}").format(dt))
|
frappe.throw(_("Can only make payment against unbilled {0}").format(dt))
|
||||||
|
|
||||||
party_type = "Customer" if dt in ("Sales Invoice", "Sales Order") else "Supplier"
|
if dt in ("Sales Invoice", "Sales Order"):
|
||||||
|
party_type = "Customer"
|
||||||
|
elif dt in ("Purchase Invoice", "Purchase Order"):
|
||||||
|
party_type = "Supplier"
|
||||||
|
elif dt in ("Expense Claim"):
|
||||||
|
party_type = "Employee"
|
||||||
|
|
||||||
# party account
|
# party account
|
||||||
if dt == "Sales Invoice":
|
if dt == "Sales Invoice":
|
||||||
@ -667,6 +701,9 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=
|
|||||||
elif dt in ("Sales Invoice", "Purchase Invoice"):
|
elif dt in ("Sales Invoice", "Purchase Invoice"):
|
||||||
grand_total = doc.base_grand_total if party_account_currency == doc.company_currency else doc.grand_total
|
grand_total = doc.base_grand_total if party_account_currency == doc.company_currency else doc.grand_total
|
||||||
outstanding_amount = doc.outstanding_amount
|
outstanding_amount = doc.outstanding_amount
|
||||||
|
elif dt in ("Expense Claim"):
|
||||||
|
grand_total = doc.total_sanctioned_amount
|
||||||
|
outstanding_amount = doc.total_sanctioned_amount - doc.total_amount_reimbursed
|
||||||
else:
|
else:
|
||||||
total_field = "base_grand_total" if party_account_currency == doc.company_currency else "grand_total"
|
total_field = "base_grand_total" if party_account_currency == doc.company_currency else "grand_total"
|
||||||
grand_total = flt(doc.get(total_field))
|
grand_total = flt(doc.get(total_field))
|
||||||
|
@ -10,6 +10,7 @@ from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_orde
|
|||||||
from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry, InvalidPaymentEntry
|
from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry, InvalidPaymentEntry
|
||||||
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
||||||
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
|
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
|
||||||
|
from erpnext.hr.doctype.expense_claim.test_expense_claim import make_expense_claim
|
||||||
|
|
||||||
test_dependencies = ["Item"]
|
test_dependencies = ["Item"]
|
||||||
|
|
||||||
@ -84,6 +85,28 @@ class TestPaymentEntry(unittest.TestCase):
|
|||||||
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", pi.name, "outstanding_amount"))
|
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", pi.name, "outstanding_amount"))
|
||||||
self.assertEqual(outstanding_amount, 0)
|
self.assertEqual(outstanding_amount, 0)
|
||||||
|
|
||||||
|
def test_payment_entry_against_ec(self):
|
||||||
|
|
||||||
|
payable = frappe.db.get_value('Company', "_Test Company", 'default_payable_account')
|
||||||
|
ec = make_expense_claim(payable, 300, 300, "_Test Company","Travel Expenses - _TC")
|
||||||
|
pe = get_payment_entry("Expense Claim", ec.name, bank_account="_Test Bank USD - _TC", bank_amount=300)
|
||||||
|
pe.reference_no = "1"
|
||||||
|
pe.reference_date = "2016-01-01"
|
||||||
|
pe.source_exchange_rate = 1
|
||||||
|
pe.insert()
|
||||||
|
pe.submit()
|
||||||
|
|
||||||
|
expected_gle = dict((d[0], d) for d in [
|
||||||
|
[payable, 300, 0, ec.name],
|
||||||
|
["_Test Bank USD - _TC", 0, 300, None]
|
||||||
|
])
|
||||||
|
|
||||||
|
self.validate_gl_entries(pe.name, expected_gle)
|
||||||
|
|
||||||
|
outstanding_amount = flt(frappe.db.get_value("Expense Claim", ec.name, "total_sanctioned_amount")) - \
|
||||||
|
flt(frappe.db.get_value("Expense Claim", ec.name, "total_amount_reimbursed"))
|
||||||
|
self.assertEqual(outstanding_amount, 0)
|
||||||
|
|
||||||
def test_payment_entry_against_si_usd_to_inr(self):
|
def test_payment_entry_against_si_usd_to_inr(self):
|
||||||
si = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC",
|
si = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC",
|
||||||
currency="USD", conversion_rate=50)
|
currency="USD", conversion_rate=50)
|
||||||
|
@ -621,7 +621,7 @@ def get_outstanding_invoices(party_type, party, account, condition=None):
|
|||||||
'invoice_amount': flt(d.invoice_amount),
|
'invoice_amount': flt(d.invoice_amount),
|
||||||
'payment_amount': flt(d.payment_amount),
|
'payment_amount': flt(d.payment_amount),
|
||||||
'outstanding_amount': flt(d.invoice_amount - d.payment_amount, precision),
|
'outstanding_amount': flt(d.invoice_amount - d.payment_amount, precision),
|
||||||
'due_date': frappe.db.get_value(d.voucher_type, d.voucher_no, "due_date"),
|
'due_date': frappe.db.get_value(d.voucher_type, d.voucher_no, "posting_date") if party_type=="Employee" else frappe.db.get_value(d.voucher_type, d.voucher_no, "due_date"),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
outstanding_invoices = sorted(outstanding_invoices, key=lambda k: k['due_date'] or getdate(nowdate()))
|
outstanding_invoices = sorted(outstanding_invoices, key=lambda k: k['due_date'] or getdate(nowdate()))
|
||||||
|
@ -14,6 +14,7 @@ class TestExpenseClaim(unittest.TestCase):
|
|||||||
frappe.db.sql("""delete from `tabTask` where project = "_Test Project 1" """)
|
frappe.db.sql("""delete from `tabTask` where project = "_Test Project 1" """)
|
||||||
frappe.db.sql("""delete from `tabProject` where name = "_Test Project 1" """)
|
frappe.db.sql("""delete from `tabProject` where name = "_Test Project 1" """)
|
||||||
|
|
||||||
|
|
||||||
frappe.get_doc({
|
frappe.get_doc({
|
||||||
"project_name": "_Test Project 1",
|
"project_name": "_Test Project 1",
|
||||||
"doctype": "Project",
|
"doctype": "Project",
|
||||||
@ -24,52 +25,25 @@ class TestExpenseClaim(unittest.TestCase):
|
|||||||
task_name = frappe.db.get_value("Task", {"project": "_Test Project 1"})
|
task_name = frappe.db.get_value("Task", {"project": "_Test Project 1"})
|
||||||
payable_account = get_payable_account("Wind Power LLC")
|
payable_account = get_payable_account("Wind Power LLC")
|
||||||
|
|
||||||
expense_claim = frappe.get_doc({
|
expense_claim = make_expense_claim(payable_account, 300, 200, "Wind Power LLC","Travel Expenses - WP", "_Test Project 1", task_name)
|
||||||
"doctype": "Expense Claim",
|
|
||||||
"employee": "_T-Employee-0001",
|
|
||||||
"payable_account": payable_account,
|
|
||||||
"approval_status": "Approved",
|
|
||||||
"project": "_Test Project 1",
|
|
||||||
"task": task_name,
|
|
||||||
"expenses":
|
|
||||||
[{ "expense_type": "Travel", "default_account": "Travel Expenses - WP", "claim_amount": 300, "sanctioned_amount": 200 }]
|
|
||||||
})
|
|
||||||
expense_claim.submit()
|
|
||||||
|
|
||||||
self.assertEqual(frappe.db.get_value("Task", task_name, "total_expense_claim"), 200)
|
self.assertEqual(frappe.db.get_value("Task", task_name, "total_expense_claim"), 200)
|
||||||
self.assertEqual(frappe.db.get_value("Project", "_Test Project 1", "total_expense_claim"), 200)
|
self.assertEqual(frappe.db.get_value("Project", "_Test Project 1", "total_expense_claim"), 200)
|
||||||
|
|
||||||
expense_claim2 = frappe.get_doc({
|
expense_claim2 = make_expense_claim(payable_account, 600, 500, "Wind Power LLC", "Travel Expenses - WP","_Test Project 1", task_name)
|
||||||
"doctype": "Expense Claim",
|
|
||||||
"employee": "_T-Employee-0001",
|
|
||||||
"approval_status": "Approved",
|
|
||||||
"project": "_Test Project 1",
|
|
||||||
"task": task_name,
|
|
||||||
"expenses":
|
|
||||||
[{ "expense_type": "Travel", "default_account": "Travel Expenses - WP", "claim_amount": 600, "sanctioned_amount": 500 }]
|
|
||||||
})
|
|
||||||
expense_claim2.submit()
|
|
||||||
|
|
||||||
self.assertEqual(frappe.db.get_value("Task", task_name, "total_expense_claim"), 700)
|
self.assertEqual(frappe.db.get_value("Task", task_name, "total_expense_claim"), 700)
|
||||||
self.assertEqual(frappe.db.get_value("Project", "_Test Project 1", "total_expense_claim"), 700)
|
self.assertEqual(frappe.db.get_value("Project", "_Test Project 1", "total_expense_claim"), 700)
|
||||||
|
|
||||||
expense_claim2.cancel()
|
expense_claim2.cancel()
|
||||||
frappe.delete_doc("Expenses Claim", expense_claim2.name)
|
frappe.delete_doc("Expense Claim", expense_claim2.name)
|
||||||
|
|
||||||
self.assertEqual(frappe.db.get_value("Task", task_name, "total_expense_claim"), 200)
|
self.assertEqual(frappe.db.get_value("Task", task_name, "total_expense_claim"), 200)
|
||||||
self.assertEqual(frappe.db.get_value("Project", "_Test Project 1", "total_expense_claim"), 200)
|
self.assertEqual(frappe.db.get_value("Project", "_Test Project 1", "total_expense_claim"), 200)
|
||||||
|
|
||||||
def test_expense_claim_status(self):
|
def test_expense_claim_status(self):
|
||||||
payable_account = get_payable_account("Wind Power LLC")
|
payable_account = get_payable_account("Wind Power LLC")
|
||||||
expense_claim = frappe.get_doc({
|
expense_claim = make_expense_claim(payable_account, 300, 200, "Wind Power LLC", "Travel Expenses - WP")
|
||||||
"doctype": "Expense Claim",
|
|
||||||
"employee": "_T-Employee-0001",
|
|
||||||
"payable_account": payable_account,
|
|
||||||
"approval_status": "Approved",
|
|
||||||
"expenses":
|
|
||||||
[{ "expense_type": "Travel", "default_account": "Travel Expenses - WP", "claim_amount": 300, "sanctioned_amount": 200 }]
|
|
||||||
})
|
|
||||||
expense_claim.submit()
|
|
||||||
|
|
||||||
je_dict = make_bank_entry(expense_claim.name)
|
je_dict = make_bank_entry(expense_claim.name)
|
||||||
je = frappe.get_doc(je_dict)
|
je = frappe.get_doc(je_dict)
|
||||||
@ -87,14 +61,7 @@ class TestExpenseClaim(unittest.TestCase):
|
|||||||
|
|
||||||
def test_expense_claim_gl_entry(self):
|
def test_expense_claim_gl_entry(self):
|
||||||
payable_account = get_payable_account("Wind Power LLC")
|
payable_account = get_payable_account("Wind Power LLC")
|
||||||
expense_claim = frappe.get_doc({
|
expense_claim = make_expense_claim(payable_account, 300, 200, "Wind Power LLC", "Travel Expenses - WP")
|
||||||
"doctype": "Expense Claim",
|
|
||||||
"employee": "_T-Employee-0001",
|
|
||||||
"payable_account": payable_account,
|
|
||||||
"approval_status": "Approved",
|
|
||||||
"expenses":
|
|
||||||
[{ "expense_type": "Travel", "default_account": "Travel Expenses - WP", "claim_amount": 300, "sanctioned_amount": 200 }]
|
|
||||||
})
|
|
||||||
expense_claim.submit()
|
expense_claim.submit()
|
||||||
|
|
||||||
gl_entries = frappe.db.sql("""select account, debit, credit
|
gl_entries = frappe.db.sql("""select account, debit, credit
|
||||||
@ -133,3 +100,23 @@ class TestExpenseClaim(unittest.TestCase):
|
|||||||
|
|
||||||
def get_payable_account(company):
|
def get_payable_account(company):
|
||||||
return frappe.db.get_value('Company', company, 'default_payable_account')
|
return frappe.db.get_value('Company', company, 'default_payable_account')
|
||||||
|
|
||||||
|
def make_expense_claim(payable_account,claim_amount, sanctioned_amount, company, account, project=None, task_name=None):
|
||||||
|
expense_claim = frappe.get_doc({
|
||||||
|
"doctype": "Expense Claim",
|
||||||
|
"employee": "_T-Employee-0001",
|
||||||
|
"payable_account": payable_account,
|
||||||
|
"approval_status": "Approved",
|
||||||
|
"company": company,
|
||||||
|
"expenses":
|
||||||
|
[{ "expense_type": "Travel", "default_account": account, "claim_amount": claim_amount, "sanctioned_amount": sanctioned_amount }]
|
||||||
|
})
|
||||||
|
if project:
|
||||||
|
expense_claim.project = project
|
||||||
|
if task_name:
|
||||||
|
expense_claim.task = task_name
|
||||||
|
|
||||||
|
expense_claim.submit()
|
||||||
|
return expense_claim
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user