perf: improve gl entry submission (#20676)
* perf: improve gl entry submission * perf: add indexes * fix: replace **kwargs with *args * fix: syntax error * fix: remove cypress * fix: travis * chore: remove purchase invoice from status updater * fix: set_staus args Co-Authored-By: Nabin Hait <nabinhait@gmail.com> * fix: only update status for invoices & fees Co-authored-by: Nabin Hait <nabinhait@gmail.com>
This commit is contained in:
parent
d42a4a6234
commit
fb35a54bee
@ -18,7 +18,8 @@
|
||||
"in_list_view": 1,
|
||||
"label": "Invoice",
|
||||
"options": "Sales Invoice",
|
||||
"reqd": 1
|
||||
"reqd": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"fetch_from": "sales_invoice.customer",
|
||||
@ -60,7 +61,7 @@
|
||||
}
|
||||
],
|
||||
"istable": 1,
|
||||
"modified": "2019-09-26 11:05:36.016772",
|
||||
"modified": "2020-02-20 16:16:20.724620",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Discounted Invoice",
|
||||
|
@ -7,4 +7,4 @@ from __future__ import unicode_literals
|
||||
from frappe.model.document import Document
|
||||
|
||||
class DiscountedInvoice(Document):
|
||||
pass
|
||||
pass
|
@ -232,11 +232,36 @@ def update_outstanding_amt(account, party_type, party, against_voucher_type, aga
|
||||
if bal < 0 and not on_cancel:
|
||||
frappe.throw(_("Outstanding for {0} cannot be less than zero ({1})").format(against_voucher, fmt_money(bal)))
|
||||
|
||||
# Update outstanding amt on against voucher
|
||||
if against_voucher_type in ["Sales Invoice", "Purchase Invoice", "Fees"]:
|
||||
update_outstanding_amt_in_ref(against_voucher, against_voucher_type, bal)
|
||||
|
||||
def update_outstanding_amt_in_ref(against_voucher, against_voucher_type, bal):
|
||||
data = []
|
||||
# Update outstanding amt on against voucher
|
||||
if against_voucher_type == "Fees":
|
||||
ref_doc = frappe.get_doc(against_voucher_type, against_voucher)
|
||||
ref_doc.db_set('outstanding_amount', bal)
|
||||
ref_doc.set_status(update=True)
|
||||
return
|
||||
elif against_voucher_type == "Purchase Invoice":
|
||||
from erpnext.accounts.doctype.purchase_invoice.purchase_invoice import get_status
|
||||
data = frappe.db.get_value(against_voucher_type, against_voucher,
|
||||
["name as purchase_invoice", "outstanding_amount",
|
||||
"is_return", "due_date", "docstatus"])
|
||||
elif against_voucher_type == "Sales Invoice":
|
||||
from erpnext.accounts.doctype.sales_invoice.sales_invoice import get_status
|
||||
data = frappe.db.get_value(against_voucher_type, against_voucher,
|
||||
["name as sales_invoice", "outstanding_amount", "is_discounted",
|
||||
"is_return", "due_date", "docstatus"])
|
||||
|
||||
precision = frappe.get_precision(against_voucher_type, "outstanding_amount")
|
||||
data = list(data)
|
||||
data.append(precision)
|
||||
status = get_status(data)
|
||||
frappe.db.set_value(against_voucher_type, against_voucher, {
|
||||
'outstanding_amount': bal,
|
||||
'status': status
|
||||
})
|
||||
|
||||
def validate_frozen_account(account, adv_adj=None):
|
||||
frozen_account = frappe.db.get_value("Account", account, "freeze_account")
|
||||
@ -274,6 +299,9 @@ def update_against_account(voucher_type, voucher_no):
|
||||
if d.against != new_against:
|
||||
frappe.db.set_value("GL Entry", d.name, "against", new_against)
|
||||
|
||||
def on_doctype_update():
|
||||
frappe.db.add_index("GL Entry", ["against_voucher_type", "against_voucher"])
|
||||
frappe.db.add_index("GL Entry", ["voucher_type", "voucher_no"])
|
||||
|
||||
def rename_gle_sle_docs():
|
||||
for doctype in ["GL Entry", "Stock Ledger Entry"]:
|
||||
|
@ -125,6 +125,27 @@ class PurchaseInvoice(BuyingController):
|
||||
else:
|
||||
self.remarks = _("No Remarks")
|
||||
|
||||
def set_status(self, update=False, status=None, update_modified=True):
|
||||
if self.is_new():
|
||||
if self.get('amended_from'):
|
||||
self.status = 'Draft'
|
||||
return
|
||||
|
||||
if not status:
|
||||
precision = self.precision("outstanding_amount")
|
||||
args = [
|
||||
self.name,
|
||||
self.outstanding_amount,
|
||||
self.is_return,
|
||||
self.due_date,
|
||||
self.docstatus,
|
||||
precision
|
||||
]
|
||||
status = get_status(args)
|
||||
|
||||
if update:
|
||||
self.db_set('status', status, update_modified = update_modified)
|
||||
|
||||
def set_missing_values(self, for_validate=False):
|
||||
if not self.credit_to:
|
||||
self.credit_to = get_party_account("Supplier", self.supplier, self.company)
|
||||
@ -1007,6 +1028,34 @@ class PurchaseInvoice(BuyingController):
|
||||
# calculate totals again after applying TDS
|
||||
self.calculate_taxes_and_totals()
|
||||
|
||||
def get_status(*args):
|
||||
purchase_invoice, outstanding_amount, is_return, due_date, docstatus, precision = args[0]
|
||||
|
||||
outstanding_amount = flt(outstanding_amount, precision)
|
||||
due_date = getdate(due_date)
|
||||
now_date = getdate()
|
||||
|
||||
if docstatus == 2:
|
||||
status = "Cancelled"
|
||||
elif docstatus == 1:
|
||||
if outstanding_amount > 0 and due_date < now_date:
|
||||
status = "Overdue"
|
||||
elif outstanding_amount > 0 and due_date >= now_date:
|
||||
status = "Unpaid"
|
||||
#Check if outstanding amount is 0 due to debit note issued against invoice
|
||||
elif outstanding_amount <= 0 and is_return == 0 and frappe.db.get_value('Purchase Invoice', {'is_return': 1, 'return_against': purchase_invoice, 'docstatus': 1}):
|
||||
status = "Debit Note Issued"
|
||||
elif is_return == 1:
|
||||
status = "Return"
|
||||
elif outstanding_amount <=0:
|
||||
status = "Paid"
|
||||
else:
|
||||
status = "Submitted"
|
||||
else:
|
||||
status = "Draft"
|
||||
|
||||
return status
|
||||
|
||||
def get_list_context(context=None):
|
||||
from erpnext.controllers.website_list_for_contact import get_list_context
|
||||
list_context = get_list_context(context)
|
||||
|
@ -1217,62 +1217,83 @@ class SalesInvoice(SellingController):
|
||||
|
||||
self.set_missing_values(for_validate = True)
|
||||
|
||||
def get_discounting_status(self):
|
||||
status = None
|
||||
if self.is_discounted:
|
||||
invoice_discounting_list = frappe.db.sql("""
|
||||
select status
|
||||
from `tabInvoice Discounting` id, `tabDiscounted Invoice` d
|
||||
where
|
||||
id.name = d.parent
|
||||
and d.sales_invoice=%s
|
||||
and id.docstatus=1
|
||||
and status in ('Disbursed', 'Settled')
|
||||
""", self.name)
|
||||
for d in invoice_discounting_list:
|
||||
status = d[0]
|
||||
if status == "Disbursed":
|
||||
break
|
||||
return status
|
||||
|
||||
def set_status(self, update=False, status=None, update_modified=True):
|
||||
if self.is_new():
|
||||
if self.get('amended_from'):
|
||||
self.status = 'Draft'
|
||||
return
|
||||
|
||||
precision = self.precision("outstanding_amount")
|
||||
outstanding_amount = flt(self.outstanding_amount, precision)
|
||||
due_date = getdate(self.due_date)
|
||||
nowdate = getdate()
|
||||
discountng_status = self.get_discounting_status()
|
||||
|
||||
if not status:
|
||||
if self.docstatus == 2:
|
||||
status = "Cancelled"
|
||||
elif self.docstatus == 1:
|
||||
if outstanding_amount > 0 and due_date < nowdate and self.is_discounted and discountng_status=='Disbursed':
|
||||
self.status = "Overdue and Discounted"
|
||||
elif outstanding_amount > 0 and due_date < nowdate:
|
||||
self.status = "Overdue"
|
||||
elif outstanding_amount > 0 and due_date >= nowdate and self.is_discounted and discountng_status=='Disbursed':
|
||||
self.status = "Unpaid and Discounted"
|
||||
elif outstanding_amount > 0 and due_date >= nowdate:
|
||||
self.status = "Unpaid"
|
||||
#Check if outstanding amount is 0 due to credit note issued against invoice
|
||||
elif outstanding_amount <= 0 and self.is_return == 0 and frappe.db.get_value('Sales Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1}):
|
||||
self.status = "Credit Note Issued"
|
||||
elif self.is_return == 1:
|
||||
self.status = "Return"
|
||||
elif outstanding_amount<=0:
|
||||
self.status = "Paid"
|
||||
else:
|
||||
self.status = "Submitted"
|
||||
else:
|
||||
self.status = "Draft"
|
||||
precision = self.precision("outstanding_amount")
|
||||
args = [
|
||||
self.name,
|
||||
self.outstanding_amount,
|
||||
self.is_discounted,
|
||||
self.is_return,
|
||||
self.due_date,
|
||||
self.docstatus,
|
||||
precision,
|
||||
]
|
||||
status = get_status(args)
|
||||
|
||||
if update:
|
||||
self.db_set('status', self.status, update_modified = update_modified)
|
||||
self.db_set('status', status, update_modified = update_modified)
|
||||
|
||||
def get_discounting_status(sales_invoice):
|
||||
status = None
|
||||
|
||||
invoice_discounting_list = frappe.db.sql("""
|
||||
select status
|
||||
from `tabInvoice Discounting` id, `tabDiscounted Invoice` d
|
||||
where
|
||||
id.name = d.parent
|
||||
and d.sales_invoice=%s
|
||||
and id.docstatus=1
|
||||
and status in ('Disbursed', 'Settled')
|
||||
""", sales_invoice)
|
||||
|
||||
for d in invoice_discounting_list:
|
||||
status = d[0]
|
||||
if status == "Disbursed":
|
||||
break
|
||||
|
||||
return status
|
||||
|
||||
def get_status(*args):
|
||||
sales_invoice, outstanding_amount, is_discounted, is_return, due_date, docstatus, precision = args[0]
|
||||
|
||||
discounting_status = None
|
||||
if is_discounted:
|
||||
discounting_status = get_discounting_status(sales_invoice)
|
||||
|
||||
outstanding_amount = flt(outstanding_amount, precision)
|
||||
due_date = getdate(due_date)
|
||||
now_date = getdate()
|
||||
|
||||
if docstatus == 2:
|
||||
status = "Cancelled"
|
||||
elif docstatus == 1:
|
||||
if outstanding_amount > 0 and due_date < now_date and is_discounted and discounting_status=='Disbursed':
|
||||
status = "Overdue and Discounted"
|
||||
elif outstanding_amount > 0 and due_date < now_date:
|
||||
status = "Overdue"
|
||||
elif outstanding_amount > 0 and due_date >= now_date and is_discounted and discounting_status=='Disbursed':
|
||||
status = "Unpaid and Discounted"
|
||||
elif outstanding_amount > 0 and due_date >= now_date:
|
||||
status = "Unpaid"
|
||||
#Check if outstanding amount is 0 due to credit note issued against invoice
|
||||
elif outstanding_amount <= 0 and is_return == 0 and frappe.db.get_value('Sales Invoice', {'is_return': 1, 'return_against': sales_invoice, 'docstatus': 1}):
|
||||
status = "Credit Note Issued"
|
||||
elif is_return == 1:
|
||||
status = "Return"
|
||||
elif outstanding_amount <=0:
|
||||
status = "Paid"
|
||||
else:
|
||||
status = "Submitted"
|
||||
else:
|
||||
status = "Draft"
|
||||
|
||||
return status
|
||||
|
||||
def validate_inter_company_party(doctype, party, company, inter_company_reference):
|
||||
if not party:
|
||||
@ -1444,7 +1465,7 @@ def get_inter_company_details(doc, doctype):
|
||||
"party": party,
|
||||
"company": company
|
||||
}
|
||||
|
||||
|
||||
def get_internal_party(parties, link_doctype, doc):
|
||||
if len(parties) == 1:
|
||||
party = parties[0].name
|
||||
|
@ -140,8 +140,11 @@ def make_entry(args, adv_adj, update_outstanding, from_repost=False):
|
||||
gle = frappe.get_doc(args)
|
||||
gle.flags.ignore_permissions = 1
|
||||
gle.flags.from_repost = from_repost
|
||||
gle.insert()
|
||||
gle.validate()
|
||||
gle.flags.ignore_permissions = True
|
||||
gle.db_insert()
|
||||
gle.run_method("on_update_with_args", adv_adj, update_outstanding, from_repost)
|
||||
gle.flags.ignore_validate = True
|
||||
gle.submit()
|
||||
|
||||
def validate_account_for_perpetual_inventory(gl_map):
|
||||
|
@ -44,17 +44,6 @@ status_map = {
|
||||
["Closed", "eval:self.status=='Closed'"],
|
||||
["On Hold", "eval:self.status=='On Hold'"],
|
||||
],
|
||||
"Purchase Invoice": [
|
||||
["Draft", None],
|
||||
["Submitted", "eval:self.docstatus==1"],
|
||||
["Paid", "eval:self.outstanding_amount==0 and self.docstatus==1"],
|
||||
["Return", "eval:self.is_return==1 and self.docstatus==1"],
|
||||
["Debit Note Issued",
|
||||
"eval:self.outstanding_amount <= 0 and self.docstatus==1 and self.is_return==0 and get_value('Purchase Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1})"],
|
||||
["Unpaid", "eval:self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.docstatus==1"],
|
||||
["Overdue", "eval:self.outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()) and self.docstatus==1"],
|
||||
["Cancelled", "eval:self.docstatus==2"],
|
||||
],
|
||||
"Purchase Order": [
|
||||
["Draft", None],
|
||||
["To Receive and Bill", "eval:self.per_received < 100 and self.per_billed < 100 and self.docstatus == 1"],
|
||||
|
Loading…
x
Reference in New Issue
Block a user