[enhancement] add status in customer, supplier

This commit is contained in:
Rushabh Mehta 2016-04-08 17:20:50 +05:30
parent 203cc962f5
commit f16f9c569b
12 changed files with 239 additions and 28 deletions

View File

@ -41,7 +41,7 @@ class FiscalYear(Document):
def on_update(self):
check_duplicate_fiscal_year(self)
def validate_overlap(self):
existing_fiscal_years = frappe.db.sql("""select name from `tabFiscal Year`
where (
@ -60,18 +60,18 @@ class FiscalYear(Document):
for existing in existing_fiscal_years:
company_for_existing = frappe.db.sql_list("""select company from `tabFiscal Year Company`
where parent=%s""", existing.name)
overlap = False
if not self.get("companies") or not company_for_existing:
overlap = True
for d in self.get("companies"):
if d.company in company_for_existing:
overlap = True
if overlap:
frappe.throw(_("Year start date or end date is overlapping with {0}. To avoid please set company")
.format(existing.name))
.format(existing.name), frappe.NameError)
@frappe.whitelist()
def check_duplicate_fiscal_year(doc):

View File

@ -0,0 +1,72 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
from frappe.utils import evaluate_filters
from erpnext.startup.notifications import get_notification_config
status_depends_on = {
'Customer': ('Opportunity', 'Quotation', 'Sales Order', 'Sales Invoice', 'Project', 'Issue'),
'Supplier': ('Supplier Quotation', 'Purchase Order', 'Purchase Invoice')
}
default_status = {
'Customer': 'Active',
'Supplier': None
}
def notify_status(doc, method):
'''Notify status to customer, supplier'''
party_type = None
for key, doctypes in status_depends_on.iteritems():
if doc.doctype in doctypes:
party_type = key
break
if not party_type:
return
party = frappe.get_doc(party_type, doc.get(party_type.lower()))
config = get_notification_config().get('for_doctype').get(doc.doctype)
status = None
if config:
if evaluate_filters(doc, config):
# filters match, passed document is open
status = 'Open'
if status=='Open':
if party.status != 'Open':
# party not open, make it open
party.status = 'Open'
party.save(ignore_permissions=True)
else:
if party.status == 'Open':
# may be open elsewhere, check
# default status
party.status = status
update_status(party, )
def update_status(doc):
'''Set status as open if there is any open notification'''
config = get_notification_config()
original_status = doc.status
doc.status = default_status[doc.doctype]
for doctype in status_depends_on[doc.doctype]:
filters = config.get('for_doctype', {}).get(doctype) or {}
filters[doc.doctype.lower()] = doc.name
if filters:
open_count = frappe.get_all(doctype, fields='count(*) as count', filters=filters)
if open_count[0].count > 0:
doc.status = 'Open'
break
if doc.status != original_status:
doc.db_set('status', doc.status)

View File

@ -114,6 +114,32 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "status",
"fieldtype": "Select",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Status",
"length": 0,
"no_copy": 0,
"options": "\nOpen",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
@ -658,7 +684,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2016-04-06 05:39:47.329568",
"modified": "2016-04-08 07:43:07.541419",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier",

View File

@ -1,3 +1,8 @@
frappe.listview_settings['Supplier'] = {
add_fields: ["supplier_name", "supplier_type"]
add_fields: ["supplier_name", "supplier_type", 'status'],
get_indicator: function(doc) {
if(doc.status==="Open") {
return [doc.status, "red", "status,=," + doc.status];
}
}
};

View File

@ -127,15 +127,18 @@ doc_events = {
"on_update": "erpnext.hr.doctype.employee.employee.update_user_permissions",
"on_update": "erpnext.utilities.doctype.contact.contact.update_contact"
},
"Sales Taxes and Charges Template": {
"on_update": "erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings.validate_cart_settings"
},
"Price List": {
("Sales Taxes and Charges Template", 'Price List'): {
"on_update": "erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings.validate_cart_settings"
},
"Address": {
"validate": "erpnext.shopping_cart.cart.set_customer_in_address"
}
},
# bubble transaction notification on master
('Opportunity', 'Quotation', 'Sales Order', 'Sales Invoice', 'Supplier Quotation',
'Purchase Order', 'Purchase Invoice', 'Project', 'Issue'): {
'on_update': 'erpnext.accounts.party_status.notify_status'
}
}
scheduler_events = {

View File

@ -260,3 +260,4 @@ erpnext.patches.v6_24.map_customer_address_to_shipping_address_on_po
erpnext.patches.v6_27.fix_recurring_order_status
erpnext.patches.v6_20x.remove_customer_supplier_roles
erpnext.patches.v6_24.rename_item_field
erpnext.patches.v7_0.update_party_status

View File

View File

@ -0,0 +1,7 @@
import frappe
def execute():
for doctype in ('Customer', 'Supplier'):
for doc in frappe.get_all(doctype):
doc = frappe.get_doc(doctype, doc.name)
doc.update_status()

View File

@ -166,6 +166,33 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"default": "Active",
"fieldname": "status",
"fieldtype": "Select",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Status",
"length": 0,
"no_copy": 0,
"options": "Active\nDormant\nOpen",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"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,
"bold": 0,
@ -927,7 +954,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2016-04-07 01:25:25.676480",
"modified": "2016-04-08 07:43:01.381976",
"modified_by": "Administrator",
"module": "Selling",
"name": "Customer",

View File

@ -1,3 +1,12 @@
frappe.listview_settings['Customer'] = {
add_fields: ["customer_name", "territory", "customer_group", "customer_type"]
add_fields: ["customer_name", "territory", "customer_group", "customer_type", 'status'],
get_indicator: function(doc) {
color = {
'Open': 'red',
'Active': 'green',
'Dormant', 'dardgrey'
}
return [__(doc.status), color[doc.status], "status,=," + doc.status];
}
};

View File

@ -11,6 +11,8 @@ from erpnext.exceptions import PartyFrozen, PartyDisabled
test_ignore = ["Price List"]
test_dependencies = ['Quotation']
test_records = frappe.get_test_records('Customer')
class TestCustomer(unittest.TestCase):
@ -99,24 +101,65 @@ class TestCustomer(unittest.TestCase):
frappe.db.sql("delete from `tabCustomer` where customer_name='_Test Customer 1'")
if not frappe.db.get_value("Customer", "_Test Customer 1"):
test_customer_1 = frappe.get_doc({
"customer_group": "_Test Customer Group",
"customer_name": "_Test Customer 1",
"customer_type": "Individual",
"doctype": "Customer",
"territory": "_Test Territory"
}).insert(ignore_permissions=True)
test_customer_1 = frappe.get_doc(
get_customer_dict('_Test Customer 1')).insert(ignore_permissions=True)
else:
test_customer_1 = frappe.get_doc("Customer", "_Test Customer 1")
duplicate_customer = frappe.get_doc({
"customer_group": "_Test Customer Group",
"customer_name": "_Test Customer 1",
"customer_type": "Individual",
"doctype": "Customer",
"territory": "_Test Territory"
}).insert(ignore_permissions=True)
duplicate_customer = frappe.get_doc(
get_customer_dict('_Test Customer 1')).insert(ignore_permissions=True)
self.assertEquals("_Test Customer 1", test_customer_1.name)
self.assertEquals("_Test Customer 1 - 1", duplicate_customer.name)
self.assertEquals(test_customer_1.customer_name, duplicate_customer.customer_name)
def test_party_status_open(self):
from erpnext.selling.doctype.quotation.test_quotation import get_quotation_dict
customer = frappe.get_doc(get_customer_dict('Party Status Test')).insert()
self.assertEquals(frappe.db.get_value('Customer', customer.name, 'status'), 'Active')
quotation = frappe.get_doc(get_quotation_dict(customer=customer.name)).insert()
self.assertEquals(frappe.db.get_value('Customer', customer.name, 'status'), 'Open')
quotation.submit()
self.assertEquals(frappe.db.get_value('Customer', customer.name, 'status'), 'Active')
quotation.cancel()
quotation.delete()
customer.delete()
def test_party_status_close(self):
from erpnext.selling.doctype.quotation.test_quotation import get_quotation_dict
customer = frappe.get_doc(get_customer_dict('Party Status Test')).insert()
self.assertEquals(frappe.db.get_value('Customer', customer.name, 'status'), 'Active')
# open quotation
quotation = frappe.get_doc(get_quotation_dict(customer=customer.name)).insert()
self.assertEquals(frappe.db.get_value('Customer', customer.name, 'status'), 'Open')
# close quotation (submit)
quotation.submit()
quotation1 = frappe.get_doc(get_quotation_dict(customer=customer.name)).insert()
# still open
self.assertEquals(frappe.db.get_value('Customer', customer.name, 'status'), 'Open')
quotation.cancel()
quotation.delete()
quotation1.delete()
customer.delete()
def get_customer_dict(customer_name):
return {
"customer_group": "_Test Customer Group",
"customer_name": customer_name,
"customer_type": "Individual",
"doctype": "Customer",
"territory": "_Test Territory"
}

View File

@ -69,3 +69,21 @@ class TestQuotation(unittest.TestCase):
si.save()
test_records = frappe.get_test_records('Quotation')
def get_quotation_dict(customer=None, item_code=None):
if not customer:
customer = '_Test Customer'
if not item_code:
item_code = '_Test Item'
return {
'doctype': 'Quotation',
'customer': customer,
'items': [
{
'item_code': item_code,
'qty': 1,
'rate': 100
}
]
}