8d9d0987fe
Co-authored-by: Pruthvi Patel <pruthvipatel145@gmail.com>
114 lines
2.6 KiB
Python
114 lines
2.6 KiB
Python
import frappe
|
|
from frappe.utils import flt, getdate
|
|
|
|
from erpnext.accounts.doctype.sales_invoice.sales_invoice import (
|
|
get_total_in_party_account_currency,
|
|
is_overdue,
|
|
)
|
|
|
|
TODAY = getdate()
|
|
|
|
def execute():
|
|
# This fix is not related to Party Specific Item,
|
|
# but it is needed for code introduced after Party Specific Item was
|
|
# If your DB doesn't have this doctype yet, you should be fine
|
|
if not frappe.db.exists("DocType", "Party Specific Item"):
|
|
return
|
|
|
|
for doctype in ("Purchase Invoice", "Sales Invoice"):
|
|
fields = [
|
|
"name",
|
|
"status",
|
|
"due_date",
|
|
"outstanding_amount",
|
|
"grand_total",
|
|
"base_grand_total",
|
|
"rounded_total",
|
|
"base_rounded_total",
|
|
"disable_rounded_total",
|
|
]
|
|
if doctype == "Sales Invoice":
|
|
fields.append("is_pos")
|
|
|
|
invoices_to_update = frappe.get_all(
|
|
doctype,
|
|
fields=fields,
|
|
filters={
|
|
"docstatus": 1,
|
|
"status": ("in", (
|
|
"Overdue",
|
|
"Overdue and Discounted",
|
|
"Partly Paid",
|
|
"Partly Paid and Discounted"
|
|
)),
|
|
"outstanding_amount": (">", 0),
|
|
"modified": (">", "2021-01-01")
|
|
# an assumption is being made that only invoices modified
|
|
# after 2021 got affected as incorrectly overdue.
|
|
# required for performance reasons.
|
|
}
|
|
)
|
|
|
|
invoices_to_update = {
|
|
invoice.name: invoice for invoice in invoices_to_update
|
|
}
|
|
|
|
payment_schedule_items = frappe.get_all(
|
|
"Payment Schedule",
|
|
fields=(
|
|
"due_date",
|
|
"payment_amount",
|
|
"base_payment_amount",
|
|
"parent"
|
|
),
|
|
filters={"parent": ("in", invoices_to_update)}
|
|
)
|
|
|
|
for item in payment_schedule_items:
|
|
invoices_to_update[item.parent].setdefault(
|
|
"payment_schedule", []
|
|
).append(item)
|
|
|
|
status_map = {}
|
|
|
|
for invoice in invoices_to_update.values():
|
|
invoice.doctype = doctype
|
|
doc = frappe.get_doc(invoice)
|
|
correct_status = get_correct_status(doc)
|
|
if not correct_status or doc.status == correct_status:
|
|
continue
|
|
|
|
status_map.setdefault(correct_status, []).append(doc.name)
|
|
|
|
for status, docs in status_map.items():
|
|
frappe.db.set_value(
|
|
doctype, {"name": ("in", docs)},
|
|
"status",
|
|
status,
|
|
update_modified=False
|
|
)
|
|
|
|
|
|
|
|
def get_correct_status(doc):
|
|
outstanding_amount = flt(
|
|
doc.outstanding_amount, doc.precision("outstanding_amount")
|
|
)
|
|
total = get_total_in_party_account_currency(doc)
|
|
|
|
status = ""
|
|
if is_overdue(doc, total):
|
|
status = "Overdue"
|
|
elif 0 < outstanding_amount < total:
|
|
status = "Partly Paid"
|
|
elif outstanding_amount > 0 and getdate(doc.due_date) >= TODAY:
|
|
status = "Unpaid"
|
|
|
|
if not status:
|
|
return
|
|
|
|
if doc.status.endswith(" and Discounted"):
|
|
status += " and Discounted"
|
|
|
|
return status
|