Added Disabled field to Supplier and Customer doctype
Frozen field is moved to More Information section for Customer and Supplier. Any Supplier/Customer which is disabled will not be shown while creating PO/SO
This commit is contained in:
parent
2ea5c6913d
commit
29b565fdf5
@ -6,10 +6,10 @@ import frappe
|
|||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import flt, fmt_money, getdate, formatdate
|
from frappe.utils import flt, fmt_money, getdate, formatdate
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from erpnext.accounts.party import validate_party_gle_currency
|
from erpnext.accounts.party import validate_party_gle_currency, validate_party_frozen_disabled
|
||||||
from erpnext.accounts.utils import get_account_currency
|
from erpnext.accounts.utils import get_account_currency
|
||||||
from erpnext.setup.doctype.company.company import get_company_currency
|
from erpnext.setup.doctype.company.company import get_company_currency
|
||||||
from erpnext.exceptions import InvalidAccountCurrency, CustomerFrozen
|
from erpnext.exceptions import InvalidAccountCurrency
|
||||||
|
|
||||||
exclude_from_linked_with = True
|
exclude_from_linked_with = True
|
||||||
|
|
||||||
@ -96,11 +96,7 @@ class GLEntry(Document):
|
|||||||
frappe.throw(_("Cost Center {0} does not belong to Company {1}").format(self.cost_center, self.company))
|
frappe.throw(_("Cost Center {0} does not belong to Company {1}").format(self.cost_center, self.company))
|
||||||
|
|
||||||
def validate_party(self):
|
def validate_party(self):
|
||||||
if self.party_type and self.party:
|
validate_party_frozen_disabled(self.party, self.party_type)
|
||||||
frozen_accounts_modifier = frappe.db.get_value( 'Accounts Settings', None,'frozen_accounts_modifier')
|
|
||||||
if not frozen_accounts_modifier in frappe.get_roles():
|
|
||||||
if frappe.db.get_value(self.party_type, self.party, "is_frozen"):
|
|
||||||
frappe.throw("{0} {1} is frozen".format(self.party_type, self.party), CustomerFrozen)
|
|
||||||
|
|
||||||
def validate_currency(self):
|
def validate_currency(self):
|
||||||
company_currency = get_company_currency(self.company)
|
company_currency = get_company_currency(self.company)
|
||||||
|
@ -10,7 +10,7 @@ from frappe.defaults import get_user_permissions
|
|||||||
from frappe.utils import add_days, getdate, formatdate, get_first_day, date_diff
|
from frappe.utils import add_days, getdate, formatdate, get_first_day, date_diff
|
||||||
from erpnext.utilities.doctype.address.address import get_address_display
|
from erpnext.utilities.doctype.address.address import get_address_display
|
||||||
from erpnext.utilities.doctype.contact.contact import get_contact_details
|
from erpnext.utilities.doctype.contact.contact import get_contact_details
|
||||||
from erpnext.exceptions import InvalidAccountCurrency
|
from erpnext.exceptions import CustomerFrozen, InvalidCurrency, CustomerDisabled
|
||||||
|
|
||||||
class DuplicatePartyAccountError(frappe.ValidationError): pass
|
class DuplicatePartyAccountError(frappe.ValidationError): pass
|
||||||
|
|
||||||
@ -308,3 +308,13 @@ def set_taxes(party, party_type, posting_date, company, customer_group=None, sup
|
|||||||
args.update({"use_for_shopping_cart": use_for_shopping_cart})
|
args.update({"use_for_shopping_cart": use_for_shopping_cart})
|
||||||
|
|
||||||
return get_tax_template(posting_date, args)
|
return get_tax_template(posting_date, args)
|
||||||
|
|
||||||
|
def validate_party_frozen_disabled(party, party_type):
|
||||||
|
if party_type and party:
|
||||||
|
frozen_accounts_modifier = frappe.db.get_value( 'Accounts Settings', None,'frozen_accounts_modifier')
|
||||||
|
if not frozen_accounts_modifier in frappe.get_roles():
|
||||||
|
if frappe.db.get_value(party_type, party, "is_frozen"):
|
||||||
|
frappe.throw("{0} {1} is frozen".format(party_type, party), CustomerFrozen)
|
||||||
|
|
||||||
|
if frappe.db.get_value(party_type, party, "disabled"):
|
||||||
|
frappe.throw("{0} {1} is disabled".format(party_type, party), CustomerDisabled)
|
||||||
|
@ -137,15 +137,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 1,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"fieldname": "is_frozen",
|
"default": "0",
|
||||||
|
"fieldname": "disabled",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"label": "Is Frozen",
|
"label": "Disabled",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
@ -459,7 +460,7 @@
|
|||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"label": "Supplier Details",
|
"label": "More Information",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
@ -523,6 +524,30 @@
|
|||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"fieldname": "is_frozen",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "Is Frozen",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"hide_heading": 0,
|
"hide_heading": 0,
|
||||||
@ -535,7 +560,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2016-01-22 02:18:14.158258",
|
"modified": "2016-01-25 06:55:53.404069",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Supplier",
|
"name": "Supplier",
|
||||||
|
@ -2,9 +2,11 @@
|
|||||||
# License: GNU General Public License v3. See license.txt
|
# License: GNU General Public License v3. See license.txt
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import frappe
|
|
||||||
import unittest
|
import frappe, unittest
|
||||||
from erpnext.accounts.party import get_due_date
|
from erpnext.accounts.party import get_due_date
|
||||||
|
from erpnext.exceptions import CustomerFrozen, CustomerDisabled
|
||||||
|
from frappe.test_runner import make_test_records
|
||||||
|
|
||||||
test_records = frappe.get_test_records('Supplier')
|
test_records = frappe.get_test_records('Supplier')
|
||||||
|
|
||||||
@ -52,3 +54,19 @@ class TestSupplier(unittest.TestCase):
|
|||||||
# Non Leap year
|
# Non Leap year
|
||||||
due_date = get_due_date("2017-01-22", "Supplier", "_Test Supplier", "_Test Company")
|
due_date = get_due_date("2017-01-22", "Supplier", "_Test Supplier", "_Test Company")
|
||||||
self.assertEqual(due_date, "2017-02-28")
|
self.assertEqual(due_date, "2017-02-28")
|
||||||
|
|
||||||
|
|
||||||
|
def test_supplier_disabled(self):
|
||||||
|
make_test_records("Item")
|
||||||
|
|
||||||
|
frappe.db.set_value("Supplier", "_Test Supplier", "disabled", 1)
|
||||||
|
|
||||||
|
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
|
||||||
|
|
||||||
|
po = create_purchase_order(do_not_save=True)
|
||||||
|
|
||||||
|
self.assertRaises(CustomerDisabled, po.save)
|
||||||
|
|
||||||
|
frappe.db.set_value("Supplier", "_Test Supplier", "disabled", 0)
|
||||||
|
|
||||||
|
po.save()
|
||||||
|
@ -10,8 +10,8 @@ from erpnext.accounts.utils import get_fiscal_year, validate_fiscal_year, get_ac
|
|||||||
from erpnext.utilities.transaction_base import TransactionBase
|
from erpnext.utilities.transaction_base import TransactionBase
|
||||||
from erpnext.controllers.recurring_document import convert_to_recurring, validate_recurring_document
|
from erpnext.controllers.recurring_document import convert_to_recurring, validate_recurring_document
|
||||||
from erpnext.controllers.sales_and_purchase_return import validate_return
|
from erpnext.controllers.sales_and_purchase_return import validate_return
|
||||||
from erpnext.accounts.party import get_party_account_currency
|
from erpnext.accounts.party import get_party_account_currency, validate_party_frozen_disabled
|
||||||
from erpnext.exceptions import CustomerFrozen, InvalidCurrency
|
from erpnext.exceptions import CustomerFrozen, InvalidCurrency, CustomerDisabled
|
||||||
|
|
||||||
force_item_fields = ("item_group", "barcode", "brand", "stock_uom")
|
force_item_fields = ("item_group", "barcode", "brand", "stock_uom")
|
||||||
|
|
||||||
@ -416,24 +416,23 @@ class AccountsController(TransactionBase):
|
|||||||
return self._abbr
|
return self._abbr
|
||||||
|
|
||||||
def validate_party(self):
|
def validate_party(self):
|
||||||
frozen_accounts_modifier = frappe.db.get_value( 'Accounts Settings', None,'frozen_accounts_modifier')
|
|
||||||
if frozen_accounts_modifier in frappe.get_roles():
|
|
||||||
return
|
|
||||||
|
|
||||||
party_type, party = self.get_party()
|
party_type, party = self.get_party()
|
||||||
|
validate_party_frozen_disabled(party, party_type)
|
||||||
if party_type:
|
|
||||||
if frappe.db.get_value(party_type, party, "is_frozen"):
|
|
||||||
frappe.throw("{0} {1} is frozen".format(party_type, party), CustomerFrozen)
|
|
||||||
|
|
||||||
def get_party(self):
|
def get_party(self):
|
||||||
party_type = None
|
party_type = None
|
||||||
if self.meta.get_field("customer"):
|
if self.doctype in ("Opportunity", "Quotation", "Sales Order", "Delivery Note", "Sales Invoice"):
|
||||||
party_type = 'Customer'
|
party_type = 'Customer'
|
||||||
|
|
||||||
elif self.meta.get_field("supplier"):
|
elif self.doctype in ("Supplier Quotation", "Purchase Order", "Purchase Receipt", "Purchase Invoice"):
|
||||||
party_type = 'Supplier'
|
party_type = 'Supplier'
|
||||||
|
|
||||||
|
elif self.meta.get_field("customer"):
|
||||||
|
party_type = "Customer"
|
||||||
|
|
||||||
|
elif self.meta.get_field("supplier"):
|
||||||
|
party_type = "Supplier"
|
||||||
|
|
||||||
party = self.get(party_type.lower()) if party_type else None
|
party = self.get(party_type.lower()) if party_type else None
|
||||||
|
|
||||||
return party_type, party
|
return party_type, party
|
||||||
@ -451,7 +450,9 @@ class AccountsController(TransactionBase):
|
|||||||
frappe.throw(_("Accounting Entry for {0}: {1} can only be made in currency: {2}")
|
frappe.throw(_("Accounting Entry for {0}: {1} can only be made in currency: {2}")
|
||||||
.format(party_type, party, party_account_currency), InvalidCurrency)
|
.format(party_type, party, party_account_currency), InvalidCurrency)
|
||||||
|
|
||||||
# Note: not validating with gle account because we don't have the account at quotation / sales order level and we shouldn't stop someone from creating a sales invoice if sales order is already created
|
# Note: not validating with gle account because we don't have the account
|
||||||
|
# at quotation / sales order level and we shouldn't stop someone
|
||||||
|
# from creating a sales invoice if sales order is already created
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_tax_rate(account_head):
|
def get_tax_rate(account_head):
|
||||||
|
@ -89,7 +89,7 @@ def customer_query(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
return frappe.db.sql("""select {fields} from `tabCustomer`
|
return frappe.db.sql("""select {fields} from `tabCustomer`
|
||||||
where docstatus < 2
|
where docstatus < 2
|
||||||
and ({key} like %(txt)s
|
and ({key} like %(txt)s
|
||||||
or customer_name like %(txt)s)
|
or customer_name like %(txt)s) and disabled=0
|
||||||
{mcond}
|
{mcond}
|
||||||
order by
|
order by
|
||||||
if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999),
|
if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999),
|
||||||
@ -118,7 +118,7 @@ def supplier_query(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
return frappe.db.sql("""select {field} from `tabSupplier`
|
return frappe.db.sql("""select {field} from `tabSupplier`
|
||||||
where docstatus < 2
|
where docstatus < 2
|
||||||
and ({key} like %(txt)s
|
and ({key} like %(txt)s
|
||||||
or supplier_name like %(txt)s)
|
or supplier_name like %(txt)s) and disabled=0
|
||||||
{mcond}
|
{mcond}
|
||||||
order by
|
order by
|
||||||
if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999),
|
if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999),
|
||||||
@ -216,12 +216,8 @@ def get_delivery_notes_to_be_billed(doctype, txt, searchfield, start, page_len,
|
|||||||
return frappe.db.sql("""select `tabDelivery Note`.name, `tabDelivery Note`.customer_name
|
return frappe.db.sql("""select `tabDelivery Note`.name, `tabDelivery Note`.customer_name
|
||||||
from `tabDelivery Note`
|
from `tabDelivery Note`
|
||||||
where `tabDelivery Note`.`%(key)s` like %(txt)s and
|
where `tabDelivery Note`.`%(key)s` like %(txt)s and
|
||||||
`tabDelivery Note`.docstatus = 1 and status not in ("Stopped", "Closed") %(fcond)s and
|
`tabDelivery Note`.docstatus = 1 and status not in ("Stopped", "Closed") %(fcond)s
|
||||||
(ifnull((select sum(qty) from `tabDelivery Note Item` where
|
and `tabDelivery Note`.per_billed < 100
|
||||||
`tabDelivery Note Item`.parent=`tabDelivery Note`.name), 0) >
|
|
||||||
ifnull((select sum(qty) from `tabSales Invoice Item` where
|
|
||||||
`tabSales Invoice Item`.docstatus = 1 and
|
|
||||||
`tabSales Invoice Item`.delivery_note=`tabDelivery Note`.name), 0))
|
|
||||||
%(mcond)s order by `tabDelivery Note`.`%(key)s` asc
|
%(mcond)s order by `tabDelivery Note`.`%(key)s` asc
|
||||||
limit %(start)s, %(page_len)s""" % {
|
limit %(start)s, %(page_len)s""" % {
|
||||||
"key": searchfield,
|
"key": searchfield,
|
||||||
|
@ -5,3 +5,4 @@ import frappe
|
|||||||
class CustomerFrozen(frappe.ValidationError): pass
|
class CustomerFrozen(frappe.ValidationError): pass
|
||||||
class InvalidAccountCurrency(frappe.ValidationError): pass
|
class InvalidAccountCurrency(frappe.ValidationError): pass
|
||||||
class InvalidCurrency(frappe.ValidationError): pass
|
class InvalidCurrency(frappe.ValidationError): pass
|
||||||
|
class CustomerDisabled(frappe.ValidationError):pass
|
||||||
|
@ -241,13 +241,14 @@
|
|||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"fieldname": "is_frozen",
|
"default": "0",
|
||||||
|
"fieldname": "disabled",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"label": "Is Frozen",
|
"label": "Disabled",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
@ -591,7 +592,7 @@
|
|||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"label": "Customer Details",
|
"label": "More Information",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"oldfieldtype": "Section Break",
|
"oldfieldtype": "Section Break",
|
||||||
@ -655,6 +656,30 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"fieldname": "is_frozen",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "Is Frozen",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
@ -794,7 +819,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2016-01-06 02:36:04.820353",
|
"modified": "2016-01-25 06:56:05.103168",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Customer",
|
"name": "Customer",
|
||||||
@ -984,5 +1009,6 @@
|
|||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"read_only_onload": 0,
|
"read_only_onload": 0,
|
||||||
"search_fields": "customer_name,customer_group,territory",
|
"search_fields": "customer_name,customer_group,territory",
|
||||||
|
"sort_order": "ASC",
|
||||||
"title_field": "customer_name"
|
"title_field": "customer_name"
|
||||||
}
|
}
|
@ -7,7 +7,7 @@ import frappe
|
|||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from frappe.test_runner import make_test_records
|
from frappe.test_runner import make_test_records
|
||||||
from erpnext.exceptions import CustomerFrozen
|
from erpnext.exceptions import CustomerFrozen, CustomerDisabled
|
||||||
|
|
||||||
test_ignore = ["Price List"]
|
test_ignore = ["Price List"]
|
||||||
|
|
||||||
@ -68,7 +68,6 @@ class TestCustomer(unittest.TestCase):
|
|||||||
frappe.rename_doc("Customer", "_Test Customer 1 Renamed", "_Test Customer 1")
|
frappe.rename_doc("Customer", "_Test Customer 1 Renamed", "_Test Customer 1")
|
||||||
|
|
||||||
def test_freezed_customer(self):
|
def test_freezed_customer(self):
|
||||||
make_test_records("Customer")
|
|
||||||
make_test_records("Item")
|
make_test_records("Item")
|
||||||
|
|
||||||
frappe.db.set_value("Customer", "_Test Customer", "is_frozen", 1)
|
frappe.db.set_value("Customer", "_Test Customer", "is_frozen", 1)
|
||||||
@ -83,7 +82,24 @@ class TestCustomer(unittest.TestCase):
|
|||||||
|
|
||||||
so.save()
|
so.save()
|
||||||
|
|
||||||
|
def test_disabled_customer(self):
|
||||||
|
make_test_records("Item")
|
||||||
|
|
||||||
|
frappe.db.set_value("Customer", "_Test Customer", "disabled", 1)
|
||||||
|
|
||||||
|
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
|
||||||
|
|
||||||
|
so = make_sales_order(do_not_save=True)
|
||||||
|
|
||||||
|
self.assertRaises(CustomerDisabled, so.save)
|
||||||
|
|
||||||
|
frappe.db.set_value("Customer", "_Test Customer", "disabled", 0)
|
||||||
|
|
||||||
|
so.save()
|
||||||
|
|
||||||
def test_duplicate_customer(self):
|
def test_duplicate_customer(self):
|
||||||
|
frappe.db.sql("delete from `tabCustomer` where customer_name='_Test Customer 1'")
|
||||||
|
|
||||||
if not frappe.db.get_value("Customer", "_Test Customer 1"):
|
if not frappe.db.get_value("Customer", "_Test Customer 1"):
|
||||||
test_customer_1 = frappe.get_doc({
|
test_customer_1 = frappe.get_doc({
|
||||||
"customer_group": "_Test Customer Group",
|
"customer_group": "_Test Customer Group",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user