Merge branch 'develop' of https://github.com/frappe/erpnext into #34282-Record-advance-payment-as-a-liability
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index 4cebb7b..aa67537 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -616,7 +616,7 @@
frm.events.set_unallocated_amount(frm);
},
- get_outstanding_invoice: function(frm) {
+ get_outstanding_invoices_or_orders: function(frm, get_outstanding_invoices, get_orders_to_be_billed) {
const today = frappe.datetime.get_today();
const fields = [
{fieldtype:"Section Break", label: __("Posting Date")},
@@ -646,12 +646,29 @@
{fieldtype:"Check", label: __("Allocate Payment Amount"), fieldname:"allocate_payment_amount", default:1},
];
+ let btn_text = "";
+
+ if (get_outstanding_invoices) {
+ btn_text = "Get Outstanding Invoices";
+ }
+ else if (get_orders_to_be_billed) {
+ btn_text = "Get Outstanding Orders";
+ }
+
frappe.prompt(fields, function(filters){
frappe.flags.allocate_payment_amount = true;
frm.events.validate_filters_data(frm, filters);
frm.doc.cost_center = filters.cost_center;
- frm.events.get_outstanding_documents(frm, filters);
- }, __("Filters"), __("Get Outstanding Documents"));
+ frm.events.get_outstanding_documents(frm, filters, get_outstanding_invoices, get_orders_to_be_billed);
+ }, __("Filters"), __(btn_text));
+ },
+
+ get_outstanding_invoices: function(frm) {
+ frm.events.get_outstanding_invoices_or_orders(frm, true, false);
+ },
+
+ get_outstanding_orders: function(frm) {
+ frm.events.get_outstanding_invoices_or_orders(frm, false, true);
},
validate_filters_data: function(frm, filters) {
@@ -677,7 +694,7 @@
}
},
- get_outstanding_documents: function(frm, filters) {
+ get_outstanding_documents: function(frm, filters, get_outstanding_invoices, get_orders_to_be_billed) {
frm.clear_table("references");
if(!frm.doc.party) {
@@ -701,6 +718,13 @@
args[key] = filters[key];
}
+ if (get_outstanding_invoices) {
+ args["get_outstanding_invoices"] = true;
+ }
+ else if (get_orders_to_be_billed) {
+ args["get_orders_to_be_billed"] = true;
+ }
+
frappe.flags.allocate_payment_amount = filters['allocate_payment_amount'];
return frappe.call({
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json
index 1c330b8..6224d40 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.json
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json
@@ -48,7 +48,8 @@
"base_received_amount",
"base_received_amount_after_tax",
"section_break_14",
- "get_outstanding_invoice",
+ "get_outstanding_invoices",
+ "get_outstanding_orders",
"references",
"section_break_34",
"total_allocated_amount",
@@ -356,12 +357,6 @@
"label": "Reference"
},
{
- "depends_on": "eval:doc.docstatus==0",
- "fieldname": "get_outstanding_invoice",
- "fieldtype": "Button",
- "label": "Get Outstanding Invoice"
- },
- {
"fieldname": "references",
"fieldtype": "Table",
"label": "Payment References",
@@ -728,12 +723,24 @@
"fieldname": "section_break_60",
"fieldtype": "Section Break",
"hide_border": 1
+ },
+ {
+ "depends_on": "eval:doc.docstatus==0",
+ "fieldname": "get_outstanding_invoices",
+ "fieldtype": "Button",
+ "label": "Get Outstanding Invoices"
+ },
+ {
+ "depends_on": "eval:doc.docstatus==0",
+ "fieldname": "get_outstanding_orders",
+ "fieldtype": "Button",
+ "label": "Get Outstanding Orders"
}
],
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2023-06-07 14:36:50.521884",
+ "modified": "2023-06-19 11:38:04.387219",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry",
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index bddce55..d23afb1 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -181,6 +181,19 @@
if self.payment_type == "Internal Transfer":
return
+ if self.party_type in ("Customer", "Supplier"):
+ self.validate_allocated_amount_with_latest_data()
+ else:
+ fail_message = _("Row #{0}: Allocated Amount cannot be greater than outstanding amount.")
+ for d in self.get("references"):
+ if (flt(d.allocated_amount)) > 0 and flt(d.allocated_amount) > flt(d.outstanding_amount):
+ frappe.throw(fail_message.format(d.idx))
+
+ # Check for negative outstanding invoices as well
+ if flt(d.allocated_amount) < 0 and flt(d.allocated_amount) < flt(d.outstanding_amount):
+ frappe.throw(fail_message.format(d.idx))
+
+ def validate_allocated_amount_with_latest_data(self):
latest_references = get_outstanding_reference_documents(
{
"posting_date": self.posting_date,
@@ -189,6 +202,8 @@
"payment_type": self.payment_type,
"party": self.party,
"party_account": self.paid_from if self.payment_type == "Receive" else self.paid_to,
+ "get_outstanding_invoices": True,
+ "get_orders_to_be_billed": True,
}
)
@@ -198,7 +213,7 @@
d = frappe._dict(d)
latest_lookup.update({(d.voucher_type, d.voucher_no): d})
- for d in self.get("references").copy():
+ for d in self.get("references"):
latest = latest_lookup.get((d.reference_doctype, d.reference_name))
# The reference has already been fully paid
@@ -213,22 +228,18 @@
):
frappe.throw(
_(
- "{0} {1} has already been partly paid. Please use the 'Get Outstanding Invoice' button to get the latest outstanding amount."
+ "{0} {1} has already been partly paid. Please use the 'Get Outstanding Invoice' or the 'Get Outstanding Orders' button to get the latest outstanding amounts."
).format(d.reference_doctype, d.reference_name)
)
- d.outstanding_amount = latest.outstanding_amount
-
fail_message = _("Row #{0}: Allocated Amount cannot be greater than outstanding amount.")
- if (flt(d.allocated_amount)) > 0:
- if flt(d.allocated_amount) > flt(d.outstanding_amount):
- frappe.throw(fail_message.format(d.idx))
+ if (flt(d.allocated_amount)) > 0 and flt(d.allocated_amount) > flt(latest.outstanding_amount):
+ frappe.throw(fail_message.format(d.idx))
# Check for negative outstanding invoices as well
- if flt(d.allocated_amount) < 0:
- if flt(d.allocated_amount) < flt(d.outstanding_amount):
- frappe.throw(fail_message.format(d.idx))
+ if flt(d.allocated_amount) < 0 and flt(d.allocated_amount) < flt(latest.outstanding_amount):
+ frappe.throw(fail_message.format(d.idx))
def delink_advance_entry_references(self):
for reference in self.references:
@@ -1432,62 +1443,75 @@
condition += " and company = {0}".format(frappe.db.escape(args.get("company")))
common_filter.append(ple.company == args.get("company"))
- outstanding_invoices = get_outstanding_invoices(
- args.get("party_type"),
- args.get("party"),
- args.get("party_account"),
- common_filter=common_filter,
- posting_date=posting_and_due_date,
- min_outstanding=args.get("outstanding_amt_greater_than"),
- max_outstanding=args.get("outstanding_amt_less_than"),
- accounting_dimensions=accounting_dimensions_filter,
- )
-
- outstanding_invoices = split_invoices_based_on_payment_terms(outstanding_invoices)
-
- for d in outstanding_invoices:
- d["exchange_rate"] = 1
- if party_account_currency != company_currency:
- if d.voucher_type in frappe.get_hooks("invoice_doctypes"):
- d["exchange_rate"] = frappe.db.get_value(d.voucher_type, d.voucher_no, "conversion_rate")
- elif d.voucher_type == "Journal Entry":
- d["exchange_rate"] = get_exchange_rate(
- party_account_currency, company_currency, d.posting_date
- )
- if d.voucher_type in ("Purchase Invoice"):
- d["bill_no"] = frappe.db.get_value(d.voucher_type, d.voucher_no, "bill_no")
-
- # Get all SO / PO which are not fully billed or against which full advance not paid
- orders_to_be_billed = []
- orders_to_be_billed = get_orders_to_be_billed(
- args.get("posting_date"),
- args.get("party_type"),
- args.get("party"),
- args.get("company"),
- party_account_currency,
- company_currency,
- filters=args,
- )
-
- # Get negative outstanding sales /purchase invoices
+ outstanding_invoices = []
negative_outstanding_invoices = []
- if args.get("party_type") != "Employee" and not args.get("voucher_no"):
- negative_outstanding_invoices = get_negative_outstanding_invoices(
+
+ if args.get("get_outstanding_invoices"):
+ outstanding_invoices = get_outstanding_invoices(
args.get("party_type"),
args.get("party"),
args.get("party_account"),
+ common_filter=common_filter,
+ posting_date=posting_and_due_date,
+ min_outstanding=args.get("outstanding_amt_greater_than"),
+ max_outstanding=args.get("outstanding_amt_less_than"),
+ accounting_dimensions=accounting_dimensions_filter,
+ )
+
+ outstanding_invoices = split_invoices_based_on_payment_terms(outstanding_invoices)
+
+ for d in outstanding_invoices:
+ d["exchange_rate"] = 1
+ if party_account_currency != company_currency:
+ if d.voucher_type in frappe.get_hooks("invoice_doctypes"):
+ d["exchange_rate"] = frappe.db.get_value(d.voucher_type, d.voucher_no, "conversion_rate")
+ elif d.voucher_type == "Journal Entry":
+ d["exchange_rate"] = get_exchange_rate(
+ party_account_currency, company_currency, d.posting_date
+ )
+ if d.voucher_type in ("Purchase Invoice"):
+ d["bill_no"] = frappe.db.get_value(d.voucher_type, d.voucher_no, "bill_no")
+
+ # Get negative outstanding sales /purchase invoices
+ if args.get("party_type") != "Employee" and not args.get("voucher_no"):
+ negative_outstanding_invoices = get_negative_outstanding_invoices(
+ args.get("party_type"),
+ args.get("party"),
+ args.get("party_account"),
+ party_account_currency,
+ company_currency,
+ condition=condition,
+ )
+
+ # Get all SO / PO which are not fully billed or against which full advance not paid
+ orders_to_be_billed = []
+ if args.get("get_orders_to_be_billed"):
+ orders_to_be_billed = get_orders_to_be_billed(
+ args.get("posting_date"),
+ args.get("party_type"),
+ args.get("party"),
+ args.get("company"),
party_account_currency,
company_currency,
- condition=condition,
+ filters=args,
)
data = negative_outstanding_invoices + outstanding_invoices + orders_to_be_billed
if not data:
+ if args.get("get_outstanding_invoices") and args.get("get_orders_to_be_billed"):
+ ref_document_type = "invoices or orders"
+ elif args.get("get_outstanding_invoices"):
+ ref_document_type = "invoices"
+ elif args.get("get_orders_to_be_billed"):
+ ref_document_type = "orders"
+
frappe.msgprint(
_(
- "No outstanding invoices found for the {0} {1} which qualify the filters you have specified."
- ).format(_(args.get("party_type")).lower(), frappe.bold(args.get("party")))
+ "No outstanding {0} found for the {1} {2} which qualify the filters you have specified."
+ ).format(
+ ref_document_type, _(args.get("party_type")).lower(), frappe.bold(args.get("party"))
+ )
)
return data
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
index 7b68dd4..ab4aab3 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
@@ -320,6 +320,7 @@
},
{
"default": "0",
+ "depends_on": "eval: !doc.is_debit_note",
"fieldname": "is_return",
"fieldtype": "Check",
"hide_days": 1,
@@ -1960,6 +1961,7 @@
},
{
"default": "0",
+ "depends_on": "eval: !doc.is_return",
"description": "Issue a debit note with 0 qty against an existing Sales Invoice",
"fieldname": "is_debit_note",
"fieldtype": "Check",
@@ -2155,7 +2157,7 @@
"link_fieldname": "consolidated_invoice"
}
],
- "modified": "2023-06-03 16:22:16.219333",
+ "modified": "2023-06-19 16:02:05.309332",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.json b/erpnext/stock/doctype/stock_entry/stock_entry.json
index fe42b1f..564c380 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.json
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.json
@@ -125,7 +125,8 @@
"oldfieldname": "purpose",
"oldfieldtype": "Select",
"options": "Material Issue\nMaterial Receipt\nMaterial Transfer\nMaterial Transfer for Manufacture\nMaterial Consumption for Manufacture\nManufacture\nRepack\nSend to Subcontractor",
- "read_only": 1
+ "read_only": 1,
+ "search_index": 1
},
{
"fieldname": "company",
@@ -678,7 +679,7 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2023-06-16 14:59:10.917235",
+ "modified": "2023-06-19 18:23:40.748114",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock Entry",