Cleanup and fixes on bypass credit limit check on sales order
This commit is contained in:
parent
57952f6946
commit
68768252ce
@ -10,8 +10,7 @@ data = {
|
|||||||
'ToDo'
|
'ToDo'
|
||||||
],
|
],
|
||||||
'properties': [
|
'properties': [
|
||||||
{'doctype': 'Item', 'fieldname': 'manufacturing', 'property': 'hidden', 'value': 1},
|
{'doctype': 'Item', 'fieldname': 'manufacturing', 'property': 'hidden', 'value': 1}
|
||||||
{'doctype': 'Customer', 'fieldname': 'credit_limit_section', 'property': 'hidden', 'value': 1},
|
|
||||||
],
|
],
|
||||||
'set_value': [
|
'set_value': [
|
||||||
['Stock Settings', None, 'show_barcode_field', 1]
|
['Stock Settings', None, 'show_barcode_field', 1]
|
||||||
|
@ -797,7 +797,7 @@
|
|||||||
"in_global_search": 0,
|
"in_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
"label": "Credit Limit",
|
"label": "Credit Limit and Payment Terms",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
@ -810,7 +810,7 @@
|
|||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0,
|
"unique": 0,
|
||||||
"width": "50%"
|
"width": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
@ -1202,7 +1202,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2017-11-23 18:59:26.897370",
|
"modified": "2017-11-23 17:41:23.243421",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Customer",
|
"name": "Customer",
|
||||||
|
@ -170,37 +170,30 @@ def check_credit_limit(customer, company):
|
|||||||
throw(_("Please contact to the user who have Sales Master Manager {0} role")
|
throw(_("Please contact to the user who have Sales Master Manager {0} role")
|
||||||
.format(" / " + credit_controller if credit_controller else ""))
|
.format(" / " + credit_controller if credit_controller else ""))
|
||||||
|
|
||||||
# get_customer_outstanding is a very generic function which is invoked from many places. A third non mandatory argument is added to change its behaviour based on caller .
|
def get_customer_outstanding(customer, company, ignore_outstanding_sales_order=False):
|
||||||
def get_customer_outstanding(customer, company, ignore_bypass_credit_limit_check_at_sales_order=None):
|
|
||||||
# Outstanding based on GL Entries
|
# Outstanding based on GL Entries
|
||||||
outstanding_based_on_gle = frappe.db.sql("""select sum(debit) - sum(credit)
|
outstanding_based_on_gle = frappe.db.sql("""
|
||||||
from `tabGL Entry` where party_type = 'Customer' and party = %s and company=%s""", (customer, company))
|
select sum(debit) - sum(credit)
|
||||||
|
from `tabGL Entry`
|
||||||
|
where party_type = 'Customer' and party = %s and company=%s""", (customer, company))
|
||||||
|
|
||||||
outstanding_based_on_gle = flt(outstanding_based_on_gle[0][0]) if outstanding_based_on_gle else 0
|
outstanding_based_on_gle = flt(outstanding_based_on_gle[0][0]) if outstanding_based_on_gle else 0
|
||||||
|
|
||||||
# Outstanding based on Sales Order
|
# Outstanding based on Sales Order
|
||||||
outstanding_based_on_so = frappe.db.sql("""
|
outstanding_based_on_so = 0.0
|
||||||
select sum(base_grand_total*(100 - per_billed)/100)
|
|
||||||
from `tabSales Order`
|
|
||||||
where customer=%s and docstatus = 1 and company=%s
|
|
||||||
and per_billed < 100 and status != 'Closed'""", (customer, company))
|
|
||||||
|
|
||||||
outstanding_based_on_so = flt(outstanding_based_on_so[0][0]) if outstanding_based_on_so else 0.0
|
# if credit limit check is bypassed at sales order level,
|
||||||
|
# we should not consider outstanding Sales Orders, when customer credit balance report is run
|
||||||
# Since the credit limit check is bypassed at sales order level, when customer credit balance report is run we need to treat sales order with status 'To Deliver and Bill' as not outstanding
|
if not ignore_outstanding_sales_order:
|
||||||
outstanding_based_on_bypassed_so = 0.0
|
outstanding_based_on_so = frappe.db.sql("""
|
||||||
bypass_credit_limit_check_at_sales_order =cint(frappe.db.get_value("Customer", customer, "bypass_credit_limit_check_at_sales_order"))
|
select sum(base_grand_total*(100 - per_billed)/100)
|
||||||
if bypass_credit_limit_check_at_sales_order == 1 and ignore_bypass_credit_limit_check_at_sales_order==False:
|
|
||||||
outstanding_based_on_bypassed_so = frappe.db.sql("""
|
|
||||||
select (sum(base_grand_total))
|
|
||||||
from `tabSales Order`
|
from `tabSales Order`
|
||||||
where customer=%s and docstatus = 1 and company=%s
|
where customer=%s and docstatus = 1 and company=%s
|
||||||
and advance_paid = 0
|
and per_billed < 100 and status != 'Closed'""", (customer, company))
|
||||||
and per_billed < 100 and status ='To Deliver and Bill'""", (customer, company))
|
|
||||||
|
|
||||||
outstanding_based_on_bypassed_so = flt(outstanding_based_on_bypassed_so[0][0]) if outstanding_based_on_bypassed_so else 0.0
|
outstanding_based_on_so = flt(outstanding_based_on_so[0][0]) if outstanding_based_on_so else 0.0
|
||||||
|
|
||||||
# Outstanding based on Delivery Note
|
# Outstanding based on Delivery Note, which are not created against Sales Order
|
||||||
unmarked_delivery_note_items = frappe.db.sql("""select
|
unmarked_delivery_note_items = frappe.db.sql("""select
|
||||||
dn_item.name, dn_item.amount, dn.base_net_total, dn.base_grand_total
|
dn_item.name, dn_item.amount, dn.base_net_total, dn.base_grand_total
|
||||||
from `tabDelivery Note` dn, `tabDelivery Note Item` dn_item
|
from `tabDelivery Note` dn, `tabDelivery Note Item` dn_item
|
||||||
@ -221,15 +214,16 @@ def get_customer_outstanding(customer, company, ignore_bypass_credit_limit_check
|
|||||||
if flt(dn_item.amount) > flt(si_amount) and dn_item.base_net_total:
|
if flt(dn_item.amount) > flt(si_amount) and dn_item.base_net_total:
|
||||||
outstanding_based_on_dn += ((flt(dn_item.amount) - flt(si_amount)) \
|
outstanding_based_on_dn += ((flt(dn_item.amount) - flt(si_amount)) \
|
||||||
/ dn_item.base_net_total) * dn_item.base_grand_total
|
/ dn_item.base_net_total) * dn_item.base_grand_total
|
||||||
#In return substract the bypassed SO values
|
|
||||||
return outstanding_based_on_gle + outstanding_based_on_so + outstanding_based_on_dn - outstanding_based_on_bypassed_so
|
return outstanding_based_on_gle + outstanding_based_on_so + outstanding_based_on_dn
|
||||||
|
|
||||||
|
|
||||||
def get_credit_limit(customer, company):
|
def get_credit_limit(customer, company):
|
||||||
credit_limit = None
|
credit_limit = None
|
||||||
|
|
||||||
if customer:
|
if customer:
|
||||||
credit_limit, customer_group = frappe.db.get_value("Customer", customer, ["credit_limit", "customer_group"])
|
credit_limit, customer_group = frappe.db.get_value("Customer",
|
||||||
|
customer, ["credit_limit", "customer_group"])
|
||||||
|
|
||||||
if not credit_limit:
|
if not credit_limit:
|
||||||
credit_limit = frappe.db.get_value("Customer Group", customer_group, "credit_limit")
|
credit_limit = frappe.db.get_value("Customer Group", customer_group, "credit_limit")
|
||||||
|
@ -14,6 +14,7 @@ from frappe.desk.notifications import clear_doctype_notifications
|
|||||||
from frappe.contacts.doctype.address.address import get_company_address
|
from frappe.contacts.doctype.address.address import get_company_address
|
||||||
from erpnext.controllers.selling_controller import SellingController
|
from erpnext.controllers.selling_controller import SellingController
|
||||||
from erpnext.accounts.doctype.subscription.subscription import get_next_schedule_date
|
from erpnext.accounts.doctype.subscription.subscription import get_next_schedule_date
|
||||||
|
from erpnext.selling.doctype.customer.customer import check_credit_limit
|
||||||
|
|
||||||
form_grid_templates = {
|
form_grid_templates = {
|
||||||
"items": "templates/form_grid/item_grid.html"
|
"items": "templates/form_grid/item_grid.html"
|
||||||
@ -188,52 +189,68 @@ class SalesOrder(SellingController):
|
|||||||
def update_project(self):
|
def update_project(self):
|
||||||
project_list = []
|
project_list = []
|
||||||
if self.project:
|
if self.project:
|
||||||
project = frappe.get_doc("Project", self.project)
|
project = frappe.get_doc("Project", self.project)
|
||||||
project.flags.dont_sync_tasks = True
|
project.flags.dont_sync_tasks = True
|
||||||
project.update_sales_costing()
|
project.update_sales_costing()
|
||||||
project.save()
|
project.save()
|
||||||
project_list.append(self.project)
|
project_list.append(self.project)
|
||||||
|
|
||||||
def check_credit_limit(self):
|
def check_credit_limit(self):
|
||||||
from erpnext.selling.doctype.customer.customer import check_credit_limit
|
# if bypass credit limit check is set to true (1) at sales order level,
|
||||||
# bypass credit limit check is set to true (1) at sales order level, then we need not to check credit limit and vise versa
|
# then we need not to check credit limit and vise versa
|
||||||
bypass_credit_limit_check_at_sales_order = cint(frappe.db.get_value("Customer", self.customer, "bypass_credit_limit_check_at_sales_order"))
|
if not cint(frappe.db.get_value("Customer", self.customer, "bypass_credit_limit_check_at_sales_order")):
|
||||||
if bypass_credit_limit_check_at_sales_order == 0:
|
check_credit_limit(self.customer, self.company)
|
||||||
check_credit_limit(self.customer, self.company)
|
|
||||||
|
|
||||||
def check_nextdoc_docstatus(self):
|
def check_nextdoc_docstatus(self):
|
||||||
# Checks Delivery Note
|
# Checks Delivery Note
|
||||||
submit_dn = frappe.db.sql_list("""select t1.name from `tabDelivery Note` t1,`tabDelivery Note Item` t2
|
submit_dn = frappe.db.sql_list("""
|
||||||
|
select t1.name
|
||||||
|
from `tabDelivery Note` t1,`tabDelivery Note Item` t2
|
||||||
where t1.name = t2.parent and t2.against_sales_order = %s and t1.docstatus = 1""", self.name)
|
where t1.name = t2.parent and t2.against_sales_order = %s and t1.docstatus = 1""", self.name)
|
||||||
|
|
||||||
if submit_dn:
|
if submit_dn:
|
||||||
frappe.throw(_("Delivery Notes {0} must be cancelled before cancelling this Sales Order").format(comma_and(submit_dn)))
|
frappe.throw(_("Delivery Notes {0} must be cancelled before cancelling this Sales Order")
|
||||||
|
.format(comma_and(submit_dn)))
|
||||||
|
|
||||||
# Checks Sales Invoice
|
# Checks Sales Invoice
|
||||||
submit_rv = frappe.db.sql_list("""select t1.name
|
submit_rv = frappe.db.sql_list("""select t1.name
|
||||||
from `tabSales Invoice` t1,`tabSales Invoice Item` t2
|
from `tabSales Invoice` t1,`tabSales Invoice Item` t2
|
||||||
where t1.name = t2.parent and t2.sales_order = %s and t1.docstatus = 1""",
|
where t1.name = t2.parent and t2.sales_order = %s and t1.docstatus = 1""",
|
||||||
self.name)
|
self.name)
|
||||||
|
|
||||||
if submit_rv:
|
if submit_rv:
|
||||||
frappe.throw(_("Sales Invoice {0} must be cancelled before cancelling this Sales Order").format(comma_and(submit_rv)))
|
frappe.throw(_("Sales Invoice {0} must be cancelled before cancelling this Sales Order")
|
||||||
|
.format(comma_and(submit_rv)))
|
||||||
|
|
||||||
#check maintenance schedule
|
#check maintenance schedule
|
||||||
submit_ms = frappe.db.sql_list("""select t1.name from `tabMaintenance Schedule` t1,
|
submit_ms = frappe.db.sql_list("""
|
||||||
`tabMaintenance Schedule Item` t2
|
select t1.name
|
||||||
|
from `tabMaintenance Schedule` t1, `tabMaintenance Schedule Item` t2
|
||||||
where t2.parent=t1.name and t2.sales_order = %s and t1.docstatus = 1""", self.name)
|
where t2.parent=t1.name and t2.sales_order = %s and t1.docstatus = 1""", self.name)
|
||||||
|
|
||||||
if submit_ms:
|
if submit_ms:
|
||||||
frappe.throw(_("Maintenance Schedule {0} must be cancelled before cancelling this Sales Order").format(comma_and(submit_ms)))
|
frappe.throw(_("Maintenance Schedule {0} must be cancelled before cancelling this Sales Order")
|
||||||
|
.format(comma_and(submit_ms)))
|
||||||
|
|
||||||
# check maintenance visit
|
# check maintenance visit
|
||||||
submit_mv = frappe.db.sql_list("""select t1.name from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2
|
submit_mv = frappe.db.sql_list("""
|
||||||
|
select t1.name
|
||||||
|
from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2
|
||||||
where t2.parent=t1.name and t2.prevdoc_docname = %s and t1.docstatus = 1""",self.name)
|
where t2.parent=t1.name and t2.prevdoc_docname = %s and t1.docstatus = 1""",self.name)
|
||||||
|
|
||||||
if submit_mv:
|
if submit_mv:
|
||||||
frappe.throw(_("Maintenance Visit {0} must be cancelled before cancelling this Sales Order").format(comma_and(submit_mv)))
|
frappe.throw(_("Maintenance Visit {0} must be cancelled before cancelling this Sales Order")
|
||||||
|
.format(comma_and(submit_mv)))
|
||||||
|
|
||||||
# check production order
|
# check production order
|
||||||
pro_order = frappe.db.sql_list("""select name from `tabProduction Order`
|
pro_order = frappe.db.sql_list("""
|
||||||
|
select name
|
||||||
|
from `tabProduction Order`
|
||||||
where sales_order = %s and docstatus = 1""", self.name)
|
where sales_order = %s and docstatus = 1""", self.name)
|
||||||
|
|
||||||
if pro_order:
|
if pro_order:
|
||||||
frappe.throw(_("Production Order {0} must be cancelled before cancelling this Sales Order").format(comma_and(pro_order)))
|
frappe.throw(_("Production Order {0} must be cancelled before cancelling this Sales Order")
|
||||||
|
.format(comma_and(pro_order)))
|
||||||
|
|
||||||
def check_modified_date(self):
|
def check_modified_date(self):
|
||||||
mod_db = frappe.db.get_value("Sales Order", self.name, "modified")
|
mod_db = frappe.db.get_value("Sales Order", self.name, "modified")
|
||||||
@ -466,10 +483,10 @@ def make_delivery_note(source_name, target_doc=None):
|
|||||||
target.po_no = ", ".join(list(set(target_po_no))) if len(target_po_no) > 1 else target_po_no[0]
|
target.po_no = ", ".join(list(set(target_po_no))) if len(target_po_no) > 1 else target_po_no[0]
|
||||||
else:
|
else:
|
||||||
target.po_no = source.po_no
|
target.po_no = source.po_no
|
||||||
# Since the credit limit check is bypassed at sales order level, we need to check it at delivery note
|
|
||||||
bypass_credit_limit_check_at_sales_order = cint(frappe.db.get_value("Customer", source.customer, "bypass_credit_limit_check_at_sales_order"))
|
# Since the credit limit check is bypassed at sales order level,
|
||||||
if bypass_credit_limit_check_at_sales_order == 1:
|
# we need to check it at delivery note
|
||||||
from erpnext.selling.doctype.customer.customer import check_credit_limit
|
if cint(frappe.db.get_value("Customer", source.customer, "bypass_credit_limit_check_at_sales_order")):
|
||||||
check_credit_limit(source.customer, source.company)
|
check_credit_limit(source.customer, source.company)
|
||||||
|
|
||||||
target.ignore_pricing_rule = 1
|
target.ignore_pricing_rule = 1
|
||||||
@ -535,10 +552,9 @@ def make_sales_invoice(source_name, target_doc=None, ignore_permissions=False):
|
|||||||
target.flags.ignore_permissions = True
|
target.flags.ignore_permissions = True
|
||||||
target.run_method("set_missing_values")
|
target.run_method("set_missing_values")
|
||||||
target.run_method("calculate_taxes_and_totals")
|
target.run_method("calculate_taxes_and_totals")
|
||||||
# Since the credit limit check is bypassed at sales order level, we need to check it at sales invoice
|
|
||||||
bypass_credit_limit_check_at_sales_order = cint(frappe.db.get_value("Customer", source.customer, "bypass_credit_limit_check_at_sales_order"))
|
# Since the credit limit check is bypassed at sales order level, we need to check it at sales invoice
|
||||||
if bypass_credit_limit_check_at_sales_order == 1:
|
if cint(frappe.db.get_value("Customer", source.customer, "bypass_credit_limit_check_at_sales_order")):
|
||||||
from erpnext.selling.doctype.customer.customer import check_credit_limit
|
|
||||||
check_credit_limit(source.customer, source.company)
|
check_credit_limit(source.customer, source.company)
|
||||||
|
|
||||||
# set company address
|
# set company address
|
||||||
|
@ -19,15 +19,19 @@ def execute(filters=None):
|
|||||||
|
|
||||||
for d in customer_list:
|
for d in customer_list:
|
||||||
row = []
|
row = []
|
||||||
#3rd argument has flag
|
|
||||||
outstanding_amt = get_customer_outstanding(d.name, filters.get("company"),False)
|
outstanding_amt = get_customer_outstanding(d.name, filters.get("company"),
|
||||||
|
ignore_outstanding_sales_order=d.bypass_credit_limit_check_at_sales_order)
|
||||||
|
|
||||||
credit_limit = get_credit_limit(d.name, filters.get("company"))
|
credit_limit = get_credit_limit(d.name, filters.get("company"))
|
||||||
|
|
||||||
bal = flt(credit_limit) - flt(outstanding_amt)
|
bal = flt(credit_limit) - flt(outstanding_amt)
|
||||||
#Value of new col is passed
|
|
||||||
if customer_naming_type == "Naming Series":
|
if customer_naming_type == "Naming Series":
|
||||||
row = [d.name, d.customer_name, d.bypass_credit_limit_check_at_sales_order, credit_limit, outstanding_amt, bal]
|
row = [d.name, d.customer_name, credit_limit, outstanding_amt, bal,
|
||||||
|
d.bypass_credit_limit_check_at_sales_order]
|
||||||
else:
|
else:
|
||||||
row = [d.name, d.bypass_credit_limit_check_at_sales_order, credit_limit, outstanding_amt, bal]
|
row = [d.name, credit_limit, outstanding_amt, bal, d.bypass_credit_limit_check_at_sales_order]
|
||||||
|
|
||||||
if credit_limit:
|
if credit_limit:
|
||||||
data.append(row)
|
data.append(row)
|
||||||
@ -36,9 +40,11 @@ def execute(filters=None):
|
|||||||
|
|
||||||
def get_columns(customer_naming_type):
|
def get_columns(customer_naming_type):
|
||||||
columns = [
|
columns = [
|
||||||
# New column is added to reflect status of bypass credit limit check flag of sales order
|
_("Customer") + ":Link/Customer:120",
|
||||||
_("Customer") + ":Link/Customer:120", _("Bypass credit check at Sales Order ") + ":Check:30", _("Credit Limit") + ":Currency:120",
|
_("Credit Limit") + ":Currency:120",
|
||||||
_("Outstanding Amt") + ":Currency:100", _("Credit Balance") + ":Currency:120"
|
_("Outstanding Amt") + ":Currency:100",
|
||||||
|
_("Credit Balance") + ":Currency:120",
|
||||||
|
_("Bypass credit check at Sales Order ") + ":Check:240"
|
||||||
]
|
]
|
||||||
|
|
||||||
if customer_naming_type == "Naming Series":
|
if customer_naming_type == "Naming Series":
|
||||||
@ -52,6 +58,6 @@ def get_details(filters):
|
|||||||
if filters.get("customer"):
|
if filters.get("customer"):
|
||||||
conditions += " where name = %(customer)s"
|
conditions += " where name = %(customer)s"
|
||||||
|
|
||||||
# Return column bypass credit limit check at sales order level
|
return frappe.db.sql("""select name, customer_name,
|
||||||
return frappe.db.sql("""select name, customer_name, bypass_credit_limit_check_at_sales_order from `tabCustomer` %s"""
|
bypass_credit_limit_check_at_sales_order from `tabCustomer` %s
|
||||||
% conditions, filters, as_dict=1)
|
""" % conditions, filters, as_dict=1)
|
Loading…
Reference in New Issue
Block a user