Make Journal entry from Invoice based on Payment Terms (due date) #11989 (#12047)
* split journal entry according to invoice due date
* fix bug where reference_due_dates options are not populated:
- after making JE, add options to _onload
- use __onload to add options
* cater for case where no payment_schedule
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.js b/erpnext/accounts/doctype/journal_entry/journal_entry.js
index e25abfb..c92a728 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.js
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.js
@@ -61,6 +61,16 @@
}
}
});
+ },
+
+ accounts_on_form_rendered: function(frm) {
+ const options = frm.doc.__onload;
+
+ if (options && frm.cur_grid) {
+ frm.cur_grid.get_field("reference_due_date")
+ .df.options = options[frm.cur_grid.get_field('reference_name').value];
+ frm.cur_grid.refresh_field('reference_due_date');
+ }
}
});
@@ -248,7 +258,6 @@
if (d.reference_type && d.reference_name && d.reference_due_date) {
if (in_list(["Sales Invoice", "Purchase Invoice"], d.reference_type)) {
- console.log('cdt:', cdt, cdn);
frappe.model.set_value(cdt, cdn, 'debit_in_account_currency', '');
frappe.model.set_value(cdt, cdn, 'credit_in_account_currency', '');
}
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index a298ae3..0c3503b 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -3,7 +3,7 @@
from __future__ import unicode_literals
import frappe, erpnext, json
-from frappe.utils import cstr, flt, fmt_money, formatdate, getdate
+from frappe.utils import cstr, flt, fmt_money, formatdate, getdate, DATE_FORMAT
from frappe import msgprint, _, scrub
from erpnext.controllers.accounts_controller import AccountsController
from erpnext.accounts.utils import get_balance_on, get_account_currency
@@ -647,9 +647,8 @@
party_type = "Supplier"
party_account = ref_doc.credit_to
-
- if (dt=="Sales Invoice" and ref_doc.outstanding_amount > 0) \
- or (dt=="Purchase Invoice" and ref_doc.outstanding_amount < 0):
+ if (dt == "Sales Invoice" and ref_doc.outstanding_amount > 0) \
+ or (dt == "Purchase Invoice" and ref_doc.outstanding_amount < 0):
amount_field_party = "credit_in_account_currency"
amount_field_bank = "debit_in_account_currency"
else:
@@ -670,6 +669,7 @@
"journal_entry": journal_entry
})
+
def get_payment_entry(ref_doc, args):
cost_center = frappe.db.get_value("Company", ref_doc.company, "cost_center")
exchange_rate = 1
@@ -687,26 +687,58 @@
"remark": args.get("remarks")
})
- party_row = je.append("accounts", {
- "account": args.get("party_account"),
- "party_type": args.get("party_type"),
- "party": ref_doc.get(args.get("party_type").lower()),
- "cost_center": cost_center,
- "account_type": frappe.db.get_value("Account", args.get("party_account"), "account_type"),
- "account_currency": args.get("party_account_currency") or \
- get_account_currency(args.get("party_account")),
- "balance": get_balance_on(args.get("party_account")),
- "party_balance": get_balance_on(party=args.get("party"), party_type=args.get("party_type")),
- "exchange_rate": exchange_rate,
- args.get("amount_field_party"): args.get("amount"),
- "is_advance": args.get("is_advance"),
- "reference_type": ref_doc.doctype,
- "reference_name": ref_doc.name
- })
+ if not ref_doc.payment_schedule:
+ je.append("accounts", {
+ "account": args.get("party_account"),
+ "party_type": args.get("party_type"),
+ "party": ref_doc.get(args.get("party_type").lower()),
+ "cost_center": cost_center,
+ "account_type": frappe.db.get_value("Account", args.get("party_account"), "account_type"),
+ "account_currency": args.get("party_account_currency") or \
+ get_account_currency(args.get("party_account")),
+ "balance": get_balance_on(args.get("party_account")),
+ "party_balance": get_balance_on(party=args.get("party"), party_type=args.get("party_type")),
+ "exchange_rate": exchange_rate,
+ args.get("amount_field_party"): args.get("amount"),
+ "is_advance": args.get("is_advance"),
+ "reference_type": ref_doc.doctype,
+ "reference_name": ref_doc.name
+ })
+
+ else:
+ options_ref_name_list = [
+ d.due_date.strftime(DATE_FORMAT) for d in ref_doc.payment_schedule
+ if d.get('due_date')
+ ]
+
+ for payment_term in ref_doc.payment_schedule:
+ je.append("accounts", {
+ "account": args.get("party_account"),
+ "party_type": args.get("party_type"),
+ "party": ref_doc.get(args.get("party_type").lower()),
+ "cost_center": cost_center,
+ "account_type": frappe.db.get_value("Account", args.get("party_account"), "account_type"),
+ "account_currency": args.get("party_account_currency") or \
+ get_account_currency(args.get("party_account")),
+ "balance": get_balance_on(args.get("party_account")),
+ "party_balance": get_balance_on(party=args.get("party"), party_type=args.get("party_type")),
+ "exchange_rate": exchange_rate,
+ args.get("amount_field_party"): payment_term.payment_amount,
+ "is_advance": args.get("is_advance"),
+ "reference_type": ref_doc.doctype,
+ "reference_name": ref_doc.name,
+ "reference_due_date": payment_term.due_date
+ })
+ je.set_onload(ref_doc.name, '\n'.join(options_ref_name_list))
+
+ # First multi currency check
+ for row in je.accounts:
+ if row.account_currency != ref_doc.company_currency:
+ je.multi_currency = 1
bank_row = je.append("accounts")
- #make it bank_details
+ # Make it bank_details
bank_account = get_default_bank_cash_account(ref_doc.company, "Bank", account=args.get("bank_account"))
if bank_account:
bank_row.update(bank_account)
@@ -725,9 +757,9 @@
else:
bank_row.set(args.get("amount_field_bank"), amount * exchange_rate)
- # set multi currency check
- if party_row.account_currency != ref_doc.company_currency \
- or (bank_row.account_currency and bank_row.account_currency != ref_doc.company_currency):
+ # Multi currency check again
+ if not je.multi_currency:
+ if bank_row.account_currency and bank_row.account_currency != ref_doc.company_currency:
je.multi_currency = 1
je.set_amounts_in_company_currency()
@@ -735,6 +767,7 @@
return je if args.get("journal_entry") else je.as_dict()
+
@frappe.whitelist()
def get_opening_accounts(company):
"""get all balance sheet accounts for opening entry"""
@@ -757,6 +790,7 @@
and jv.docstatus = 1 and jv.`{0}` like %s order by jv.name desc limit %s, %s""".format(frappe.db.escape(searchfield)),
(filters.get("account"), cstr(filters.get("party")), "%{0}%".format(txt), start, page_len))
+
@frappe.whitelist()
def get_outstanding(args):
if not frappe.has_permission("Account"):
@@ -809,6 +843,7 @@
"party": invoice.get(scrub(party_type))
}
+
@frappe.whitelist()
def get_party_account_and_balance(company, party_type, party):
if not frappe.has_permission("Account"):
@@ -826,6 +861,7 @@
"account_currency": frappe.db.get_value("Account", account, "account_currency")
}
+
@frappe.whitelist()
def get_account_balance_and_party_type(account, date, company, debit=None, credit=None, exchange_rate=None):
"""Returns dict of account balance and party type to be set in Journal Entry on selection of account."""
@@ -863,7 +899,7 @@
return grid_values
-# Added posting_date as one of the parameters of get_exchange_rate
+
@frappe.whitelist()
def get_exchange_rate(posting_date, account=None, account_currency=None, company=None,
reference_type=None, reference_name=None, debit=None, credit=None, exchange_rate=None):
@@ -896,6 +932,7 @@
# don't return None or 0 as it is multipled with a value and that value could be lost
return exchange_rate or 1
+
@frappe.whitelist()
def get_average_exchange_rate(account):
exchange_rate = 0