feat: CRM Settings (#27788)
* feat: crm settings * feat: CRM Settings * feat: lead and opprtunity section * feat: added CRM Settings in ERPNext Settings workspace * fix: review chnages * added patch * fix: linter issues * fix: linter issues * fix: linter issues * fix: removed crm settings from selling module * fix: raw query to frappe.qb * fix: removed hardcoded value * fix: linter issue * fix: simplify CRM Settings migration patch Co-authored-by: Anupam Kumar <anupam@Anupams-MacBook-Air.local> Co-authored-by: Rucha Mahabal <ruchamahabal2@gmail.com>
This commit is contained in:
parent
c56a450474
commit
3928a402d4
0
erpnext/crm/doctype/crm_settings/__init__.py
Normal file
0
erpnext/crm/doctype/crm_settings/__init__.py
Normal file
8
erpnext/crm/doctype/crm_settings/crm_settings.js
Normal file
8
erpnext/crm/doctype/crm_settings/crm_settings.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
|
||||||
|
frappe.ui.form.on('CRM Settings', {
|
||||||
|
// refresh: function(frm) {
|
||||||
|
|
||||||
|
// }
|
||||||
|
});
|
||||||
114
erpnext/crm/doctype/crm_settings/crm_settings.json
Normal file
114
erpnext/crm/doctype/crm_settings/crm_settings.json
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
{
|
||||||
|
"actions": [],
|
||||||
|
"creation": "2021-09-09 17:03:22.754446",
|
||||||
|
"description": "Settings for Selling Module",
|
||||||
|
"doctype": "DocType",
|
||||||
|
"document_type": "Other",
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"section_break_5",
|
||||||
|
"campaign_naming_by",
|
||||||
|
"allow_lead_duplication_based_on_emails",
|
||||||
|
"column_break_4",
|
||||||
|
"create_event_on_next_contact_date",
|
||||||
|
"auto_creation_of_contact",
|
||||||
|
"opportunity_section",
|
||||||
|
"close_opportunity_after_days",
|
||||||
|
"column_break_9",
|
||||||
|
"create_event_on_next_contact_date_opportunity",
|
||||||
|
"quotation_section",
|
||||||
|
"default_valid_till"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldname": "campaign_naming_by",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Campaign Naming By",
|
||||||
|
"options": "Campaign Name\nNaming Series"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_9",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "default_valid_till",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": "Default Quotation Validity Days"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "section_break_5",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Lead"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "allow_lead_duplication_based_on_emails",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Allow Lead Duplication based on Emails"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "1",
|
||||||
|
"fieldname": "auto_creation_of_contact",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Auto Creation of Contact"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "1",
|
||||||
|
"fieldname": "create_event_on_next_contact_date",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Create Event on Next Contact Date"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "opportunity_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Opportunity"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "15",
|
||||||
|
"description": "Auto close Opportunity Replied after the no. of days mentioned above",
|
||||||
|
"fieldname": "close_opportunity_after_days",
|
||||||
|
"fieldtype": "Int",
|
||||||
|
"label": "Close Replied Opportunity After Days"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "1",
|
||||||
|
"fieldname": "create_event_on_next_contact_date_opportunity",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Create Event on Next Contact Date"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_4",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "quotation_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Quotation"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"icon": "fa fa-cog",
|
||||||
|
"index_web_pages_for_search": 1,
|
||||||
|
"issingle": 1,
|
||||||
|
"links": [],
|
||||||
|
"migration_hash": "3ae78b12dd1c64d551736c6e82092f90",
|
||||||
|
"modified": "2021-11-03 09:00:36.883496",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "CRM",
|
||||||
|
"name": "CRM Settings",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"create": 1,
|
||||||
|
"email": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"role": "System Manager",
|
||||||
|
"share": 1,
|
||||||
|
"write": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC",
|
||||||
|
"track_changes": 1
|
||||||
|
}
|
||||||
9
erpnext/crm/doctype/crm_settings/crm_settings.py
Normal file
9
erpnext/crm/doctype/crm_settings/crm_settings.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
# import frappe
|
||||||
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
|
||||||
|
class CRMSettings(Document):
|
||||||
|
pass
|
||||||
9
erpnext/crm/doctype/crm_settings/test_crm_settings.py
Normal file
9
erpnext/crm/doctype/crm_settings/test_crm_settings.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# See license.txt
|
||||||
|
|
||||||
|
# import frappe
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
|
||||||
|
class TestCRMSettings(unittest.TestCase):
|
||||||
|
pass
|
||||||
@ -11,6 +11,7 @@ from frappe.utils import (
|
|||||||
cint,
|
cint,
|
||||||
comma_and,
|
comma_and,
|
||||||
cstr,
|
cstr,
|
||||||
|
get_link_to_form,
|
||||||
getdate,
|
getdate,
|
||||||
has_gravatar,
|
has_gravatar,
|
||||||
nowdate,
|
nowdate,
|
||||||
@ -91,13 +92,14 @@ class Lead(SellingController):
|
|||||||
self.contact_doc.save()
|
self.contact_doc.save()
|
||||||
|
|
||||||
def add_calendar_event(self, opts=None, force=False):
|
def add_calendar_event(self, opts=None, force=False):
|
||||||
super(Lead, self).add_calendar_event({
|
if frappe.db.get_single_value('CRM Settings', 'create_event_on_next_contact_date'):
|
||||||
"owner": self.lead_owner,
|
super(Lead, self).add_calendar_event({
|
||||||
"starts_on": self.contact_date,
|
"owner": self.lead_owner,
|
||||||
"ends_on": self.ends_on or "",
|
"starts_on": self.contact_date,
|
||||||
"subject": ('Contact ' + cstr(self.lead_name)),
|
"ends_on": self.ends_on or "",
|
||||||
"description": ('Contact ' + cstr(self.lead_name)) + (self.contact_by and ('. By : ' + cstr(self.contact_by)) or '')
|
"subject": ('Contact ' + cstr(self.lead_name)),
|
||||||
}, force)
|
"description": ('Contact ' + cstr(self.lead_name)) + (self.contact_by and ('. By : ' + cstr(self.contact_by)) or '')
|
||||||
|
}, force)
|
||||||
|
|
||||||
def update_prospects(self):
|
def update_prospects(self):
|
||||||
prospects = frappe.get_all('Prospect Lead', filters={'lead': self.name}, fields=['parent'])
|
prospects = frappe.get_all('Prospect Lead', filters={'lead': self.name}, fields=['parent'])
|
||||||
@ -108,12 +110,13 @@ class Lead(SellingController):
|
|||||||
def check_email_id_is_unique(self):
|
def check_email_id_is_unique(self):
|
||||||
if self.email_id:
|
if self.email_id:
|
||||||
# validate email is unique
|
# validate email is unique
|
||||||
duplicate_leads = frappe.get_all("Lead", filters={"email_id": self.email_id, "name": ["!=", self.name]})
|
if not frappe.db.get_single_value('CRM Settings', 'allow_lead_duplication_based_on_emails'):
|
||||||
duplicate_leads = [lead.name for lead in duplicate_leads]
|
duplicate_leads = frappe.get_all("Lead", filters={"email_id": self.email_id, "name": ["!=", self.name]})
|
||||||
|
duplicate_leads = [frappe.bold(get_link_to_form('Lead', lead.name)) for lead in duplicate_leads]
|
||||||
|
|
||||||
if duplicate_leads:
|
if duplicate_leads:
|
||||||
frappe.throw(_("Email Address must be unique, already exists for {0}")
|
frappe.throw(_("Email Address must be unique, already exists for {0}")
|
||||||
.format(comma_and(duplicate_leads)), frappe.DuplicateEntryError)
|
.format(comma_and(duplicate_leads)), frappe.DuplicateEntryError)
|
||||||
|
|
||||||
def on_trash(self):
|
def on_trash(self):
|
||||||
frappe.db.sql("""update `tabIssue` set lead='' where lead=%s""", self.name)
|
frappe.db.sql("""update `tabIssue` set lead='' where lead=%s""", self.name)
|
||||||
@ -172,41 +175,42 @@ class Lead(SellingController):
|
|||||||
self.title = self.company_name or self.lead_name
|
self.title = self.company_name or self.lead_name
|
||||||
|
|
||||||
def create_contact(self):
|
def create_contact(self):
|
||||||
if not self.lead_name:
|
if frappe.db.get_single_value('CRM Settings', 'auto_creation_of_contact'):
|
||||||
self.set_full_name()
|
if not self.lead_name:
|
||||||
self.set_lead_name()
|
self.set_full_name()
|
||||||
|
self.set_lead_name()
|
||||||
|
|
||||||
contact = frappe.new_doc("Contact")
|
contact = frappe.new_doc("Contact")
|
||||||
contact.update({
|
contact.update({
|
||||||
"first_name": self.first_name or self.lead_name,
|
"first_name": self.first_name or self.lead_name,
|
||||||
"last_name": self.last_name,
|
"last_name": self.last_name,
|
||||||
"salutation": self.salutation,
|
"salutation": self.salutation,
|
||||||
"gender": self.gender,
|
"gender": self.gender,
|
||||||
"designation": self.designation,
|
"designation": self.designation,
|
||||||
"company_name": self.company_name,
|
"company_name": self.company_name,
|
||||||
})
|
|
||||||
|
|
||||||
if self.email_id:
|
|
||||||
contact.append("email_ids", {
|
|
||||||
"email_id": self.email_id,
|
|
||||||
"is_primary": 1
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if self.phone:
|
if self.email_id:
|
||||||
contact.append("phone_nos", {
|
contact.append("email_ids", {
|
||||||
"phone": self.phone,
|
"email_id": self.email_id,
|
||||||
"is_primary_phone": 1
|
"is_primary": 1
|
||||||
})
|
})
|
||||||
|
|
||||||
if self.mobile_no:
|
if self.phone:
|
||||||
contact.append("phone_nos", {
|
contact.append("phone_nos", {
|
||||||
"phone": self.mobile_no,
|
"phone": self.phone,
|
||||||
"is_primary_mobile_no":1
|
"is_primary_phone": 1
|
||||||
})
|
})
|
||||||
|
|
||||||
contact.insert(ignore_permissions=True)
|
if self.mobile_no:
|
||||||
|
contact.append("phone_nos", {
|
||||||
|
"phone": self.mobile_no,
|
||||||
|
"is_primary_mobile_no":1
|
||||||
|
})
|
||||||
|
|
||||||
return contact
|
contact.insert(ignore_permissions=True)
|
||||||
|
|
||||||
|
return contact
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_customer(source_name, target_doc=None):
|
def make_customer(source_name, target_doc=None):
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import frappe
|
|||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.email.inbox import link_communication_to_document
|
from frappe.email.inbox import link_communication_to_document
|
||||||
from frappe.model.mapper import get_mapped_doc
|
from frappe.model.mapper import get_mapped_doc
|
||||||
|
from frappe.query_builder import DocType
|
||||||
from frappe.utils import cint, cstr, flt, get_fullname
|
from frappe.utils import cint, cstr, flt, get_fullname
|
||||||
|
|
||||||
from erpnext.setup.utils import get_exchange_rate
|
from erpnext.setup.utils import get_exchange_rate
|
||||||
@ -28,7 +29,6 @@ class Opportunity(TransactionBase):
|
|||||||
})
|
})
|
||||||
|
|
||||||
self.make_new_lead_if_required()
|
self.make_new_lead_if_required()
|
||||||
|
|
||||||
self.validate_item_details()
|
self.validate_item_details()
|
||||||
self.validate_uom_is_integer("uom", "qty")
|
self.validate_uom_is_integer("uom", "qty")
|
||||||
self.validate_cust_name()
|
self.validate_cust_name()
|
||||||
@ -70,21 +70,21 @@ class Opportunity(TransactionBase):
|
|||||||
"""Set lead against new opportunity"""
|
"""Set lead against new opportunity"""
|
||||||
if (not self.get("party_name")) and self.contact_email:
|
if (not self.get("party_name")) and self.contact_email:
|
||||||
# check if customer is already created agains the self.contact_email
|
# check if customer is already created agains the self.contact_email
|
||||||
customer = frappe.db.sql("""select
|
dynamic_link, contact = DocType("Dynamic Link"), DocType("Contact")
|
||||||
distinct `tabDynamic Link`.link_name as customer
|
customer = frappe.qb.from_(
|
||||||
from
|
dynamic_link
|
||||||
`tabContact`,
|
).join(
|
||||||
`tabDynamic Link`
|
contact
|
||||||
where `tabContact`.email_id='{0}'
|
).on(
|
||||||
and
|
(contact.name == dynamic_link.parent)
|
||||||
`tabContact`.name=`tabDynamic Link`.parent
|
& (dynamic_link.link_doctype == "Customer")
|
||||||
and
|
& (contact.email_id == self.contact_email)
|
||||||
ifnull(`tabDynamic Link`.link_name, '')<>''
|
).select(
|
||||||
and
|
dynamic_link.link_name
|
||||||
`tabDynamic Link`.link_doctype='Customer'
|
).distinct().run(as_dict=True)
|
||||||
""".format(self.contact_email), as_dict=True)
|
|
||||||
if customer and customer[0].customer:
|
if customer and customer[0].link_name:
|
||||||
self.party_name = customer[0].customer
|
self.party_name = customer[0].link_name
|
||||||
self.opportunity_from = "Customer"
|
self.opportunity_from = "Customer"
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -191,30 +191,31 @@ class Opportunity(TransactionBase):
|
|||||||
self.add_calendar_event()
|
self.add_calendar_event()
|
||||||
|
|
||||||
def add_calendar_event(self, opts=None, force=False):
|
def add_calendar_event(self, opts=None, force=False):
|
||||||
if not opts:
|
if frappe.db.get_single_value('CRM Settings', 'create_event_on_next_contact_date_opportunity'):
|
||||||
opts = frappe._dict()
|
if not opts:
|
||||||
|
opts = frappe._dict()
|
||||||
|
|
||||||
opts.description = ""
|
opts.description = ""
|
||||||
opts.contact_date = self.contact_date
|
opts.contact_date = self.contact_date
|
||||||
|
|
||||||
if self.party_name and self.opportunity_from == 'Customer':
|
if self.party_name and self.opportunity_from == 'Customer':
|
||||||
if self.contact_person:
|
if self.contact_person:
|
||||||
opts.description = 'Contact '+cstr(self.contact_person)
|
opts.description = 'Contact '+cstr(self.contact_person)
|
||||||
else:
|
else:
|
||||||
opts.description = 'Contact customer '+cstr(self.party_name)
|
opts.description = 'Contact customer '+cstr(self.party_name)
|
||||||
elif self.party_name and self.opportunity_from == 'Lead':
|
elif self.party_name and self.opportunity_from == 'Lead':
|
||||||
if self.contact_display:
|
if self.contact_display:
|
||||||
opts.description = 'Contact '+cstr(self.contact_display)
|
opts.description = 'Contact '+cstr(self.contact_display)
|
||||||
else:
|
else:
|
||||||
opts.description = 'Contact lead '+cstr(self.party_name)
|
opts.description = 'Contact lead '+cstr(self.party_name)
|
||||||
|
|
||||||
opts.subject = opts.description
|
opts.subject = opts.description
|
||||||
opts.description += '. By : ' + cstr(self.contact_by)
|
opts.description += '. By : ' + cstr(self.contact_by)
|
||||||
|
|
||||||
if self.to_discuss:
|
if self.to_discuss:
|
||||||
opts.description += ' To Discuss : ' + cstr(self.to_discuss)
|
opts.description += ' To Discuss : ' + cstr(self.to_discuss)
|
||||||
|
|
||||||
super(Opportunity, self).add_calendar_event(opts, force)
|
super(Opportunity, self).add_calendar_event(opts, force)
|
||||||
|
|
||||||
def validate_item_details(self):
|
def validate_item_details(self):
|
||||||
if not self.get('items'):
|
if not self.get('items'):
|
||||||
@ -363,7 +364,7 @@ def set_multiple_status(names, status):
|
|||||||
|
|
||||||
def auto_close_opportunity():
|
def auto_close_opportunity():
|
||||||
""" auto close the `Replied` Opportunities after 7 days """
|
""" auto close the `Replied` Opportunities after 7 days """
|
||||||
auto_close_after_days = frappe.db.get_single_value("Selling Settings", "close_opportunity_after_days") or 15
|
auto_close_after_days = frappe.db.get_single_value("CRM Settings", "close_opportunity_after_days") or 15
|
||||||
|
|
||||||
opportunities = frappe.db.sql(""" select name from tabOpportunity where status='Replied' and
|
opportunities = frappe.db.sql(""" select name from tabOpportunity where status='Replied' and
|
||||||
modified<DATE_SUB(CURDATE(), INTERVAL %s DAY) """, (auto_close_after_days), as_dict=True)
|
modified<DATE_SUB(CURDATE(), INTERVAL %s DAY) """, (auto_close_after_days), as_dict=True)
|
||||||
|
|||||||
@ -313,3 +313,4 @@ erpnext.patches.v13_0.update_category_in_ltds_certificate
|
|||||||
erpnext.patches.v13_0.create_pan_field_for_india #2
|
erpnext.patches.v13_0.create_pan_field_for_india #2
|
||||||
erpnext.patches.v14_0.delete_hub_doctypes
|
erpnext.patches.v14_0.delete_hub_doctypes
|
||||||
erpnext.patches.v13_0.create_ksa_vat_custom_fields
|
erpnext.patches.v13_0.create_ksa_vat_custom_fields
|
||||||
|
erpnext.patches.v14_0.migrate_crm_settings
|
||||||
|
|||||||
16
erpnext/patches/v14_0/migrate_crm_settings.py
Normal file
16
erpnext/patches/v14_0/migrate_crm_settings.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
settings = frappe.db.get_value('Selling Settings', 'Selling Settings', [
|
||||||
|
'campaign_naming_by',
|
||||||
|
'close_opportunity_after_days',
|
||||||
|
'default_valid_till'
|
||||||
|
], as_dict=True)
|
||||||
|
|
||||||
|
frappe.reload_doc('crm', 'doctype', 'crm_settings')
|
||||||
|
frappe.db.set_value('CRM Settings', 'CRM Settings', {
|
||||||
|
'campaign_naming_by': settings.campaign_naming_by,
|
||||||
|
'close_opportunity_after_days': settings.close_opportunity_after_days,
|
||||||
|
'default_valid_till': settings.default_valid_till
|
||||||
|
})
|
||||||
@ -11,11 +11,6 @@
|
|||||||
"customer_group",
|
"customer_group",
|
||||||
"column_break_4",
|
"column_break_4",
|
||||||
"territory",
|
"territory",
|
||||||
"crm_settings_section",
|
|
||||||
"campaign_naming_by",
|
|
||||||
"default_valid_till",
|
|
||||||
"column_break_9",
|
|
||||||
"close_opportunity_after_days",
|
|
||||||
"item_price_settings_section",
|
"item_price_settings_section",
|
||||||
"selling_price_list",
|
"selling_price_list",
|
||||||
"maintain_same_rate_action",
|
"maintain_same_rate_action",
|
||||||
@ -43,13 +38,6 @@
|
|||||||
"label": "Customer Naming By",
|
"label": "Customer Naming By",
|
||||||
"options": "Customer Name\nNaming Series\nAuto Name"
|
"options": "Customer Name\nNaming Series\nAuto Name"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "campaign_naming_by",
|
|
||||||
"fieldtype": "Select",
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Campaign Naming By",
|
|
||||||
"options": "Campaign Name\nNaming Series\nAuto Name"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "customer_group",
|
"fieldname": "customer_group",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
@ -71,18 +59,6 @@
|
|||||||
"label": "Default Price List",
|
"label": "Default Price List",
|
||||||
"options": "Price List"
|
"options": "Price List"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"default": "15",
|
|
||||||
"description": "Auto close Opportunity after the no. of days mentioned above",
|
|
||||||
"fieldname": "close_opportunity_after_days",
|
|
||||||
"fieldtype": "Int",
|
|
||||||
"label": "Close Opportunity After Days"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "default_valid_till",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"label": "Default Quotation Validity Days"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "column_break_5",
|
"fieldname": "column_break_5",
|
||||||
"fieldtype": "Column Break"
|
"fieldtype": "Column Break"
|
||||||
@ -169,15 +145,6 @@
|
|||||||
"fieldname": "column_break_4",
|
"fieldname": "column_break_4",
|
||||||
"fieldtype": "Column Break"
|
"fieldtype": "Column Break"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "crm_settings_section",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"label": "CRM Settings"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "column_break_9",
|
|
||||||
"fieldtype": "Column Break"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "item_price_settings_section",
|
"fieldname": "item_price_settings_section",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
@ -204,7 +171,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-09-08 19:38:10.175989",
|
"modified": "2021-09-13 12:32:17.004404",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Selling Settings",
|
"name": "Selling Settings",
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
"idx": 0,
|
"idx": 0,
|
||||||
"label": "ERPNext Settings",
|
"label": "ERPNext Settings",
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-10-26 21:32:55.323591",
|
"modified": "2021-11-05 21:32:55.323591",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Setup",
|
"module": "Setup",
|
||||||
"name": "ERPNext Settings",
|
"name": "ERPNext Settings",
|
||||||
@ -123,6 +123,13 @@
|
|||||||
"label": "Products Settings",
|
"label": "Products Settings",
|
||||||
"link_to": "Products Settings",
|
"link_to": "Products Settings",
|
||||||
"type": "DocType"
|
"type": "DocType"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doc_view": "",
|
||||||
|
"icon": "crm",
|
||||||
|
"label": "CRM Settings",
|
||||||
|
"link_to": "CRM Settings",
|
||||||
|
"type": "DocType"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"title": "ERPNext Settings"
|
"title": "ERPNext Settings"
|
||||||
|
|||||||
@ -22,7 +22,7 @@ def boot_session(bootinfo):
|
|||||||
'customer_group')
|
'customer_group')
|
||||||
bootinfo.sysdefaults.allow_stale = cint(frappe.db.get_single_value('Accounts Settings',
|
bootinfo.sysdefaults.allow_stale = cint(frappe.db.get_single_value('Accounts Settings',
|
||||||
'allow_stale'))
|
'allow_stale'))
|
||||||
bootinfo.sysdefaults.quotation_valid_till = cint(frappe.db.get_single_value('Selling Settings',
|
bootinfo.sysdefaults.quotation_valid_till = cint(frappe.db.get_single_value('CRM Settings',
|
||||||
'default_valid_till'))
|
'default_valid_till'))
|
||||||
|
|
||||||
# if no company, show a dialog box to create a new company
|
# if no company, show a dialog box to create a new company
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user