Skip to content

Commit

Permalink
Merge pull request #36084 from frappe/version-13-hotfix
Browse files Browse the repository at this point in the history
chore: release v13
  • Loading branch information
deepeshgarg007 authored Jul 11, 2023
2 parents 77eb11a + 1d6bc68 commit 30c9b15
Show file tree
Hide file tree
Showing 14 changed files with 403 additions and 238 deletions.
162 changes: 88 additions & 74 deletions erpnext/accounts/doctype/payment_entry/payment_entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,16 @@

import frappe
from frappe import ValidationError, _, scrub, throw
from frappe.utils import cint, comma_or, flt, get_link_to_form, getdate, nowdate
from frappe.utils import (
cint,
comma_and,
comma_or,
flt,
fmt_money,
get_link_to_form,
getdate,
nowdate,
)
from six import iteritems, string_types

import erpnext
Expand Down Expand Up @@ -191,17 +200,17 @@ def validate_allocated_amount_with_latest_data(self):
# The reference has already been fully paid
if not latest:
frappe.throw(
_("{0} {1} has already been fully paid.").format(d.reference_doctype, d.reference_name)
_("{0} {1} has already been fully paid.").format(_(d.reference_doctype), d.reference_name)
)
# The reference has already been partly paid
elif (
latest.outstanding_amount < latest.invoice_amount
and flt(d.outstanding_amount, d.precision("outstanding_amount")) != latest.outstanding_amount
):
elif latest.outstanding_amount < latest.invoice_amount and flt(
d.outstanding_amount, d.precision("outstanding_amount")
) != flt(latest.outstanding_amount, d.precision("outstanding_amount")):

frappe.throw(
_(
"{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)
).format(_(d.reference_doctype), d.reference_name)
)

fail_message = _("Row #{0}: Allocated Amount cannot be greater than outstanding amount.")
Expand Down Expand Up @@ -319,7 +328,7 @@ def validate_payment_type(self):
def validate_party_details(self):
if 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(_("{0} {1} does not exist").format(_(self.party_type), self.party))

def set_exchange_rate(self, ref_doc=None):
self.set_source_exchange_rate(ref_doc)
Expand Down Expand Up @@ -376,7 +385,9 @@ def validate_reference_documents(self):
continue
if d.reference_doctype not in valid_reference_doctypes:
frappe.throw(
_("Reference Doctype must be one of {0}").format(comma_or(valid_reference_doctypes))
_("Reference Doctype must be one of {0}").format(
comma_or((_(d) for d in valid_reference_doctypes))
)
)

elif d.reference_name:
Expand All @@ -389,7 +400,7 @@ def validate_reference_documents(self):
if self.party != ref_doc.get(scrub(self.party_type)):
frappe.throw(
_("{0} {1} is not associated with {2} {3}").format(
d.reference_doctype, d.reference_name, self.party_type, self.party
_(d.reference_doctype), d.reference_name, _(self.party_type), self.party
)
)
else:
Expand All @@ -410,18 +421,18 @@ def validate_reference_documents(self):
if ref_party_account != self.party_account:
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
_(d.reference_doctype), d.reference_name, ref_party_account, self.party_account
)
)

if ref_doc.doctype == "Purchase Invoice" and ref_doc.get("on_hold"):
frappe.throw(
_("{0} {1} is on hold").format(d.reference_doctype, d.reference_name),
title=_("Invalid Invoice"),
_("{0} {1} is on hold").format(_(d.reference_doctype), d.reference_name),
title=_("Invalid Purchase Invoice"),
)

if ref_doc.docstatus != 1:
frappe.throw(_("{0} {1} must be submitted").format(d.reference_doctype, d.reference_name))
frappe.throw(_("{0} {1} must be submitted").format(_(d.reference_doctype), d.reference_name))

def validate_paid_invoices(self):
no_oustanding_refs = {}
Expand All @@ -437,14 +448,13 @@ def validate_paid_invoices(self):
if outstanding_amount <= 0 and not is_return:
no_oustanding_refs.setdefault(d.reference_doctype, []).append(d)

for k, v in no_oustanding_refs.items():
for reference_doctype, references in no_oustanding_refs.items():
frappe.msgprint(
_(
"{} - {} now has {} as it had no outstanding amount left before submitting the Payment Entry."
"References {0} of type {1} had no outstanding amount left before submitting the Payment Entry. Now they have a negative outstanding amount."
).format(
_(k),
frappe.bold(", ".join(d.reference_name for d in v)),
frappe.bold(_("negative outstanding amount")),
frappe.bold(comma_and((d.reference_name for d in references))),
_(reference_doctype),
)
+ "<br><br>"
+ _("If this is undesirable please cancel the corresponding Payment Entry."),
Expand Down Expand Up @@ -479,7 +489,7 @@ def validate_journal_entry(self):
if not valid:
frappe.throw(
_("Against Journal Entry {0} does not have any unmatched {1} entry").format(
d.reference_name, dr_or_cr
d.reference_name, _(dr_or_cr)
)
)

Expand Down Expand Up @@ -546,7 +556,7 @@ def update_payment_schedule(self, cancel=0):
if allocated_amount > outstanding:
frappe.throw(
_("Row #{0}: Cannot allocate more than {1} against payment term {2}").format(
idx, outstanding, key[0]
idx, fmt_money(outstanding), key[0]
)
)

Expand Down Expand Up @@ -823,15 +833,15 @@ def validate_payment_against_negative_invoice(self):
_("Cannot {0} {1} {2} without any negative outstanding invoice").format(
_(self.payment_type),
(_("to") if self.party_type == "Customer" else _("from")),
self.party_type,
_(self.party_type),
),
InvalidPaymentEntry,
)

elif paid_amount - additional_charges > total_negative_outstanding:
frappe.throw(
_("Paid Amount cannot be greater than total negative outstanding amount {0}").format(
total_negative_outstanding
fmt_money(total_negative_outstanding)
),
InvalidPaymentEntry,
)
Expand Down Expand Up @@ -1327,6 +1337,9 @@ def get_outstanding_reference_documents(args):
if args.get("party_type") == "Member":
return

if not args.get("get_outstanding_invoices") and not args.get("get_orders_to_be_billed"):
args["get_outstanding_invoices"] = True

# confirm that Supplier is not blocked
if args.get("party_type") == "Supplier":
supplier_status = get_supplier_block_status(args["party"])
Expand Down Expand Up @@ -1433,7 +1446,7 @@ def get_outstanding_reference_documents(args):
_(
"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"))
_(ref_document_type), _(args.get("party_type")).lower(), frappe.bold(args.get("party"))
)
)

Expand Down Expand Up @@ -1508,60 +1521,59 @@ def get_orders_to_be_billed(
cost_center=None,
filters=None,
):
voucher_type = None
if party_type == "Customer":
voucher_type = "Sales Order"
elif party_type == "Supplier":
voucher_type = "Purchase Order"
elif party_type == "Employee":
voucher_type = None

if not voucher_type:
return []

# Add cost center condition
if voucher_type:
doc = frappe.get_doc({"doctype": voucher_type})
condition = ""
if doc and hasattr(doc, "cost_center") and doc.cost_center:
condition = " and cost_center='%s'" % cost_center

orders = []
if voucher_type:
if party_account_currency == company_currency:
grand_total_field = "base_grand_total"
rounded_total_field = "base_rounded_total"
else:
grand_total_field = "grand_total"
rounded_total_field = "rounded_total"

orders = frappe.db.sql(
"""
select
name as voucher_no,
if({rounded_total_field}, {rounded_total_field}, {grand_total_field}) as invoice_amount,
(if({rounded_total_field}, {rounded_total_field}, {grand_total_field}) - advance_paid) as outstanding_amount,
transaction_date as posting_date
from
`tab{voucher_type}`
where
{party_type} = %s
and docstatus = 1
and company = %s
and ifnull(status, "") != "Closed"
and if({rounded_total_field}, {rounded_total_field}, {grand_total_field}) > advance_paid
and abs(100 - per_billed) > 0.01
{condition}
order by
transaction_date, name
""".format(
**{
"rounded_total_field": rounded_total_field,
"grand_total_field": grand_total_field,
"voucher_type": voucher_type,
"party_type": scrub(party_type),
"condition": condition,
}
),
(party, company),
as_dict=True,
)
doc = frappe.get_doc({"doctype": voucher_type})
condition = ""
if doc and hasattr(doc, "cost_center") and doc.cost_center:
condition = " and cost_center='%s'" % cost_center

if party_account_currency == company_currency:
grand_total_field = "base_grand_total"
rounded_total_field = "base_rounded_total"
else:
grand_total_field = "grand_total"
rounded_total_field = "rounded_total"

orders = frappe.db.sql(
"""
select
name as voucher_no,
if({rounded_total_field}, {rounded_total_field}, {grand_total_field}) as invoice_amount,
(if({rounded_total_field}, {rounded_total_field}, {grand_total_field}) - advance_paid) as outstanding_amount,
transaction_date as posting_date
from
`tab{voucher_type}`
where
{party_type} = %s
and docstatus = 1
and company = %s
and ifnull(status, "") != "Closed"
and if({rounded_total_field}, {rounded_total_field}, {grand_total_field}) > advance_paid
and abs(100 - per_billed) > 0.01
{condition}
order by
transaction_date, name
""".format(
**{
"rounded_total_field": rounded_total_field,
"grand_total_field": grand_total_field,
"voucher_type": voucher_type,
"party_type": scrub(party_type),
"condition": condition,
}
),
(party, company),
as_dict=True,
)

order_list = []
for d in orders:
Expand Down Expand Up @@ -1594,6 +1606,8 @@ def get_negative_outstanding_invoices(
cost_center=None,
condition=None,
):
if party_type not in ["Customer", "Supplier"]:
return []
voucher_type = "Sales Invoice" if party_type == "Customer" else "Purchase Invoice"
supplier_condition = ""
if voucher_type == "Purchase Invoice":
Expand Down Expand Up @@ -1642,7 +1656,7 @@ def get_negative_outstanding_invoices(
def get_party_details(company, party_type, party, date, cost_center=None):
bank_account = ""
if not frappe.db.exists(party_type, party):
frappe.throw(_("Invalid {0}: {1}").format(party_type, party))
frappe.throw(_("{0} {1} does not exist").format(_(party_type), party))

party_account = get_party_account(party_type, party, company)

Expand Down Expand Up @@ -1927,7 +1941,7 @@ def get_payment_entry(
if dt in ("Sales Order", "Purchase Order") and flt(doc.per_billed, 2) >= (
100.0 + over_billing_allowance
):
frappe.throw(_("Can only make payment against unbilled {0}").format(dt))
frappe.throw(_("Can only make payment against unbilled {0}").format(_(dt)))

party_type = set_party_type(dt)
party_account = set_party_account(dt, dn, doc, party_type)
Expand Down
5 changes: 3 additions & 2 deletions erpnext/accounts/doctype/pos_invoice/pos_invoice.json
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,8 @@
"no_copy": 1,
"options": "POS Invoice",
"print_hide": 1,
"read_only": 1
"read_only": 1,
"search_index": 1
},
{
"default": "0",
Expand Down Expand Up @@ -1572,7 +1573,7 @@
"icon": "fa fa-file-text",
"is_submittable": 1,
"links": [],
"modified": "2022-09-27 13:00:24.166684",
"modified": "2022-09-30 03:49:50.455199",
"modified_by": "Administrator",
"module": "Accounts",
"name": "POS Invoice",
Expand Down
4 changes: 0 additions & 4 deletions erpnext/accounts/doctype/pos_invoice/pos_invoice.py
Original file line number Diff line number Diff line change
Expand Up @@ -752,7 +752,3 @@ def append_payment(payment_mode):
]:
payment_mode = get_mode_of_payment_info(mode_of_payment, doc.company)
append_payment(payment_mode[0])


def on_doctype_update():
frappe.db.add_index("POS Invoice", ["return_against"])
2 changes: 1 addition & 1 deletion erpnext/accounts/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,7 @@ def get_held_invoices(party_type, party):

if party_type == "Supplier":
held_invoices = frappe.db.sql(
"select name from `tabPurchase Invoice` where release_date IS NOT NULL and release_date > CURDATE()",
"select name from `tabPurchase Invoice` where on_hold = 1 and release_date IS NOT NULL and release_date > CURDATE()",
as_dict=1,
)
held_invoices = set(d["name"] for d in held_invoices)
Expand Down
Loading

0 comments on commit 30c9b15

Please sign in to comment.