Merge branch 'feature_10861' of https://github.com/ashish-greycube/erpnext into feature_10861
This commit is contained in:
commit
62155fa0e5
@ -918,6 +918,13 @@ def make_delivery_note(source_name, target_doc=None):
|
|||||||
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")
|
||||||
|
|
||||||
|
#PR : 10861, Author : ashish-greycube & jigneshpshah, Email:mr.ashish.shah@gmail.com
|
||||||
|
# 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"))
|
||||||
|
if bypass_credit_limit_check_at_sales_order == 1:
|
||||||
|
from erpnext.selling.doctype.customer.customer import check_credit_limit
|
||||||
|
check_credit_limit(source.customer, source.company)
|
||||||
|
|
||||||
def update_item(source_doc, target_doc, source_parent):
|
def update_item(source_doc, target_doc, source_parent):
|
||||||
target_doc.qty = flt(source_doc.qty) - flt(source_doc.delivered_qty)
|
target_doc.qty = flt(source_doc.qty) - flt(source_doc.delivered_qty)
|
||||||
target_doc.stock_qty = target_doc.qty * flt(source_doc.conversion_factor)
|
target_doc.stock_qty = target_doc.qty * flt(source_doc.conversion_factor)
|
||||||
|
@ -456,9 +456,13 @@ erpnext.patches.v9_0.add_healthcare_domain
|
|||||||
erpnext.patches.v9_0.set_variant_item_description
|
erpnext.patches.v9_0.set_variant_item_description
|
||||||
erpnext.patches.v9_0.set_uoms_in_variant_field
|
erpnext.patches.v9_0.set_uoms_in_variant_field
|
||||||
erpnext.patches.v9_0.copy_old_fees_field_data
|
erpnext.patches.v9_0.copy_old_fees_field_data
|
||||||
|
<<<<<<< HEAD
|
||||||
execute:frappe.delete_doc_if_exists("DocType", "Program Fee")
|
execute:frappe.delete_doc_if_exists("DocType", "Program Fee")
|
||||||
erpnext.patches.v9_0.set_pos_profile_name
|
erpnext.patches.v9_0.set_pos_profile_name
|
||||||
erpnext.patches.v9_0.remove_non_existing_warehouse_from_stock_settings
|
erpnext.patches.v9_0.remove_non_existing_warehouse_from_stock_settings
|
||||||
execute:frappe.delete_doc_if_exists("DocType", "Program Fee")
|
execute:frappe.delete_doc_if_exists("DocType", "Program Fee")
|
||||||
erpnext.patches.v9_0.update_employee_loan_details
|
erpnext.patches.v9_0.update_employee_loan_details
|
||||||
erpnext.patches.v9_2.delete_healthcare_domain_default_items
|
erpnext.patches.v9_2.delete_healthcare_domain_default_items
|
||||||
|
=======
|
||||||
|
erpnext.patches.v9_0.set_bypasscreditlimitcheckatsalesorder_in_customer
|
||||||
|
>>>>>>> b883e4ee0d5a1fdbb8c25fe95f7af6b76d07b099
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
frappe.reload_doctype("Customer")
|
||||||
|
|
||||||
|
if "bypass_credit_limit_check_at_sales_order" in frappe.db.get_table_columns("Customer"):
|
||||||
|
frappe.db.sql("""
|
||||||
|
update `tabCustomer`
|
||||||
|
set bypass_credit_limit_check_at_sales_order = 0
|
||||||
|
where (bypass_credit_limit_check_at_sales_order is NULL)""")
|
@ -907,6 +907,37 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "bypass_credit_limit_check_at_sales_order",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Bypass credit limit check at Sales Order",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -1202,7 +1233,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2017-07-24 00:55:07.445783",
|
"modified": "2017-10-26 16:21:18.028471",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Customer",
|
"name": "Customer",
|
||||||
|
@ -170,7 +170,9 @@ 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 ""))
|
||||||
|
|
||||||
def get_customer_outstanding(customer, company):
|
#PR : 10861, Author : ashish-greycube & jigneshpshah, Email:mr.ashish.shah@gmail.com
|
||||||
|
# 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,caller=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("""select sum(debit) - sum(credit)
|
||||||
from `tabGL Entry` where party_type = 'Customer' and party = %s and company=%s""", (customer, company))
|
from `tabGL Entry` where party_type = 'Customer' and party = %s and company=%s""", (customer, company))
|
||||||
@ -186,6 +188,20 @@ def get_customer_outstanding(customer, company):
|
|||||||
|
|
||||||
outstanding_based_on_so = flt(outstanding_based_on_so[0][0]) if outstanding_based_on_so else 0.0
|
outstanding_based_on_so = flt(outstanding_based_on_so[0][0]) if outstanding_based_on_so else 0.0
|
||||||
|
|
||||||
|
#PR : 10861, Author : ashish-greycube & jigneshpshah, Email:mr.ashish.shah@gmail.com
|
||||||
|
# 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
|
||||||
|
outstanding_based_on_bypassed_so = 0.0
|
||||||
|
bypass_credit_limit_check_at_sales_order = cint(frappe.db.get_value("Customer", customer, "bypass_credit_limit_check_at_sales_order"))
|
||||||
|
if bypass_credit_limit_check_at_sales_order == 1 and caller=='customer_credit_balance_report':
|
||||||
|
outstanding_based_on_bypassed_so = frappe.db.sql("""
|
||||||
|
select (sum(base_grand_total))
|
||||||
|
from `tabSales Order`
|
||||||
|
where customer=%s and docstatus = 1 and company=%s
|
||||||
|
and advance_paid = 0
|
||||||
|
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 Delivery Note
|
# Outstanding based on Delivery Note
|
||||||
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
|
||||||
@ -207,8 +223,8 @@ def get_customer_outstanding(customer, company):
|
|||||||
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
|
||||||
|
#PR : 10861, Author : ashish-greycube & jigneshpshah, Email:mr.ashish.shah@gmail.com. In return substract the bypassed SO values
|
||||||
return outstanding_based_on_gle + outstanding_based_on_so + outstanding_based_on_dn
|
return outstanding_based_on_gle + outstanding_based_on_so + outstanding_based_on_dn - outstanding_based_on_bypassed_so
|
||||||
|
|
||||||
|
|
||||||
def get_credit_limit(customer, company):
|
def get_credit_limit(customer, company):
|
||||||
|
@ -196,7 +196,11 @@ class SalesOrder(SellingController):
|
|||||||
|
|
||||||
def check_credit_limit(self):
|
def check_credit_limit(self):
|
||||||
from erpnext.selling.doctype.customer.customer import check_credit_limit
|
from erpnext.selling.doctype.customer.customer import check_credit_limit
|
||||||
check_credit_limit(self.customer, self.company)
|
#PR : 10861, Author : ashish-greycube & jigneshpshah, Email:mr.ashish.shah@gmail.com
|
||||||
|
# bypass credit limit check is set to true (1) at sales order level, 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 bypass_credit_limit_check_at_sales_order == 0:
|
||||||
|
check_credit_limit(self.customer, self.company)
|
||||||
|
|
||||||
def check_nextdoc_docstatus(self):
|
def check_nextdoc_docstatus(self):
|
||||||
# Checks Delivery Note
|
# Checks Delivery Note
|
||||||
@ -464,6 +468,13 @@ def make_delivery_note(source_name, target_doc=None):
|
|||||||
else:
|
else:
|
||||||
target.po_no = source.po_no
|
target.po_no = source.po_no
|
||||||
|
|
||||||
|
#PR : 10861, Author : ashish-greycube & jigneshpshah, Email:mr.ashish.shah@gmail.com
|
||||||
|
# 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"))
|
||||||
|
if bypass_credit_limit_check_at_sales_order == 1:
|
||||||
|
from erpnext.selling.doctype.customer.customer import check_credit_limit
|
||||||
|
check_credit_limit(source.customer, source.company)
|
||||||
|
|
||||||
target.ignore_pricing_rule = 1
|
target.ignore_pricing_rule = 1
|
||||||
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")
|
||||||
@ -528,6 +539,13 @@ def make_sales_invoice(source_name, target_doc=None, ignore_permissions=False):
|
|||||||
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")
|
||||||
|
|
||||||
|
#PR : 10861, Author : ashish-greycube & jigneshpshah, Email:mr.ashish.shah@gmail.com
|
||||||
|
# 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"))
|
||||||
|
if bypass_credit_limit_check_at_sales_order == 1:
|
||||||
|
from erpnext.selling.doctype.customer.customer import check_credit_limit
|
||||||
|
check_credit_limit(source.customer, source.company)
|
||||||
|
|
||||||
# set company address
|
# set company address
|
||||||
target.update(get_company_address(target.company))
|
target.update(get_company_address(target.company))
|
||||||
if target.company_address:
|
if target.company_address:
|
||||||
|
@ -0,0 +1,54 @@
|
|||||||
|
QUnit.module('Sales Order');
|
||||||
|
|
||||||
|
QUnit.test("test_sales_order_with_bypass_credit_limit_check", function(assert) {
|
||||||
|
//#PR : 10861, Author : ashish-greycube & jigneshpshah, Email:mr.ashish.shah@gmail.com
|
||||||
|
assert.expect(2);
|
||||||
|
let done = assert.async();
|
||||||
|
frappe.run_serially([
|
||||||
|
() => frappe.new_doc('Customer'),
|
||||||
|
() => frappe.timeout(1),
|
||||||
|
() => frappe.click_link('Edit in full page'),
|
||||||
|
() => cur_frm.set_value("customer_name", "Test Customer 10"),
|
||||||
|
() => cur_frm.set_value("credit_limit", 100.00),
|
||||||
|
() => cur_frm.set_value("bypass_credit_limit_check_at_sales_order", 1),
|
||||||
|
// save form
|
||||||
|
() => cur_frm.save(),
|
||||||
|
() => frappe.timeout(1),
|
||||||
|
|
||||||
|
() => frappe.new_doc('Item'),
|
||||||
|
() => frappe.timeout(1),
|
||||||
|
() => frappe.click_link('Edit in full page'),
|
||||||
|
() => cur_frm.set_value("item_code", "Test Product 10"),
|
||||||
|
() => cur_frm.set_value("item_group", "Products"),
|
||||||
|
() => cur_frm.set_value("standard_rate", 100),
|
||||||
|
// save form
|
||||||
|
() => cur_frm.save(),
|
||||||
|
() => frappe.timeout(1),
|
||||||
|
|
||||||
|
() => {
|
||||||
|
return frappe.tests.make('Sales Order', [
|
||||||
|
{customer: 'Test Customer 5'},
|
||||||
|
{items: [
|
||||||
|
[
|
||||||
|
{'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
|
||||||
|
{'qty': 5},
|
||||||
|
{'item_code': 'Test Product 10'},
|
||||||
|
]
|
||||||
|
]}
|
||||||
|
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
() => cur_frm.save(),
|
||||||
|
() => frappe.tests.click_button('Submit'),
|
||||||
|
() => assert.equal("Confirm", cur_dialog.title,'confirmation for submit'),
|
||||||
|
() => frappe.tests.click_button('Yes'),
|
||||||
|
() => frappe.timeout(3),
|
||||||
|
() => {
|
||||||
|
|
||||||
|
assert.ok(cur_frm.doc.status=="To Deliver and Bill", "It is submited. Credit limit is NOT checked for sales order");
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
() => done()
|
||||||
|
]);
|
||||||
|
});
|
@ -0,0 +1,59 @@
|
|||||||
|
QUnit.module('Sales Order');
|
||||||
|
|
||||||
|
QUnit.test("test_sales_order_without_bypass_credit_limit_check", function(assert) {
|
||||||
|
//#PR : 10861, Author : ashish-greycube & jigneshpshah, Email:mr.ashish.shah@gmail.com
|
||||||
|
assert.expect(2);
|
||||||
|
let done = assert.async();
|
||||||
|
frappe.run_serially([
|
||||||
|
() => frappe.new_doc('Customer'),
|
||||||
|
() => frappe.timeout(1),
|
||||||
|
() => frappe.click_link('Edit in full page'),
|
||||||
|
() => cur_frm.set_value("customer_name", "Test Customer 11"),
|
||||||
|
() => cur_frm.set_value("credit_limit", 100.00),
|
||||||
|
() => cur_frm.set_value("bypass_credit_limit_check_at_sales_order", 0),
|
||||||
|
// save form
|
||||||
|
() => cur_frm.save(),
|
||||||
|
() => frappe.timeout(1),
|
||||||
|
|
||||||
|
() => frappe.new_doc('Item'),
|
||||||
|
() => frappe.timeout(1),
|
||||||
|
() => frappe.click_link('Edit in full page'),
|
||||||
|
() => cur_frm.set_value("item_code", "Test Product 11"),
|
||||||
|
() => cur_frm.set_value("item_group", "Products"),
|
||||||
|
() => cur_frm.set_value("standard_rate", 100),
|
||||||
|
// save form
|
||||||
|
() => cur_frm.save(),
|
||||||
|
() => frappe.timeout(1),
|
||||||
|
|
||||||
|
() => {
|
||||||
|
return frappe.tests.make('Sales Order', [
|
||||||
|
{customer: 'Test Customer 11'},
|
||||||
|
{items: [
|
||||||
|
[
|
||||||
|
{'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
|
||||||
|
{'qty': 5},
|
||||||
|
{'item_code': 'Test Product 11'},
|
||||||
|
]
|
||||||
|
]}
|
||||||
|
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
() => cur_frm.save(),
|
||||||
|
() => frappe.tests.click_button('Submit'),
|
||||||
|
() => assert.equal("Confirm", cur_dialog.title,'confirmation for submit'),
|
||||||
|
() => frappe.tests.click_button('Yes'),
|
||||||
|
() => frappe.timeout(3),
|
||||||
|
() => {
|
||||||
|
|
||||||
|
if (cur_dialog.body.innerText.match(/^Credit limit has been crossed for customer.*$/))
|
||||||
|
{
|
||||||
|
/*Match found */
|
||||||
|
assert.ok(true, "Credit Limit crossed message received");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
() => cur_dialog.cancel(),
|
||||||
|
() => done()
|
||||||
|
]);
|
||||||
|
});
|
@ -19,14 +19,15 @@ def execute(filters=None):
|
|||||||
|
|
||||||
for d in customer_list:
|
for d in customer_list:
|
||||||
row = []
|
row = []
|
||||||
outstanding_amt = get_customer_outstanding(d.name, filters.get("company"))
|
#PR : 10861, Author : ashish-greycube & jigneshpshah, Email:mr.ashish.shah@gmail.com. 3rd arg is added
|
||||||
|
outstanding_amt = get_customer_outstanding(d.name, filters.get("company"),'customer_credit_balance_report')
|
||||||
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)
|
||||||
|
#PR : 10861, Author : ashish-greycube & jigneshpshah, Email:mr.ashish.shah@gmail.com. Value of new col is passed
|
||||||
if customer_naming_type == "Naming Series":
|
if customer_naming_type == "Naming Series":
|
||||||
row = [d.name, d.customer_name, credit_limit, outstanding_amt, bal]
|
row = [d.name, d.customer_name, d.bypass_credit_limit_check_at_sales_order, credit_limit, outstanding_amt, bal]
|
||||||
else:
|
else:
|
||||||
row = [d.name, credit_limit, outstanding_amt, bal]
|
row = [d.name, d.bypass_credit_limit_check_at_sales_order, credit_limit, outstanding_amt, bal]
|
||||||
|
|
||||||
if credit_limit:
|
if credit_limit:
|
||||||
data.append(row)
|
data.append(row)
|
||||||
@ -35,7 +36,9 @@ def execute(filters=None):
|
|||||||
|
|
||||||
def get_columns(customer_naming_type):
|
def get_columns(customer_naming_type):
|
||||||
columns = [
|
columns = [
|
||||||
_("Customer") + ":Link/Customer:120", _("Credit Limit") + ":Currency:120",
|
#PR : 10861, Author : ashish-greycube & jigneshpshah, Email:mr.ashish.shah@gmail.com
|
||||||
|
# New column is added to reflect status of bypass credit limit check flag of sales order
|
||||||
|
_("Customer") + ":Link/Customer:120",_("Bypass credit check at Sales Order ") + ":Check:30", _("Credit Limit") + ":Currency:120",
|
||||||
_("Outstanding Amt") + ":Currency:100", _("Credit Balance") + ":Currency:120"
|
_("Outstanding Amt") + ":Currency:100", _("Credit Balance") + ":Currency:120"
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -49,6 +52,7 @@ def get_details(filters):
|
|||||||
|
|
||||||
if filters.get("customer"):
|
if filters.get("customer"):
|
||||||
conditions += " where name = %(customer)s"
|
conditions += " where name = %(customer)s"
|
||||||
|
#PR : 10861, Author : ashish-greycube & jigneshpshah, Email:mr.ashish.shah@gmail.com
|
||||||
return frappe.db.sql("""select name, customer_name from `tabCustomer` %s"""
|
# Return column bypass credit limit check at sales order level
|
||||||
|
return frappe.db.sql("""select name, customer_name,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