Update manuals. Fix codacy issues
This commit is contained in:
parent
118ceda46f
commit
38d4be8325
@ -18,21 +18,21 @@ from erpnext.controllers.accounts_controller import AccountsController
|
|||||||
class InvalidPaymentEntry(ValidationError): pass
|
class InvalidPaymentEntry(ValidationError): pass
|
||||||
|
|
||||||
class PaymentEntry(AccountsController):
|
class PaymentEntry(AccountsController):
|
||||||
def setup_party_account_field(self):
|
def setup_party_account_field(self):
|
||||||
self.party_account_field = None
|
self.party_account_field = None
|
||||||
self.party_account = None
|
self.party_account = None
|
||||||
self.party_account_currency = None
|
self.party_account_currency = None
|
||||||
|
|
||||||
if self.payment_type == "Receive":
|
if self.payment_type == "Receive":
|
||||||
self.party_account_field = "paid_from"
|
self.party_account_field = "paid_from"
|
||||||
self.party_account = self.paid_from
|
self.party_account = self.paid_from
|
||||||
self.party_account_currency = self.paid_from_account_currency
|
self.party_account_currency = self.paid_from_account_currency
|
||||||
|
|
||||||
elif self.payment_type == "Pay":
|
elif self.payment_type == "Pay":
|
||||||
self.party_account_field = "paid_to"
|
self.party_account_field = "paid_to"
|
||||||
self.party_account = self.paid_to
|
self.party_account = self.paid_to
|
||||||
self.party_account_currency = self.paid_to_account_currency
|
self.party_account_currency = self.paid_to_account_currency
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.setup_party_account_field()
|
self.setup_party_account_field()
|
||||||
self.set_missing_values()
|
self.set_missing_values()
|
||||||
@ -50,7 +50,7 @@ class PaymentEntry(AccountsController):
|
|||||||
self.set_remarks()
|
self.set_remarks()
|
||||||
self.validate_duplicate_entry()
|
self.validate_duplicate_entry()
|
||||||
self.validate_allocated_amount()
|
self.validate_allocated_amount()
|
||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
self.setup_party_account_field()
|
self.setup_party_account_field()
|
||||||
if self.difference_amount:
|
if self.difference_amount:
|
||||||
@ -58,7 +58,7 @@ class PaymentEntry(AccountsController):
|
|||||||
self.make_gl_entries()
|
self.make_gl_entries()
|
||||||
self.update_advance_paid()
|
self.update_advance_paid()
|
||||||
self.update_expense_claim()
|
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)
|
||||||
@ -72,8 +72,8 @@ class PaymentEntry(AccountsController):
|
|||||||
if (d.reference_doctype, d.reference_name) in reference_names:
|
if (d.reference_doctype, d.reference_name) in reference_names:
|
||||||
frappe.throw(_("Row #{0}: Duplicate entry in References {1} {2}").format(d.idx, d.reference_doctype, d.reference_name))
|
frappe.throw(_("Row #{0}: Duplicate entry in References {1} {2}").format(d.idx, d.reference_doctype, d.reference_name))
|
||||||
reference_names.append((d.reference_doctype, d.reference_name))
|
reference_names.append((d.reference_doctype, d.reference_name))
|
||||||
|
|
||||||
|
|
||||||
def validate_allocated_amount(self):
|
def validate_allocated_amount(self):
|
||||||
for d in self.get("references"):
|
for d in self.get("references"):
|
||||||
if (flt(d.allocated_amount))> 0:
|
if (flt(d.allocated_amount))> 0:
|
||||||
@ -89,98 +89,98 @@ class PaymentEntry(AccountsController):
|
|||||||
|
|
||||||
def set_missing_values(self):
|
def set_missing_values(self):
|
||||||
if self.payment_type == "Internal Transfer":
|
if self.payment_type == "Internal Transfer":
|
||||||
for field in ("party", "party_balance", "total_allocated_amount",
|
for field in ("party", "party_balance", "total_allocated_amount",
|
||||||
"base_total_allocated_amount", "unallocated_amount"):
|
"base_total_allocated_amount", "unallocated_amount"):
|
||||||
self.set(field, None)
|
self.set(field, None)
|
||||||
self.references = []
|
self.references = []
|
||||||
else:
|
else:
|
||||||
if not self.party_type:
|
if not self.party_type:
|
||||||
frappe.throw(_("Party Type is mandatory"))
|
frappe.throw(_("Party Type is mandatory"))
|
||||||
|
|
||||||
if not self.party:
|
if not self.party:
|
||||||
frappe.throw(_("Party is mandatory"))
|
frappe.throw(_("Party is mandatory"))
|
||||||
|
|
||||||
self.party_name = frappe.db.get_value(self.party_type, self.party,
|
self.party_name = frappe.db.get_value(self.party_type, self.party,
|
||||||
self.party_type.lower() + "_name")
|
self.party_type.lower() + "_name")
|
||||||
|
|
||||||
if self.party:
|
if self.party:
|
||||||
if not self.party_balance:
|
if not self.party_balance:
|
||||||
self.party_balance = get_balance_on(party_type=self.party_type,
|
self.party_balance = get_balance_on(party_type=self.party_type,
|
||||||
party=self.party, date=self.posting_date, company=self.company)
|
party=self.party, date=self.posting_date, company=self.company)
|
||||||
|
|
||||||
if not self.party_account:
|
if not self.party_account:
|
||||||
party_account = get_party_account(self.party_type, self.party, self.company)
|
party_account = get_party_account(self.party_type, self.party, self.company)
|
||||||
self.set(self.party_account_field, party_account)
|
self.set(self.party_account_field, party_account)
|
||||||
self.party_account = party_account
|
self.party_account = party_account
|
||||||
|
|
||||||
if self.paid_from and not (self.paid_from_account_currency or self.paid_from_account_balance):
|
if self.paid_from and not (self.paid_from_account_currency or self.paid_from_account_balance):
|
||||||
acc = get_account_details(self.paid_from, self.posting_date)
|
acc = get_account_details(self.paid_from, self.posting_date)
|
||||||
self.paid_from_account_currency = acc.account_currency
|
self.paid_from_account_currency = acc.account_currency
|
||||||
self.paid_from_account_balance = acc.account_balance
|
self.paid_from_account_balance = acc.account_balance
|
||||||
|
|
||||||
if self.paid_to and not (self.paid_to_account_currency or self.paid_to_account_balance):
|
if self.paid_to and not (self.paid_to_account_currency or self.paid_to_account_balance):
|
||||||
acc = get_account_details(self.paid_to, self.posting_date)
|
acc = get_account_details(self.paid_to, self.posting_date)
|
||||||
self.paid_to_account_currency = acc.account_currency
|
self.paid_to_account_currency = acc.account_currency
|
||||||
self.paid_to_account_balance = acc.account_balance
|
self.paid_to_account_balance = acc.account_balance
|
||||||
|
|
||||||
self.party_account_currency = self.paid_from_account_currency \
|
self.party_account_currency = self.paid_from_account_currency \
|
||||||
if self.payment_type=="Receive" else self.paid_to_account_currency
|
if self.payment_type=="Receive" else self.paid_to_account_currency
|
||||||
|
|
||||||
self.set_missing_ref_details()
|
self.set_missing_ref_details()
|
||||||
|
|
||||||
|
|
||||||
def set_missing_ref_details(self):
|
def set_missing_ref_details(self):
|
||||||
for d in self.get("references"):
|
for d in self.get("references"):
|
||||||
if d.allocated_amount:
|
if d.allocated_amount:
|
||||||
ref_details = get_reference_details(d.reference_doctype,
|
ref_details = get_reference_details(d.reference_doctype,
|
||||||
d.reference_name, self.party_account_currency)
|
d.reference_name, self.party_account_currency)
|
||||||
|
|
||||||
for field, value in ref_details.items():
|
for field, value in ref_details.items():
|
||||||
if not d.get(field):
|
if not d.get(field):
|
||||||
d.set(field, value)
|
d.set(field, value)
|
||||||
|
|
||||||
def validate_payment_type(self):
|
def validate_payment_type(self):
|
||||||
if self.payment_type not in ("Receive", "Pay", "Internal Transfer"):
|
if self.payment_type not in ("Receive", "Pay", "Internal Transfer"):
|
||||||
frappe.throw(_("Payment Type must be one of Receive, Pay and Internal Transfer"))
|
frappe.throw(_("Payment Type must be one of Receive, Pay and Internal Transfer"))
|
||||||
|
|
||||||
def validate_party_details(self):
|
def validate_party_details(self):
|
||||||
if self.party:
|
if self.party:
|
||||||
if not frappe.db.exists(self.party_type, self.party):
|
if not frappe.db.exists(self.party_type, self.party):
|
||||||
frappe.throw(_("Invalid {0}: {1}").format(self.party_type, self.party))
|
frappe.throw(_("Invalid {0}: {1}").format(self.party_type, self.party))
|
||||||
|
|
||||||
if self.party_account:
|
if self.party_account:
|
||||||
party_account_type = "Receivable" if self.party_type=="Customer" else "Payable"
|
party_account_type = "Receivable" if self.party_type=="Customer" else "Payable"
|
||||||
self.validate_account_type(self.party_account, [party_account_type])
|
self.validate_account_type(self.party_account, [party_account_type])
|
||||||
|
|
||||||
def validate_bank_accounts(self):
|
def validate_bank_accounts(self):
|
||||||
if self.payment_type in ("Pay", "Internal Transfer"):
|
if self.payment_type in ("Pay", "Internal Transfer"):
|
||||||
self.validate_account_type(self.paid_from, ["Bank", "Cash"])
|
self.validate_account_type(self.paid_from, ["Bank", "Cash"])
|
||||||
|
|
||||||
if self.payment_type in ("Receive", "Internal Transfer"):
|
if self.payment_type in ("Receive", "Internal Transfer"):
|
||||||
self.validate_account_type(self.paid_to, ["Bank", "Cash"])
|
self.validate_account_type(self.paid_to, ["Bank", "Cash"])
|
||||||
|
|
||||||
def validate_account_type(self, account, account_types):
|
def validate_account_type(self, account, account_types):
|
||||||
account_type = frappe.db.get_value("Account", account, "account_type")
|
account_type = frappe.db.get_value("Account", account, "account_type")
|
||||||
if account_type not in account_types:
|
if account_type not in account_types:
|
||||||
frappe.throw(_("Account Type for {0} must be {1}").format(account, comma_or(account_types)))
|
frappe.throw(_("Account Type for {0} must be {1}").format(account, comma_or(account_types)))
|
||||||
|
|
||||||
def set_exchange_rate(self):
|
def set_exchange_rate(self):
|
||||||
if self.paid_from and not self.source_exchange_rate:
|
if self.paid_from and not self.source_exchange_rate:
|
||||||
if self.paid_from_account_currency == self.company_currency:
|
if self.paid_from_account_currency == self.company_currency:
|
||||||
self.source_exchange_rate = 1
|
self.source_exchange_rate = 1
|
||||||
else:
|
else:
|
||||||
self.source_exchange_rate = get_exchange_rate(self.paid_from_account_currency,
|
self.source_exchange_rate = get_exchange_rate(self.paid_from_account_currency,
|
||||||
self.company_currency, self.posting_date)
|
self.company_currency, self.posting_date)
|
||||||
|
|
||||||
if self.paid_to and not self.target_exchange_rate:
|
if self.paid_to and not self.target_exchange_rate:
|
||||||
self.target_exchange_rate = get_exchange_rate(self.paid_to_account_currency,
|
self.target_exchange_rate = get_exchange_rate(self.paid_to_account_currency,
|
||||||
self.company_currency, self.posting_date)
|
self.company_currency, self.posting_date)
|
||||||
|
|
||||||
def validate_mandatory(self):
|
def validate_mandatory(self):
|
||||||
for field in ("paid_amount", "received_amount", "source_exchange_rate", "target_exchange_rate"):
|
for field in ("paid_amount", "received_amount", "source_exchange_rate", "target_exchange_rate"):
|
||||||
if not self.get(field):
|
if not self.get(field):
|
||||||
frappe.throw(_("{0} is mandatory").format(self.meta.get_label(field)))
|
frappe.throw(_("{0} is mandatory").format(self.meta.get_label(field)))
|
||||||
|
|
||||||
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")
|
||||||
@ -195,7 +195,7 @@ class PaymentEntry(AccountsController):
|
|||||||
if d.reference_doctype not in valid_reference_doctypes:
|
if d.reference_doctype not in valid_reference_doctypes:
|
||||||
frappe.throw(_("Reference Doctype must be one of {0}")
|
frappe.throw(_("Reference Doctype must be one of {0}")
|
||||||
.format(comma_or(valid_reference_doctypes)))
|
.format(comma_or(valid_reference_doctypes)))
|
||||||
|
|
||||||
elif d.reference_name:
|
elif d.reference_name:
|
||||||
if not frappe.db.exists(d.reference_doctype, d.reference_name):
|
if not frappe.db.exists(d.reference_doctype, d.reference_name):
|
||||||
frappe.throw(_("{0} {1} does not exist").format(d.reference_doctype, d.reference_name))
|
frappe.throw(_("{0} {1} does not exist").format(d.reference_doctype, d.reference_name))
|
||||||
@ -208,7 +208,7 @@ class PaymentEntry(AccountsController):
|
|||||||
.format(d.reference_doctype, d.reference_name, self.party_type, self.party))
|
.format(d.reference_doctype, d.reference_name, self.party_type, self.party))
|
||||||
else:
|
else:
|
||||||
self.validate_journal_entry()
|
self.validate_journal_entry()
|
||||||
|
|
||||||
if d.reference_doctype in ("Sales Invoice", "Purchase Invoice", "Expense Claim"):
|
if d.reference_doctype in ("Sales Invoice", "Purchase Invoice", "Expense Claim"):
|
||||||
if self.party_type=="Customer":
|
if self.party_type=="Customer":
|
||||||
ref_party_account = ref_doc.debit_to
|
ref_party_account = ref_doc.debit_to
|
||||||
@ -216,18 +216,18 @@ class PaymentEntry(AccountsController):
|
|||||||
ref_party_account = ref_doc.credit_to
|
ref_party_account = ref_doc.credit_to
|
||||||
elif self.party_type=="Employee":
|
elif self.party_type=="Employee":
|
||||||
ref_party_account = ref_doc.payable_account
|
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} is associated with {2}, but Party Account is {3}")
|
frappe.throw(_("{0} {1} is associated with {2}, but Party Account is {3}")
|
||||||
.format(d.reference_doctype, d.reference_name, ref_party_account, 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")
|
||||||
.format(d.reference_doctype, d.reference_name))
|
.format(d.reference_doctype, d.reference_name))
|
||||||
|
|
||||||
def validate_journal_entry(self):
|
def validate_journal_entry(self):
|
||||||
for d in self.get("references"):
|
for d in self.get("references"):
|
||||||
if d.allocated_amount and d.reference_doctype == "Journal Entry":
|
if d.allocated_amount and d.reference_doctype == "Journal Entry":
|
||||||
je_accounts = frappe.db.sql("""select debit, credit from `tabJournal Entry Account`
|
je_accounts = frappe.db.sql("""select debit, credit from `tabJournal Entry Account`
|
||||||
where account = %s and party=%s and docstatus = 1 and parent = %s
|
where account = %s and party=%s and docstatus = 1 and parent = %s
|
||||||
and (reference_type is null or reference_type in ("", "Sales Order", "Purchase Order"))
|
and (reference_type is null or reference_type in ("", "Sales Order", "Purchase Order"))
|
||||||
@ -245,7 +245,7 @@ class PaymentEntry(AccountsController):
|
|||||||
if not valid:
|
if not valid:
|
||||||
frappe.throw(_("Against Journal Entry {0} does not have any unmatched {1} entry")
|
frappe.throw(_("Against Journal Entry {0} does not have any unmatched {1} entry")
|
||||||
.format(d.reference_name, dr_or_cr))
|
.format(d.reference_name, dr_or_cr))
|
||||||
|
|
||||||
def set_amounts(self):
|
def set_amounts(self):
|
||||||
self.set_amounts_in_company_currency()
|
self.set_amounts_in_company_currency()
|
||||||
self.set_total_allocated_amount()
|
self.set_total_allocated_amount()
|
||||||
@ -255,111 +255,111 @@ class PaymentEntry(AccountsController):
|
|||||||
def set_amounts_in_company_currency(self):
|
def set_amounts_in_company_currency(self):
|
||||||
self.base_paid_amount, self.base_received_amount, self.difference_amount = 0, 0, 0
|
self.base_paid_amount, self.base_received_amount, self.difference_amount = 0, 0, 0
|
||||||
if self.paid_amount:
|
if self.paid_amount:
|
||||||
self.base_paid_amount = flt(flt(self.paid_amount) * flt(self.source_exchange_rate),
|
self.base_paid_amount = flt(flt(self.paid_amount) * flt(self.source_exchange_rate),
|
||||||
self.precision("base_paid_amount"))
|
self.precision("base_paid_amount"))
|
||||||
|
|
||||||
if self.received_amount:
|
if self.received_amount:
|
||||||
self.base_received_amount = flt(flt(self.received_amount) * flt(self.target_exchange_rate),
|
self.base_received_amount = flt(flt(self.received_amount) * flt(self.target_exchange_rate),
|
||||||
self.precision("base_received_amount"))
|
self.precision("base_received_amount"))
|
||||||
|
|
||||||
def set_total_allocated_amount(self):
|
def set_total_allocated_amount(self):
|
||||||
if self.payment_type == "Internal Transfer":
|
if self.payment_type == "Internal Transfer":
|
||||||
return
|
return
|
||||||
|
|
||||||
total_allocated_amount, base_total_allocated_amount = 0, 0
|
total_allocated_amount, base_total_allocated_amount = 0, 0
|
||||||
for d in self.get("references"):
|
for d in self.get("references"):
|
||||||
if d.allocated_amount:
|
if d.allocated_amount:
|
||||||
total_allocated_amount += flt(d.allocated_amount)
|
total_allocated_amount += flt(d.allocated_amount)
|
||||||
base_total_allocated_amount += flt(flt(d.allocated_amount) * flt(d.exchange_rate),
|
base_total_allocated_amount += flt(flt(d.allocated_amount) * flt(d.exchange_rate),
|
||||||
self.precision("base_paid_amount"))
|
self.precision("base_paid_amount"))
|
||||||
|
|
||||||
self.total_allocated_amount = abs(total_allocated_amount)
|
self.total_allocated_amount = abs(total_allocated_amount)
|
||||||
self.base_total_allocated_amount = abs(base_total_allocated_amount)
|
self.base_total_allocated_amount = abs(base_total_allocated_amount)
|
||||||
|
|
||||||
def set_unallocated_amount(self):
|
def set_unallocated_amount(self):
|
||||||
self.unallocated_amount = 0;
|
self.unallocated_amount = 0;
|
||||||
if self.party:
|
if self.party:
|
||||||
party_amount = self.paid_amount if self.payment_type=="Receive" else self.received_amount
|
party_amount = self.paid_amount if self.payment_type=="Receive" else self.received_amount
|
||||||
|
|
||||||
total_deductions = sum([flt(d.amount) for d in self.get("deductions")])
|
total_deductions = sum([flt(d.amount) for d in self.get("deductions")])
|
||||||
|
|
||||||
if self.total_allocated_amount < party_amount:
|
if self.total_allocated_amount < party_amount:
|
||||||
if self.payment_type == "Receive":
|
if self.payment_type == "Receive":
|
||||||
self.unallocated_amount = party_amount - (self.total_allocated_amount - total_deductions)
|
self.unallocated_amount = party_amount - (self.total_allocated_amount - total_deductions)
|
||||||
else:
|
else:
|
||||||
self.unallocated_amount = party_amount - (self.total_allocated_amount + total_deductions)
|
self.unallocated_amount = party_amount - (self.total_allocated_amount + total_deductions)
|
||||||
|
|
||||||
def set_difference_amount(self):
|
def set_difference_amount(self):
|
||||||
base_unallocated_amount = flt(self.unallocated_amount) * (flt(self.source_exchange_rate)
|
base_unallocated_amount = flt(self.unallocated_amount) * (flt(self.source_exchange_rate)
|
||||||
if self.payment_type=="Receive" else flt(self.target_exchange_rate))
|
if self.payment_type=="Receive" else flt(self.target_exchange_rate))
|
||||||
|
|
||||||
base_party_amount = flt(self.base_total_allocated_amount) + flt(base_unallocated_amount)
|
base_party_amount = flt(self.base_total_allocated_amount) + flt(base_unallocated_amount)
|
||||||
|
|
||||||
if self.payment_type == "Receive":
|
if self.payment_type == "Receive":
|
||||||
self.difference_amount = base_party_amount - self.base_received_amount
|
self.difference_amount = base_party_amount - self.base_received_amount
|
||||||
elif self.payment_type == "Pay":
|
elif self.payment_type == "Pay":
|
||||||
self.difference_amount = self.base_paid_amount - base_party_amount
|
self.difference_amount = self.base_paid_amount - base_party_amount
|
||||||
else:
|
else:
|
||||||
self.difference_amount = self.base_paid_amount - flt(self.base_received_amount)
|
self.difference_amount = self.base_paid_amount - flt(self.base_received_amount)
|
||||||
|
|
||||||
for d in self.get("deductions"):
|
for d in self.get("deductions"):
|
||||||
if d.amount:
|
if d.amount:
|
||||||
self.difference_amount -= flt(d.amount)
|
self.difference_amount -= flt(d.amount)
|
||||||
|
|
||||||
self.difference_amount = flt(self.difference_amount, self.precision("difference_amount"))
|
self.difference_amount = flt(self.difference_amount, self.precision("difference_amount"))
|
||||||
|
|
||||||
def clear_unallocated_reference_document_rows(self):
|
def clear_unallocated_reference_document_rows(self):
|
||||||
self.set("references", self.get("references", {"allocated_amount": ["not in", [0, None, ""]]}))
|
self.set("references", self.get("references", {"allocated_amount": ["not in", [0, None, ""]]}))
|
||||||
|
|
||||||
frappe.db.sql("""delete from `tabPayment Entry Reference`
|
frappe.db.sql("""delete from `tabPayment Entry Reference`
|
||||||
where parent = %s and allocated_amount = 0""", self.name)
|
where parent = %s and allocated_amount = 0""", self.name)
|
||||||
|
|
||||||
def validate_payment_against_negative_invoice(self):
|
def validate_payment_against_negative_invoice(self):
|
||||||
if ((self.payment_type=="Pay" and self.party_type=="Customer")
|
if ((self.payment_type=="Pay" and self.party_type=="Customer")
|
||||||
or (self.payment_type=="Receive" and self.party_type=="Supplier")):
|
or (self.payment_type=="Receive" and self.party_type=="Supplier")):
|
||||||
|
|
||||||
total_negative_outstanding = sum([abs(flt(d.outstanding_amount))
|
total_negative_outstanding = sum([abs(flt(d.outstanding_amount))
|
||||||
for d in self.get("references") if flt(d.outstanding_amount) < 0])
|
for d in self.get("references") if flt(d.outstanding_amount) < 0])
|
||||||
|
|
||||||
party_amount = self.paid_amount if self.payment_type=="Receive" else self.received_amount
|
party_amount = self.paid_amount if self.payment_type=="Receive" else self.received_amount
|
||||||
|
|
||||||
if not total_negative_outstanding:
|
if not total_negative_outstanding:
|
||||||
frappe.throw(_("Cannot {0} {1} {2} without any negative outstanding invoice")
|
frappe.throw(_("Cannot {0} {1} {2} without any negative outstanding invoice")
|
||||||
.format(self.payment_type, ("to" if self.party_type=="Customer" else "from"),
|
.format(self.payment_type, ("to" if self.party_type=="Customer" else "from"),
|
||||||
self.party_type), InvalidPaymentEntry)
|
self.party_type), InvalidPaymentEntry)
|
||||||
|
|
||||||
elif party_amount > total_negative_outstanding:
|
elif party_amount > total_negative_outstanding:
|
||||||
frappe.throw(_("Paid Amount cannot be greater than total negative outstanding amount {0}")
|
frappe.throw(_("Paid Amount cannot be greater than total negative outstanding amount {0}")
|
||||||
.format(total_negative_outstanding), InvalidPaymentEntry)
|
.format(total_negative_outstanding), InvalidPaymentEntry)
|
||||||
|
|
||||||
def set_title(self):
|
def set_title(self):
|
||||||
if self.payment_type in ("Receive", "Pay"):
|
if self.payment_type in ("Receive", "Pay"):
|
||||||
self.title = self.party
|
self.title = self.party
|
||||||
else:
|
else:
|
||||||
self.title = self.paid_from + " - " + self.paid_to
|
self.title = self.paid_from + " - " + self.paid_to
|
||||||
|
|
||||||
def validate_transaction_reference(self):
|
def validate_transaction_reference(self):
|
||||||
bank_account = self.paid_to if self.payment_type == "Receive" else self.paid_from
|
bank_account = self.paid_to if self.payment_type == "Receive" else self.paid_from
|
||||||
bank_account_type = frappe.db.get_value("Account", bank_account, "account_type")
|
bank_account_type = frappe.db.get_value("Account", bank_account, "account_type")
|
||||||
|
|
||||||
if bank_account_type == "Bank":
|
if bank_account_type == "Bank":
|
||||||
if not self.reference_no or not self.reference_date:
|
if not self.reference_no or not self.reference_date:
|
||||||
frappe.throw(_("Reference No and Reference Date is mandatory for Bank transaction"))
|
frappe.throw(_("Reference No and Reference Date is mandatory for Bank transaction"))
|
||||||
|
|
||||||
def set_remarks(self):
|
def set_remarks(self):
|
||||||
if self.remarks: return
|
if self.remarks: return
|
||||||
|
|
||||||
if self.payment_type=="Internal Transfer":
|
if self.payment_type=="Internal Transfer":
|
||||||
remarks = [_("Amount {0} {1} transferred from {2} to {3}")
|
remarks = [_("Amount {0} {1} transferred from {2} to {3}")
|
||||||
.format(self.paid_from_account_currency, self.paid_amount, self.paid_from, self.paid_to)]
|
.format(self.paid_from_account_currency, self.paid_amount, self.paid_from, self.paid_to)]
|
||||||
else:
|
else:
|
||||||
|
|
||||||
remarks = [_("Amount {0} {1} {2} {3}").format(
|
remarks = [_("Amount {0} {1} {2} {3}").format(
|
||||||
self.party_account_currency,
|
self.party_account_currency,
|
||||||
self.paid_amount if self.payment_type=="Receive" else self.received_amount,
|
self.paid_amount if self.payment_type=="Receive" else self.received_amount,
|
||||||
_("received from") if self.payment_type=="Receive" else _("to"), self.party
|
_("received from") if self.payment_type=="Receive" else _("to"), self.party
|
||||||
)]
|
)]
|
||||||
|
|
||||||
if self.reference_no:
|
if self.reference_no:
|
||||||
remarks.append(_("Transaction reference no {0} dated {1}")
|
remarks.append(_("Transaction reference no {0} dated {1}")
|
||||||
.format(self.reference_no, self.reference_date))
|
.format(self.reference_no, self.reference_date))
|
||||||
@ -367,35 +367,35 @@ class PaymentEntry(AccountsController):
|
|||||||
if self.payment_type in ["Receive", "Pay"]:
|
if self.payment_type in ["Receive", "Pay"]:
|
||||||
for d in self.get("references"):
|
for d in self.get("references"):
|
||||||
if d.allocated_amount:
|
if d.allocated_amount:
|
||||||
remarks.append(_("Amount {0} {1} against {2} {3}").format(self.party_account_currency,
|
remarks.append(_("Amount {0} {1} against {2} {3}").format(self.party_account_currency,
|
||||||
d.allocated_amount, d.reference_doctype, d.reference_name))
|
d.allocated_amount, d.reference_doctype, d.reference_name))
|
||||||
|
|
||||||
for d in self.get("deductions"):
|
for d in self.get("deductions"):
|
||||||
if d.amount:
|
if d.amount:
|
||||||
remarks.append(_("Amount {0} {1} deducted against {2}")
|
remarks.append(_("Amount {0} {1} deducted against {2}")
|
||||||
.format(self.company_currency, d.amount, d.account))
|
.format(self.company_currency, d.amount, d.account))
|
||||||
|
|
||||||
self.set("remarks", "\n".join(remarks))
|
self.set("remarks", "\n".join(remarks))
|
||||||
|
|
||||||
def make_gl_entries(self, cancel=0, adv_adj=0):
|
def make_gl_entries(self, cancel=0, adv_adj=0):
|
||||||
if self.payment_type in ("Receive", "Pay") and not self.get("party_account_field"):
|
if self.payment_type in ("Receive", "Pay") and not self.get("party_account_field"):
|
||||||
self.setup_party_account_field()
|
self.setup_party_account_field()
|
||||||
|
|
||||||
gl_entries = []
|
gl_entries = []
|
||||||
self.add_party_gl_entries(gl_entries)
|
self.add_party_gl_entries(gl_entries)
|
||||||
self.add_bank_gl_entries(gl_entries)
|
self.add_bank_gl_entries(gl_entries)
|
||||||
self.add_deductions_gl_entries(gl_entries)
|
self.add_deductions_gl_entries(gl_entries)
|
||||||
|
|
||||||
make_gl_entries(gl_entries, cancel=cancel, adv_adj=adv_adj)
|
make_gl_entries(gl_entries, cancel=cancel, adv_adj=adv_adj)
|
||||||
|
|
||||||
def add_party_gl_entries(self, gl_entries):
|
def add_party_gl_entries(self, gl_entries):
|
||||||
if self.party_account:
|
if self.party_account:
|
||||||
if self.payment_type=="Receive":
|
if self.payment_type=="Receive":
|
||||||
against_account = self.paid_to
|
against_account = self.paid_to
|
||||||
else:
|
else:
|
||||||
against_account = self.paid_from
|
against_account = self.paid_from
|
||||||
|
|
||||||
|
|
||||||
party_gl_dict = self.get_gl_dict({
|
party_gl_dict = self.get_gl_dict({
|
||||||
"account": self.party_account,
|
"account": self.party_account,
|
||||||
"party_type": self.party_type,
|
"party_type": self.party_type,
|
||||||
@ -403,39 +403,39 @@ class PaymentEntry(AccountsController):
|
|||||||
"against": against_account,
|
"against": against_account,
|
||||||
"account_currency": self.party_account_currency
|
"account_currency": self.party_account_currency
|
||||||
})
|
})
|
||||||
|
|
||||||
dr_or_cr = "credit" if self.party_type == "Customer" else "debit"
|
dr_or_cr = "credit" if self.party_type == "Customer" else "debit"
|
||||||
|
|
||||||
for d in self.get("references"):
|
for d in self.get("references"):
|
||||||
gle = party_gl_dict.copy()
|
gle = party_gl_dict.copy()
|
||||||
gle.update({
|
gle.update({
|
||||||
"against_voucher_type": d.reference_doctype,
|
"against_voucher_type": d.reference_doctype,
|
||||||
"against_voucher": d.reference_name
|
"against_voucher": d.reference_name
|
||||||
})
|
})
|
||||||
|
|
||||||
allocated_amount_in_company_currency = flt(flt(d.allocated_amount) * flt(d.exchange_rate),
|
allocated_amount_in_company_currency = flt(flt(d.allocated_amount) * flt(d.exchange_rate),
|
||||||
self.precision("paid_amount"))
|
self.precision("paid_amount"))
|
||||||
|
|
||||||
gle.update({
|
gle.update({
|
||||||
dr_or_cr + "_in_account_currency": d.allocated_amount,
|
dr_or_cr + "_in_account_currency": d.allocated_amount,
|
||||||
dr_or_cr: allocated_amount_in_company_currency
|
dr_or_cr: allocated_amount_in_company_currency
|
||||||
})
|
})
|
||||||
|
|
||||||
gl_entries.append(gle)
|
gl_entries.append(gle)
|
||||||
|
|
||||||
if self.unallocated_amount:
|
if self.unallocated_amount:
|
||||||
base_unallocated_amount = base_unallocated_amount = self.unallocated_amount * \
|
base_unallocated_amount = base_unallocated_amount = self.unallocated_amount * \
|
||||||
(self.source_exchange_rate if self.payment_type=="Receive" else self.target_exchange_rate)
|
(self.source_exchange_rate if self.payment_type=="Receive" else self.target_exchange_rate)
|
||||||
|
|
||||||
gle = party_gl_dict.copy()
|
gle = party_gl_dict.copy()
|
||||||
|
|
||||||
gle.update({
|
gle.update({
|
||||||
dr_or_cr + "_in_account_currency": self.unallocated_amount,
|
dr_or_cr + "_in_account_currency": self.unallocated_amount,
|
||||||
dr_or_cr: base_unallocated_amount
|
dr_or_cr: base_unallocated_amount
|
||||||
})
|
})
|
||||||
|
|
||||||
gl_entries.append(gle)
|
gl_entries.append(gle)
|
||||||
|
|
||||||
def add_bank_gl_entries(self, gl_entries):
|
def add_bank_gl_entries(self, gl_entries):
|
||||||
if self.payment_type in ("Pay", "Internal Transfer"):
|
if self.payment_type in ("Pay", "Internal Transfer"):
|
||||||
gl_entries.append(
|
gl_entries.append(
|
||||||
@ -457,14 +457,14 @@ class PaymentEntry(AccountsController):
|
|||||||
"debit": self.base_received_amount
|
"debit": self.base_received_amount
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
def add_deductions_gl_entries(self, gl_entries):
|
def add_deductions_gl_entries(self, gl_entries):
|
||||||
for d in self.get("deductions"):
|
for d in self.get("deductions"):
|
||||||
if d.amount:
|
if d.amount:
|
||||||
account_currency = get_account_currency(d.account)
|
account_currency = get_account_currency(d.account)
|
||||||
if account_currency != self.company_currency:
|
if account_currency != self.company_currency:
|
||||||
frappe.throw(_("Currency for {0} must be {1}").format(d.account, self.company_currency))
|
frappe.throw(_("Currency for {0} must be {1}").format(d.account, self.company_currency))
|
||||||
|
|
||||||
gl_entries.append(
|
gl_entries.append(
|
||||||
self.get_gl_dict({
|
self.get_gl_dict({
|
||||||
"account": d.account,
|
"account": d.account,
|
||||||
@ -475,7 +475,7 @@ class PaymentEntry(AccountsController):
|
|||||||
"cost_center": d.cost_center
|
"cost_center": d.cost_center
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
def update_advance_paid(self):
|
def update_advance_paid(self):
|
||||||
if self.payment_type in ("Receive", "Pay") and self.party:
|
if self.payment_type in ("Receive", "Pay") and self.party:
|
||||||
for d in self.get("references"):
|
for d in self.get("references"):
|
||||||
@ -495,17 +495,17 @@ def get_outstanding_reference_documents(args):
|
|||||||
|
|
||||||
party_account_currency = get_account_currency(args.get("party_account"))
|
party_account_currency = get_account_currency(args.get("party_account"))
|
||||||
company_currency = frappe.db.get_value("Company", args.get("company"), "default_currency")
|
company_currency = frappe.db.get_value("Company", args.get("company"), "default_currency")
|
||||||
|
|
||||||
# Get negative outstanding sales /purchase invoices
|
# Get negative outstanding sales /purchase invoices
|
||||||
total_field = "base_grand_total" if party_account_currency == company_currency else "grand_total"
|
total_field = "base_grand_total" if party_account_currency == company_currency else "grand_total"
|
||||||
|
|
||||||
negative_outstanding_invoices = get_negative_outstanding_invoices(args.get("party_type"),
|
negative_outstanding_invoices = get_negative_outstanding_invoices(args.get("party_type"),
|
||||||
args.get("party"), args.get("party_account"), total_field)
|
args.get("party"), args.get("party_account"), total_field)
|
||||||
|
|
||||||
# Get positive outstanding sales /purchase invoices
|
# Get positive outstanding sales /purchase invoices
|
||||||
outstanding_invoices = get_outstanding_invoices(args.get("party_type"), args.get("party"),
|
outstanding_invoices = get_outstanding_invoices(args.get("party_type"), args.get("party"),
|
||||||
args.get("party_account"))
|
args.get("party_account"))
|
||||||
|
|
||||||
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:
|
||||||
@ -517,11 +517,11 @@ def get_outstanding_reference_documents(args):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Get all SO / PO which are not fully billed or aginst which full advance not paid
|
# Get all SO / PO which are not fully billed or aginst which full advance not paid
|
||||||
orders_to_be_billed = get_orders_to_be_billed(args.get("posting_date"),args.get("party_type"), args.get("party"),
|
orders_to_be_billed = get_orders_to_be_billed(args.get("posting_date"),args.get("party_type"), args.get("party"),
|
||||||
party_account_currency, company_currency)
|
party_account_currency, company_currency)
|
||||||
|
|
||||||
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):
|
||||||
if party_type == "Customer":
|
if party_type == "Customer":
|
||||||
voucher_type = 'Sales Order'
|
voucher_type = 'Sales Order'
|
||||||
@ -529,7 +529,7 @@ def get_orders_to_be_billed(posting_date, party_type, party, party_account_curre
|
|||||||
voucher_type = 'Purchase Order'
|
voucher_type = 'Purchase Order'
|
||||||
elif party_type == "Employee":
|
elif party_type == "Employee":
|
||||||
voucher_type = None
|
voucher_type = None
|
||||||
|
|
||||||
orders = []
|
orders = []
|
||||||
if voucher_type:
|
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"
|
||||||
@ -560,19 +560,19 @@ def get_orders_to_be_billed(posting_date, party_type, party, party_account_curre
|
|||||||
for d in orders:
|
for d in orders:
|
||||||
d["voucher_type"] = voucher_type
|
d["voucher_type"] = voucher_type
|
||||||
# This assumes that the exchange rate required is the one in the SO
|
# This assumes that the exchange rate required is the one in the SO
|
||||||
d["exchange_rate"] = get_exchange_rate(party_account_currency,
|
d["exchange_rate"] = get_exchange_rate(party_account_currency,
|
||||||
company_currency, posting_date)
|
company_currency, posting_date)
|
||||||
order_list.append(d)
|
order_list.append(d)
|
||||||
|
|
||||||
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":
|
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
|
||||||
"{voucher_type}" as voucher_type, name as voucher_no,
|
"{voucher_type}" as voucher_type, name as voucher_no,
|
||||||
{total_field} as invoice_amount, outstanding_amount, posting_date,
|
{total_field} as invoice_amount, outstanding_amount, posting_date,
|
||||||
due_date, conversion_rate as exchange_rate
|
due_date, conversion_rate as exchange_rate
|
||||||
from
|
from
|
||||||
`tab{voucher_type}`
|
`tab{voucher_type}`
|
||||||
@ -588,18 +588,18 @@ def get_negative_outstanding_invoices(party_type, party, party_account, total_fi
|
|||||||
}), (party, party_account), as_dict = True)
|
}), (party, party_account), as_dict = True)
|
||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_party_details(company, party_type, party, date):
|
def get_party_details(company, party_type, party, date):
|
||||||
if not frappe.db.exists(party_type, party):
|
if not frappe.db.exists(party_type, party):
|
||||||
frappe.throw(_("Invalid {0}: {1}").format(party_type, party))
|
frappe.throw(_("Invalid {0}: {1}").format(party_type, party))
|
||||||
|
|
||||||
party_account = get_party_account(party_type, party, company)
|
party_account = get_party_account(party_type, party, company)
|
||||||
|
|
||||||
account_currency = get_account_currency(party_account)
|
account_currency = get_account_currency(party_account)
|
||||||
account_balance = get_balance_on(party_account, date)
|
account_balance = get_balance_on(party_account, date)
|
||||||
party_balance = get_balance_on(party_type=party_type, party=party)
|
party_balance = get_balance_on(party_type=party_type, party=party)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"party_account": party_account,
|
"party_account": party_account,
|
||||||
"party_account_currency": account_currency,
|
"party_account_currency": account_currency,
|
||||||
@ -607,7 +607,7 @@ def get_party_details(company, party_type, party, date):
|
|||||||
"account_balance": account_balance
|
"account_balance": account_balance
|
||||||
}
|
}
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_account_details(account, date):
|
def get_account_details(account, date):
|
||||||
frappe.has_permission('Payment Entry', throw=True)
|
frappe.has_permission('Payment Entry', throw=True)
|
||||||
return frappe._dict({
|
return frappe._dict({
|
||||||
@ -615,61 +615,61 @@ def get_account_details(account, date):
|
|||||||
"account_balance": get_balance_on(account, date),
|
"account_balance": get_balance_on(account, date),
|
||||||
"account_type": frappe.db.get_value("Account", account, "account_type")
|
"account_type": frappe.db.get_value("Account", account, "account_type")
|
||||||
})
|
})
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_company_defaults(company):
|
def get_company_defaults(company):
|
||||||
fields = ["write_off_account", "exchange_gain_loss_account", "cost_center"]
|
fields = ["write_off_account", "exchange_gain_loss_account", "cost_center"]
|
||||||
ret = frappe.db.get_value("Company", company, fields, as_dict=1)
|
ret = frappe.db.get_value("Company", company, fields, as_dict=1)
|
||||||
|
|
||||||
for fieldname in fields:
|
for fieldname in fields:
|
||||||
if not ret[fieldname]:
|
if not ret[fieldname]:
|
||||||
frappe.throw(_("Please set default {0} in Company {1}")
|
frappe.throw(_("Please set default {0} in Company {1}")
|
||||||
.format(frappe.get_meta("Company").get_label(fieldname), company))
|
.format(frappe.get_meta("Company").get_label(fieldname), company))
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_reference_details(reference_doctype, reference_name, party_account_currency):
|
def get_reference_details(reference_doctype, reference_name, party_account_currency):
|
||||||
total_amount = outstanding_amount = exchange_rate = None
|
total_amount = outstanding_amount = exchange_rate = None
|
||||||
ref_doc = frappe.get_doc(reference_doctype, reference_name)
|
ref_doc = frappe.get_doc(reference_doctype, reference_name)
|
||||||
|
|
||||||
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":
|
if ref_doc.doctype == "Expense Claim":
|
||||||
total_amount = ref_doc.total_sanctioned_amount
|
total_amount = ref_doc.total_sanctioned_amount
|
||||||
else:
|
else:
|
||||||
total_amount = ref_doc.base_grand_total
|
total_amount = ref_doc.base_grand_total
|
||||||
exchange_rate = 1
|
exchange_rate = 1
|
||||||
else:
|
else:
|
||||||
total_amount = ref_doc.grand_total
|
total_amount = ref_doc.grand_total
|
||||||
|
|
||||||
# Get the exchange rate from the original ref doc
|
# Get the exchange rate from the original ref doc
|
||||||
# or get it based on the posting date of the ref doc
|
# or get it based on the posting date of the ref doc
|
||||||
exchange_rate = ref_doc.get("conversion_rate") or \
|
exchange_rate = ref_doc.get("conversion_rate") or \
|
||||||
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", "Expense Claim") \
|
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
|
||||||
exchange_rate = get_exchange_rate(party_account_currency,
|
exchange_rate = get_exchange_rate(party_account_currency,
|
||||||
ref_doc.company_currency, ref_doc.posting_date)
|
ref_doc.company_currency, ref_doc.posting_date)
|
||||||
|
|
||||||
return frappe._dict({
|
return frappe._dict({
|
||||||
"due_date": ref_doc.get("due_date"),
|
"due_date": ref_doc.get("due_date"),
|
||||||
"total_amount": total_amount,
|
"total_amount": total_amount,
|
||||||
"outstanding_amount": outstanding_amount,
|
"outstanding_amount": outstanding_amount,
|
||||||
"exchange_rate": exchange_rate
|
"exchange_rate": exchange_rate
|
||||||
})
|
})
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=None):
|
def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=None):
|
||||||
doc = frappe.get_doc(dt, dn)
|
doc = frappe.get_doc(dt, dn)
|
||||||
|
|
||||||
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))
|
||||||
|
|
||||||
if dt in ("Sales Invoice", "Sales Order"):
|
if dt in ("Sales Invoice", "Sales Order"):
|
||||||
party_type = "Customer"
|
party_type = "Customer"
|
||||||
elif dt in ("Purchase Invoice", "Purchase Order"):
|
elif dt in ("Purchase Invoice", "Purchase Order"):
|
||||||
@ -684,16 +684,16 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=
|
|||||||
party_account = doc.credit_to
|
party_account = doc.credit_to
|
||||||
else:
|
else:
|
||||||
party_account = get_party_account(party_type, doc.get(party_type.lower()), doc.company)
|
party_account = get_party_account(party_type, doc.get(party_type.lower()), doc.company)
|
||||||
|
|
||||||
party_account_currency = doc.get("party_account_currency") or get_account_currency(party_account)
|
party_account_currency = doc.get("party_account_currency") or get_account_currency(party_account)
|
||||||
|
|
||||||
# payment type
|
# payment type
|
||||||
if (dt == "Sales Order" or (dt=="Sales Invoice" and doc.outstanding_amount > 0)) \
|
if (dt == "Sales Order" or (dt=="Sales Invoice" and doc.outstanding_amount > 0)) \
|
||||||
or (dt=="Purchase Invoice" and doc.outstanding_amount < 0):
|
or (dt=="Purchase Invoice" and doc.outstanding_amount < 0):
|
||||||
payment_type = "Receive"
|
payment_type = "Receive"
|
||||||
else:
|
else:
|
||||||
payment_type = "Pay"
|
payment_type = "Pay"
|
||||||
|
|
||||||
# amounts
|
# amounts
|
||||||
grand_total = outstanding_amount = 0
|
grand_total = outstanding_amount = 0
|
||||||
if party_amount:
|
if party_amount:
|
||||||
@ -710,9 +710,9 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=
|
|||||||
outstanding_amount = grand_total - flt(doc.advance_paid)
|
outstanding_amount = grand_total - flt(doc.advance_paid)
|
||||||
|
|
||||||
# bank or cash
|
# bank or cash
|
||||||
bank = get_default_bank_cash_account(doc.company, "Bank", mode_of_payment=doc.get("mode_of_payment"),
|
bank = get_default_bank_cash_account(doc.company, "Bank", mode_of_payment=doc.get("mode_of_payment"),
|
||||||
account=bank_account)
|
account=bank_account)
|
||||||
|
|
||||||
paid_amount = received_amount = 0
|
paid_amount = received_amount = 0
|
||||||
if party_account_currency == bank.account_currency:
|
if party_account_currency == bank.account_currency:
|
||||||
paid_amount = received_amount = abs(outstanding_amount)
|
paid_amount = received_amount = abs(outstanding_amount)
|
||||||
@ -724,7 +724,7 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=
|
|||||||
received_amount = abs(outstanding_amount)
|
received_amount = abs(outstanding_amount)
|
||||||
if bank_amount:
|
if bank_amount:
|
||||||
paid_amount = bank_amount
|
paid_amount = bank_amount
|
||||||
|
|
||||||
pe = frappe.new_doc("Payment Entry")
|
pe = frappe.new_doc("Payment Entry")
|
||||||
pe.payment_type = payment_type
|
pe.payment_type = payment_type
|
||||||
pe.company = doc.company
|
pe.company = doc.company
|
||||||
@ -741,7 +741,7 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=
|
|||||||
pe.received_amount = received_amount
|
pe.received_amount = received_amount
|
||||||
pe.allocate_payment_amount = 1
|
pe.allocate_payment_amount = 1
|
||||||
pe.letter_head = doc.get("letter_head")
|
pe.letter_head = doc.get("letter_head")
|
||||||
|
|
||||||
pe.append("references", {
|
pe.append("references", {
|
||||||
"reference_doctype": dt,
|
"reference_doctype": dt,
|
||||||
"reference_name": dn,
|
"reference_name": dn,
|
||||||
|
@ -21,102 +21,102 @@ class TestPaymentEntry(unittest.TestCase):
|
|||||||
pe.paid_from = "Debtors - _TC"
|
pe.paid_from = "Debtors - _TC"
|
||||||
pe.insert()
|
pe.insert()
|
||||||
pe.submit()
|
pe.submit()
|
||||||
|
|
||||||
expected_gle = dict((d[0], d) for d in [
|
expected_gle = dict((d[0], d) for d in [
|
||||||
["Debtors - _TC", 0, 1000, so.name],
|
["Debtors - _TC", 0, 1000, so.name],
|
||||||
["_Test Cash - _TC", 1000.0, 0, None]
|
["_Test Cash - _TC", 1000.0, 0, None]
|
||||||
])
|
])
|
||||||
|
|
||||||
self.validate_gl_entries(pe.name, expected_gle)
|
self.validate_gl_entries(pe.name, expected_gle)
|
||||||
|
|
||||||
so_advance_paid = frappe.db.get_value("Sales Order", so.name, "advance_paid")
|
so_advance_paid = frappe.db.get_value("Sales Order", so.name, "advance_paid")
|
||||||
self.assertEqual(so_advance_paid, 1000)
|
self.assertEqual(so_advance_paid, 1000)
|
||||||
|
|
||||||
pe.cancel()
|
pe.cancel()
|
||||||
|
|
||||||
self.assertFalse(self.get_gle(pe.name))
|
self.assertFalse(self.get_gle(pe.name))
|
||||||
|
|
||||||
so_advance_paid = frappe.db.get_value("Sales Order", so.name, "advance_paid")
|
so_advance_paid = frappe.db.get_value("Sales Order", so.name, "advance_paid")
|
||||||
self.assertEqual(so_advance_paid, 0)
|
self.assertEqual(so_advance_paid, 0)
|
||||||
|
|
||||||
def test_payment_entry_against_si_usd_to_usd(self):
|
def test_payment_entry_against_si_usd_to_usd(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)
|
||||||
pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank USD - _TC")
|
pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank USD - _TC")
|
||||||
pe.reference_no = "1"
|
pe.reference_no = "1"
|
||||||
pe.reference_date = "2016-01-01"
|
pe.reference_date = "2016-01-01"
|
||||||
pe.target_exchange_rate = 50
|
pe.target_exchange_rate = 50
|
||||||
pe.insert()
|
pe.insert()
|
||||||
pe.submit()
|
pe.submit()
|
||||||
|
|
||||||
expected_gle = dict((d[0], d) for d in [
|
expected_gle = dict((d[0], d) for d in [
|
||||||
["_Test Receivable USD - _TC", 0, 5000, si.name],
|
["_Test Receivable USD - _TC", 0, 5000, si.name],
|
||||||
["_Test Bank USD - _TC", 5000.0, 0, None]
|
["_Test Bank USD - _TC", 5000.0, 0, None]
|
||||||
])
|
])
|
||||||
|
|
||||||
self.validate_gl_entries(pe.name, expected_gle)
|
self.validate_gl_entries(pe.name, expected_gle)
|
||||||
|
|
||||||
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"))
|
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"))
|
||||||
self.assertEqual(outstanding_amount, 0)
|
self.assertEqual(outstanding_amount, 0)
|
||||||
|
|
||||||
pe.cancel()
|
pe.cancel()
|
||||||
self.assertFalse(self.get_gle(pe.name))
|
self.assertFalse(self.get_gle(pe.name))
|
||||||
|
|
||||||
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"))
|
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"))
|
||||||
self.assertEqual(outstanding_amount, 100)
|
self.assertEqual(outstanding_amount, 100)
|
||||||
|
|
||||||
def test_payment_entry_against_pi(self):
|
def test_payment_entry_against_pi(self):
|
||||||
pi = make_purchase_invoice(supplier="_Test Supplier USD", debit_to="_Test Payable USD - _TC",
|
pi = make_purchase_invoice(supplier="_Test Supplier USD", debit_to="_Test Payable USD - _TC",
|
||||||
currency="USD", conversion_rate=50)
|
currency="USD", conversion_rate=50)
|
||||||
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank USD - _TC")
|
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank USD - _TC")
|
||||||
pe.reference_no = "1"
|
pe.reference_no = "1"
|
||||||
pe.reference_date = "2016-01-01"
|
pe.reference_date = "2016-01-01"
|
||||||
pe.source_exchange_rate = 50
|
pe.source_exchange_rate = 50
|
||||||
pe.insert()
|
pe.insert()
|
||||||
pe.submit()
|
pe.submit()
|
||||||
|
|
||||||
expected_gle = dict((d[0], d) for d in [
|
expected_gle = dict((d[0], d) for d in [
|
||||||
["_Test Payable USD - _TC", 12500, 0, pi.name],
|
["_Test Payable USD - _TC", 12500, 0, pi.name],
|
||||||
["_Test Bank USD - _TC", 0, 12500, None]
|
["_Test Bank USD - _TC", 0, 12500, None]
|
||||||
])
|
])
|
||||||
|
|
||||||
self.validate_gl_entries(pe.name, expected_gle)
|
self.validate_gl_entries(pe.name, expected_gle)
|
||||||
|
|
||||||
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):
|
def test_payment_entry_against_ec(self):
|
||||||
|
|
||||||
payable = frappe.db.get_value('Company', "_Test Company", 'default_payable_account')
|
payable = frappe.db.get_value('Company', "_Test Company", 'default_payable_account')
|
||||||
ec = make_expense_claim(payable, 300, 300, "_Test Company","Travel Expenses - _TC")
|
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 = get_payment_entry("Expense Claim", ec.name, bank_account="_Test Bank USD - _TC", bank_amount=300)
|
||||||
pe.reference_no = "1"
|
pe.reference_no = "1"
|
||||||
pe.reference_date = "2016-01-01"
|
pe.reference_date = "2016-01-01"
|
||||||
pe.source_exchange_rate = 1
|
pe.source_exchange_rate = 1
|
||||||
pe.insert()
|
pe.insert()
|
||||||
pe.submit()
|
pe.submit()
|
||||||
|
|
||||||
expected_gle = dict((d[0], d) for d in [
|
expected_gle = dict((d[0], d) for d in [
|
||||||
[payable, 300, 0, ec.name],
|
[payable, 300, 0, ec.name],
|
||||||
["_Test Bank USD - _TC", 0, 300, None]
|
["_Test Bank USD - _TC", 0, 300, None]
|
||||||
])
|
])
|
||||||
|
|
||||||
self.validate_gl_entries(pe.name, expected_gle)
|
self.validate_gl_entries(pe.name, expected_gle)
|
||||||
|
|
||||||
outstanding_amount = flt(frappe.db.get_value("Expense Claim", ec.name, "total_sanctioned_amount")) - \
|
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"))
|
flt(frappe.db.get_value("Expense Claim", ec.name, "total_amount_reimbursed"))
|
||||||
self.assertEqual(outstanding_amount, 0)
|
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)
|
||||||
pe = get_payment_entry("Sales Invoice", si.name, party_amount=20,
|
pe = get_payment_entry("Sales Invoice", si.name, party_amount=20,
|
||||||
bank_account="_Test Bank - _TC", bank_amount=900)
|
bank_account="_Test Bank - _TC", bank_amount=900)
|
||||||
pe.reference_no = "1"
|
pe.reference_no = "1"
|
||||||
pe.reference_date = "2016-01-01"
|
pe.reference_date = "2016-01-01"
|
||||||
|
|
||||||
self.assertEqual(pe.difference_amount, 100)
|
self.assertEqual(pe.difference_amount, 100)
|
||||||
|
|
||||||
pe.append("deductions", {
|
pe.append("deductions", {
|
||||||
"account": "_Test Exchange Gain/Loss - _TC",
|
"account": "_Test Exchange Gain/Loss - _TC",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
@ -124,15 +124,15 @@ class TestPaymentEntry(unittest.TestCase):
|
|||||||
})
|
})
|
||||||
pe.insert()
|
pe.insert()
|
||||||
pe.submit()
|
pe.submit()
|
||||||
|
|
||||||
expected_gle = dict((d[0], d) for d in [
|
expected_gle = dict((d[0], d) for d in [
|
||||||
["_Test Receivable USD - _TC", 0, 1000, si.name],
|
["_Test Receivable USD - _TC", 0, 1000, si.name],
|
||||||
["_Test Bank - _TC", 900, 0, None],
|
["_Test Bank - _TC", 900, 0, None],
|
||||||
["_Test Exchange Gain/Loss - _TC", 100.0, 0, None],
|
["_Test Exchange Gain/Loss - _TC", 100.0, 0, None],
|
||||||
])
|
])
|
||||||
|
|
||||||
self.validate_gl_entries(pe.name, expected_gle)
|
self.validate_gl_entries(pe.name, expected_gle)
|
||||||
|
|
||||||
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"))
|
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"))
|
||||||
self.assertEqual(outstanding_amount, 80)
|
self.assertEqual(outstanding_amount, 80)
|
||||||
|
|
||||||
@ -163,7 +163,7 @@ class TestPaymentEntry(unittest.TestCase):
|
|||||||
pe.source_exchange_rate, 65.1,
|
pe.source_exchange_rate, 65.1,
|
||||||
"{0} is not equal to {1}".format(pe.source_exchange_rate, 65.1)
|
"{0} is not equal to {1}".format(pe.source_exchange_rate, 65.1)
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_internal_transfer_usd_to_inr(self):
|
def test_internal_transfer_usd_to_inr(self):
|
||||||
pe = frappe.new_doc("Payment Entry")
|
pe = frappe.new_doc("Payment Entry")
|
||||||
pe.payment_type = "Internal Transfer"
|
pe.payment_type = "Internal Transfer"
|
||||||
@ -175,31 +175,31 @@ class TestPaymentEntry(unittest.TestCase):
|
|||||||
pe.received_amount = 4500
|
pe.received_amount = 4500
|
||||||
pe.reference_no = "2"
|
pe.reference_no = "2"
|
||||||
pe.reference_date = nowdate()
|
pe.reference_date = nowdate()
|
||||||
|
|
||||||
pe.setup_party_account_field()
|
pe.setup_party_account_field()
|
||||||
pe.set_missing_values()
|
pe.set_missing_values()
|
||||||
pe.set_exchange_rate()
|
pe.set_exchange_rate()
|
||||||
pe.set_amounts()
|
pe.set_amounts()
|
||||||
|
|
||||||
self.assertEquals(pe.difference_amount, 500)
|
self.assertEquals(pe.difference_amount, 500)
|
||||||
|
|
||||||
pe.append("deductions", {
|
pe.append("deductions", {
|
||||||
"account": "_Test Exchange Gain/Loss - _TC",
|
"account": "_Test Exchange Gain/Loss - _TC",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"amount": 500
|
"amount": 500
|
||||||
})
|
})
|
||||||
|
|
||||||
pe.insert()
|
pe.insert()
|
||||||
pe.submit()
|
pe.submit()
|
||||||
|
|
||||||
expected_gle = dict((d[0], d) for d in [
|
expected_gle = dict((d[0], d) for d in [
|
||||||
["_Test Bank USD - _TC", 0, 5000, None],
|
["_Test Bank USD - _TC", 0, 5000, None],
|
||||||
["_Test Bank - _TC", 4500, 0, None],
|
["_Test Bank - _TC", 4500, 0, None],
|
||||||
["_Test Exchange Gain/Loss - _TC", 500.0, 0, None],
|
["_Test Exchange Gain/Loss - _TC", 500.0, 0, None],
|
||||||
])
|
])
|
||||||
|
|
||||||
self.validate_gl_entries(pe.name, expected_gle)
|
self.validate_gl_entries(pe.name, expected_gle)
|
||||||
|
|
||||||
def test_payment_against_negative_sales_invoice(self):
|
def test_payment_against_negative_sales_invoice(self):
|
||||||
pe1 = frappe.new_doc("Payment Entry")
|
pe1 = frappe.new_doc("Payment Entry")
|
||||||
pe1.payment_type = "Pay"
|
pe1.payment_type = "Pay"
|
||||||
@ -209,33 +209,33 @@ class TestPaymentEntry(unittest.TestCase):
|
|||||||
pe1.paid_from = "_Test Cash - _TC"
|
pe1.paid_from = "_Test Cash - _TC"
|
||||||
pe1.paid_amount = 100
|
pe1.paid_amount = 100
|
||||||
pe1.received_amount = 100
|
pe1.received_amount = 100
|
||||||
|
|
||||||
self.assertRaises(InvalidPaymentEntry, pe1.validate)
|
self.assertRaises(InvalidPaymentEntry, pe1.validate)
|
||||||
|
|
||||||
si1 = create_sales_invoice()
|
si1 = create_sales_invoice()
|
||||||
|
|
||||||
# create full payment entry against si1
|
# create full payment entry against si1
|
||||||
pe2 = get_payment_entry("Sales Invoice", si1.name, bank_account="_Test Cash - _TC")
|
pe2 = get_payment_entry("Sales Invoice", si1.name, bank_account="_Test Cash - _TC")
|
||||||
pe2.insert()
|
pe2.insert()
|
||||||
pe2.submit()
|
pe2.submit()
|
||||||
|
|
||||||
# create return entry against si1
|
# create return entry against si1
|
||||||
create_sales_invoice(is_return=1, return_against=si1.name, qty=-1)
|
create_sales_invoice(is_return=1, return_against=si1.name, qty=-1)
|
||||||
si1_outstanding = frappe.db.get_value("Sales Invoice", si1.name, "outstanding_amount")
|
si1_outstanding = frappe.db.get_value("Sales Invoice", si1.name, "outstanding_amount")
|
||||||
self.assertEqual(si1_outstanding, -100)
|
self.assertEqual(si1_outstanding, -100)
|
||||||
|
|
||||||
# pay more than outstanding against si1
|
# pay more than outstanding against si1
|
||||||
pe3 = get_payment_entry("Sales Invoice", si1.name, bank_account="_Test Cash - _TC")
|
pe3 = get_payment_entry("Sales Invoice", si1.name, bank_account="_Test Cash - _TC")
|
||||||
pe3.paid_amount = pe3.received_amount = 300
|
pe3.paid_amount = pe3.received_amount = 300
|
||||||
self.assertRaises(InvalidPaymentEntry, pe3.validate)
|
self.assertRaises(InvalidPaymentEntry, pe3.validate)
|
||||||
|
|
||||||
# pay negative outstanding against si1
|
# pay negative outstanding against si1
|
||||||
pe3.paid_to = "Debtors - _TC"
|
pe3.paid_to = "Debtors - _TC"
|
||||||
pe3.paid_amount = pe3.received_amount = 100
|
pe3.paid_amount = pe3.received_amount = 100
|
||||||
|
|
||||||
pe3.insert()
|
pe3.insert()
|
||||||
pe3.submit()
|
pe3.submit()
|
||||||
|
|
||||||
expected_gle = dict((d[0], d) for d in [
|
expected_gle = dict((d[0], d) for d in [
|
||||||
["Debtors - _TC", 100, 0, si1.name],
|
["Debtors - _TC", 100, 0, si1.name],
|
||||||
["_Test Cash - _TC", 0, 100, None]
|
["_Test Cash - _TC", 0, 100, None]
|
||||||
@ -251,10 +251,10 @@ class TestPaymentEntry(unittest.TestCase):
|
|||||||
|
|
||||||
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si1.name, "outstanding_amount"))
|
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si1.name, "outstanding_amount"))
|
||||||
self.assertEqual(outstanding_amount, -100)
|
self.assertEqual(outstanding_amount, -100)
|
||||||
|
|
||||||
def validate_gl_entries(self, voucher_no, expected_gle):
|
def validate_gl_entries(self, voucher_no, expected_gle):
|
||||||
gl_entries = self.get_gle(voucher_no)
|
gl_entries = self.get_gle(voucher_no)
|
||||||
|
|
||||||
self.assertTrue(gl_entries)
|
self.assertTrue(gl_entries)
|
||||||
|
|
||||||
for i, gle in enumerate(gl_entries):
|
for i, gle in enumerate(gl_entries):
|
||||||
@ -262,7 +262,7 @@ class TestPaymentEntry(unittest.TestCase):
|
|||||||
self.assertEquals(expected_gle[gle.account][1], gle.debit)
|
self.assertEquals(expected_gle[gle.account][1], gle.debit)
|
||||||
self.assertEquals(expected_gle[gle.account][2], gle.credit)
|
self.assertEquals(expected_gle[gle.account][2], gle.credit)
|
||||||
self.assertEquals(expected_gle[gle.account][3], gle.against_voucher)
|
self.assertEquals(expected_gle[gle.account][3], gle.against_voucher)
|
||||||
|
|
||||||
def get_gle(self, voucher_no):
|
def get_gle(self, voucher_no):
|
||||||
return frappe.db.sql("""select account, debit, credit, against_voucher
|
return frappe.db.sql("""select account, debit, credit, against_voucher
|
||||||
from `tabGL Entry` where voucher_type='Payment Entry' and voucher_no=%s
|
from `tabGL Entry` where voucher_type='Payment Entry' and voucher_no=%s
|
||||||
|
@ -6,6 +6,7 @@ Payment Entry can be made against following transactions.
|
|||||||
2. Purchase Invoice.
|
2. Purchase Invoice.
|
||||||
3. Sales Order (Advance Payment)
|
3. Sales Order (Advance Payment)
|
||||||
4. Purchase Order (Advance Payment)
|
4. Purchase Order (Advance Payment)
|
||||||
|
5. Expense Claim
|
||||||
|
|
||||||
####Step 1: Make Payment
|
####Step 1: Make Payment
|
||||||
|
|
||||||
@ -21,7 +22,7 @@ In the Payment Entry, select Mode of Payment (eg: Bank, Cash, Wire Transfer). In
|
|||||||
|
|
||||||
####Step 3: Payment Amount
|
####Step 3: Payment Amount
|
||||||
|
|
||||||
Enter actual payment amount received from the Customer or paid to the Supplier.
|
Enter actual payment amount received from the Customer or paid to the Supplier or Employee.
|
||||||
|
|
||||||
<img class="screenshot" alt="Making Payment" src="/docs/assets/img/accounts/payment-entry-3.png">
|
<img class="screenshot" alt="Making Payment" src="/docs/assets/img/accounts/payment-entry-3.png">
|
||||||
|
|
||||||
@ -90,7 +91,7 @@ Following internal transfers can be managed from the Payment Entry.
|
|||||||
- Updating opening balance in an Accounts.
|
- Updating opening balance in an Accounts.
|
||||||
- Fixed Asset Depreciation entry.
|
- Fixed Asset Depreciation entry.
|
||||||
- For adjusting Credit Note against Sales Invoice and Debit Note against Purchase Invoice, incase there is no payment happening at all.
|
- For adjusting Credit Note against Sales Invoice and Debit Note against Purchase Invoice, incase there is no payment happening at all.
|
||||||
|
4. Payment Entries are used if a cheque is printed.
|
||||||
* * *
|
* * *
|
||||||
|
|
||||||
## Managing Outstanding Payments
|
## Managing Outstanding Payments
|
||||||
|
@ -39,11 +39,18 @@ To make payment against the expense claim, user has to click on Make > Bank Entr
|
|||||||
<img class="screenshot" alt="Expense Claim" src="/docs/assets/img/human-resources/payment.png">
|
<img class="screenshot" alt="Expense Claim" src="/docs/assets/img/human-resources/payment.png">
|
||||||
|
|
||||||
#### Payment Entry
|
#### Payment Entry
|
||||||
<img class="screenshot" alt="Expense Claim" src="/docs/assets/img/human-resources/payment_entry.png">
|
<img class="screenshot" alt="Expense Claim" src="{{docs_base_url}}/assets/img/human-resources/payment_entry.png">
|
||||||
|
|
||||||
|
|
||||||
Note: This amount should not be clubbed with Salary because the amount will then be taxable to the Employee.
|
Note: This amount should not be clubbed with Salary because the amount will then be taxable to the Employee.
|
||||||
|
|
||||||
|
Alternatively, a Payment Entry can be made for an employee and all outstanding Expense Claims will be pulled in.
|
||||||
|
|
||||||
|
> Accounts > Payment Entry > New Payment Entry
|
||||||
|
|
||||||
|
Set the Payment Type to "Pay", the Party Type to Employee, the Party to the employee being paid and the account being paid
|
||||||
|
from. All outstanding expense claims will be pulled in and payments amounts can be allocated to each expense.
|
||||||
|
<img class="screenshot" alt="Expense Claim" src="{{docs_base_url}}/assets/img/human-resources/expense_claim_payment_entry.png">
|
||||||
|
|
||||||
### Linking with Task & Project
|
### Linking with Task & Project
|
||||||
|
|
||||||
* To Link Expense Claim with Task or Project specify the Task or the Project while making an Expense Claim
|
* To Link Expense Claim with Task or Project specify the Task or the Project while making an Expense Claim
|
||||||
|
@ -14,7 +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",
|
||||||
@ -25,7 +25,7 @@ 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 = make_expense_claim(payable_account, 300, 200, "Wind Power LLC","Travel Expenses - WP", "_Test Project 1", task_name)
|
make_expense_claim(payable_account, 300, 200, "Wind Power LLC","Travel Expenses - WP", "_Test Project 1", task_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)
|
||||||
@ -40,7 +40,7 @@ class TestExpenseClaim(unittest.TestCase):
|
|||||||
|
|
||||||
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 = make_expense_claim(payable_account, 300, 200, "Wind Power LLC", "Travel Expenses - WP")
|
expense_claim = make_expense_claim(payable_account, 300, 200, "Wind Power LLC", "Travel Expenses - WP")
|
||||||
@ -54,7 +54,7 @@ class TestExpenseClaim(unittest.TestCase):
|
|||||||
|
|
||||||
expense_claim = frappe.get_doc("Expense Claim", expense_claim.name)
|
expense_claim = frappe.get_doc("Expense Claim", expense_claim.name)
|
||||||
self.assertEqual(expense_claim.status, "Paid")
|
self.assertEqual(expense_claim.status, "Paid")
|
||||||
|
|
||||||
je.cancel()
|
je.cancel()
|
||||||
expense_claim = frappe.get_doc("Expense Claim", expense_claim.name)
|
expense_claim = frappe.get_doc("Expense Claim", expense_claim.name)
|
||||||
self.assertEqual(expense_claim.status, "Unpaid")
|
self.assertEqual(expense_claim.status, "Unpaid")
|
||||||
@ -63,7 +63,7 @@ class TestExpenseClaim(unittest.TestCase):
|
|||||||
payable_account = get_payable_account("Wind Power LLC")
|
payable_account = get_payable_account("Wind Power LLC")
|
||||||
expense_claim = make_expense_claim(payable_account, 300, 200, "Wind Power LLC", "Travel Expenses - WP")
|
expense_claim = make_expense_claim(payable_account, 300, 200, "Wind Power LLC", "Travel Expenses - WP")
|
||||||
expense_claim.submit()
|
expense_claim.submit()
|
||||||
|
|
||||||
gl_entries = frappe.db.sql("""select account, debit, credit
|
gl_entries = frappe.db.sql("""select account, debit, credit
|
||||||
from `tabGL Entry` where voucher_type='Expense Claim' and voucher_no=%s
|
from `tabGL Entry` where voucher_type='Expense Claim' and voucher_no=%s
|
||||||
order by account asc""", expense_claim.name, as_dict=1)
|
order by account asc""", expense_claim.name, as_dict=1)
|
||||||
@ -100,7 +100,7 @@ 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):
|
def make_expense_claim(payable_account,claim_amount, sanctioned_amount, company, account, project=None, task_name=None):
|
||||||
expense_claim = frappe.get_doc({
|
expense_claim = frappe.get_doc({
|
||||||
"doctype": "Expense Claim",
|
"doctype": "Expense Claim",
|
||||||
@ -118,5 +118,5 @@ def make_expense_claim(payable_account,claim_amount, sanctioned_amount, company,
|
|||||||
|
|
||||||
expense_claim.submit()
|
expense_claim.submit()
|
||||||
return expense_claim
|
return expense_claim
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user