mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-20 13:39:18 +00:00
fixed conflict
This commit is contained in:
0
erpnext/crm/__init__.py
Normal file
0
erpnext/crm/__init__.py
Normal file
0
erpnext/crm/doctype/__init__.py
Normal file
0
erpnext/crm/doctype/__init__.py
Normal file
9
erpnext/crm/doctype/lead/.py
Normal file
9
erpnext/crm/doctype/lead/.py
Normal file
@@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class Lead(Document):
|
||||
pass
|
||||
0
erpnext/crm/doctype/lead/__init__.py
Normal file
0
erpnext/crm/doctype/lead/__init__.py
Normal file
63
erpnext/crm/doctype/lead/lead.js
Normal file
63
erpnext/crm/doctype/lead/lead.js
Normal file
@@ -0,0 +1,63 @@
|
||||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.provide("erpnext");
|
||||
cur_frm.email_field = "email_id";
|
||||
|
||||
erpnext.LeadController = frappe.ui.form.Controller.extend({
|
||||
setup: function() {
|
||||
this.frm.fields_dict.customer.get_query = function(doc, cdt, cdn) {
|
||||
return { query: "erpnext.controllers.queries.customer_query" } }
|
||||
},
|
||||
|
||||
onload: function() {
|
||||
if(cur_frm.fields_dict.lead_owner.df.options.match(/^User/)) {
|
||||
cur_frm.fields_dict.lead_owner.get_query = function(doc, cdt, cdn) {
|
||||
return { query:"frappe.core.doctype.user.user.user_query" } }
|
||||
}
|
||||
|
||||
if(cur_frm.fields_dict.contact_by.df.options.match(/^User/)) {
|
||||
cur_frm.fields_dict.contact_by.get_query = function(doc, cdt, cdn) {
|
||||
return { query:"frappe.core.doctype.user.user.user_query" } }
|
||||
}
|
||||
},
|
||||
|
||||
refresh: function() {
|
||||
var doc = this.frm.doc;
|
||||
erpnext.toggle_naming_series();
|
||||
|
||||
if(!this.frm.doc.__islocal && this.frm.doc.__onload && !this.frm.doc.__onload.is_customer) {
|
||||
this.frm.add_custom_button(__("Create Customer"), this.create_customer,
|
||||
frappe.boot.doctype_icons["Customer"], "btn-default");
|
||||
this.frm.add_custom_button(__("Create Opportunity"), this.create_opportunity,
|
||||
frappe.boot.doctype_icons["Opportunity"], "btn-default");
|
||||
cur_frm.add_custom_button(__("Send SMS"), this.frm.cscript.send_sms, "icon-mobile-phone");
|
||||
}
|
||||
|
||||
if(!this.frm.doc.__islocal) {
|
||||
erpnext.utils.render_address_and_contact(cur_frm);
|
||||
}
|
||||
},
|
||||
|
||||
create_customer: function() {
|
||||
frappe.model.open_mapped_doc({
|
||||
method: "erpnext.crm.doctype.lead.lead.make_customer",
|
||||
frm: cur_frm
|
||||
})
|
||||
},
|
||||
|
||||
create_opportunity: function() {
|
||||
frappe.model.open_mapped_doc({
|
||||
method: "erpnext.crm.doctype.lead.lead.make_opportunity",
|
||||
frm: cur_frm
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
$.extend(cur_frm.cscript, new erpnext.LeadController({frm: cur_frm}));
|
||||
|
||||
cur_frm.cscript.send_sms = function() {
|
||||
frappe.require("assets/erpnext/js/sms_manager.js");
|
||||
var sms_man = new SMSManager(cur_frm.doc);
|
||||
}
|
||||
|
||||
429
erpnext/crm/doctype/lead/lead.json
Normal file
429
erpnext/crm/doctype/lead/lead.json
Normal file
@@ -0,0 +1,429 @@
|
||||
{
|
||||
"allow_import": 1,
|
||||
"autoname": "naming_series:",
|
||||
"creation": "2013-04-10 11:45:37",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Master",
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "lead_details",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Lead Details",
|
||||
"options": "icon-user",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "naming_series",
|
||||
"fieldtype": "Select",
|
||||
"label": "Series",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "naming_series",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "LEAD-",
|
||||
"permlevel": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "lead_name",
|
||||
"fieldtype": "Data",
|
||||
"in_filter": 1,
|
||||
"in_list_view": 0,
|
||||
"label": "Contact Name",
|
||||
"oldfieldname": "lead_name",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "company_name",
|
||||
"fieldtype": "Data",
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Organization Name",
|
||||
"oldfieldname": "company_name",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "email_id",
|
||||
"fieldtype": "Data",
|
||||
"label": "Email Id",
|
||||
"oldfieldname": "email_id",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"default": "Lead",
|
||||
"fieldname": "status",
|
||||
"fieldtype": "Select",
|
||||
"in_filter": 1,
|
||||
"in_list_view": 0,
|
||||
"label": "Status",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "status",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Lead\nOpen\nReplied\nOpportunity\nInterested\nConverted\nDo Not Contact",
|
||||
"permlevel": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "source",
|
||||
"fieldtype": "Select",
|
||||
"in_filter": 1,
|
||||
"in_list_view": 0,
|
||||
"label": "Source",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "source",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "\nAdvertisement\nBlog Post\nCampaign\nCall\nCustomer\nExhibition\nSupplier\nWebsite\nEmail",
|
||||
"permlevel": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "col_break123",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.source == 'Customer'",
|
||||
"fieldname": "customer",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"label": "From Customer",
|
||||
"oldfieldname": "customer",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Customer",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.source == 'Campaign'",
|
||||
"description": "Enter campaign name if the source of lead is campaign.",
|
||||
"fieldname": "campaign_name",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"label": "Campaign Name",
|
||||
"oldfieldname": "campaign_name",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Campaign",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"default": "__user",
|
||||
"fieldname": "lead_owner",
|
||||
"fieldtype": "Link",
|
||||
"in_filter": 1,
|
||||
"label": "Lead Owner",
|
||||
"oldfieldname": "lead_owner",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "User",
|
||||
"permlevel": 0,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "contact_by",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"in_filter": 1,
|
||||
"label": "Next Contact By",
|
||||
"oldfieldname": "contact_by",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "User",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"reqd": 0,
|
||||
"width": "100px"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"description": "Add to calendar on this date",
|
||||
"fieldname": "contact_date",
|
||||
"fieldtype": "Datetime",
|
||||
"in_filter": 1,
|
||||
"label": "Next Contact Date",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "contact_date",
|
||||
"oldfieldtype": "Date",
|
||||
"permlevel": 0,
|
||||
"reqd": 0,
|
||||
"width": "100px"
|
||||
},
|
||||
{
|
||||
"fieldname": "fold",
|
||||
"fieldtype": "Fold",
|
||||
"label": "fold",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "contact_info",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Address & Contact",
|
||||
"oldfieldtype": "Column Break",
|
||||
"options": "icon-map-marker",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.__islocal",
|
||||
"fieldname": "address_desc",
|
||||
"fieldtype": "HTML",
|
||||
"hidden": 0,
|
||||
"label": "Address Desc",
|
||||
"options": "<em>Addresses will appear only when you save the lead</em>",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "address_html",
|
||||
"fieldtype": "HTML",
|
||||
"hidden": 0,
|
||||
"label": "Address HTML",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break2",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "phone",
|
||||
"fieldtype": "Data",
|
||||
"label": "Phone",
|
||||
"oldfieldname": "contact_no",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "mobile_no",
|
||||
"fieldtype": "Data",
|
||||
"label": "Mobile No.",
|
||||
"oldfieldname": "mobile_no",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "fax",
|
||||
"fieldtype": "Data",
|
||||
"label": "Fax",
|
||||
"oldfieldname": "fax",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "website",
|
||||
"fieldtype": "Data",
|
||||
"label": "Website",
|
||||
"oldfieldname": "website",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"description": "",
|
||||
"fieldname": "territory",
|
||||
"fieldtype": "Link",
|
||||
"label": "Territory",
|
||||
"oldfieldname": "territory",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Territory",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "more_info",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "More Info",
|
||||
"oldfieldtype": "Section Break",
|
||||
"options": "icon-file-text",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "type",
|
||||
"fieldtype": "Select",
|
||||
"in_filter": 1,
|
||||
"label": "Lead Type",
|
||||
"oldfieldname": "type",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "\nClient\nChannel Partner\nConsultant",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "market_segment",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"in_filter": 1,
|
||||
"label": "Market Segment",
|
||||
"oldfieldname": "market_segment",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "\nLower Income\nMiddle Income\nUpper Income",
|
||||
"permlevel": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "industry",
|
||||
"fieldtype": "Link",
|
||||
"label": "Industry",
|
||||
"oldfieldname": "industry",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Industry Type",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "request_type",
|
||||
"fieldtype": "Select",
|
||||
"label": "Request Type",
|
||||
"oldfieldname": "request_type",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "\nProduct Enquiry\nRequest for Information\nSuggestions\nOther",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "fiscal_year",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
"in_filter": 1,
|
||||
"label": "Fiscal Year",
|
||||
"oldfieldname": "fiscal_year",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Fiscal Year",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break3",
|
||||
"fieldtype": "Column Break",
|
||||
"oldfieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"label": "Company",
|
||||
"oldfieldname": "company",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Company",
|
||||
"permlevel": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "unsubscribed",
|
||||
"fieldtype": "Check",
|
||||
"label": "Unsubscribed",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "blog_subscriber",
|
||||
"fieldtype": "Check",
|
||||
"label": "Blog Subscriber",
|
||||
"permlevel": 0
|
||||
}
|
||||
],
|
||||
"icon": "icon-user",
|
||||
"idx": 1,
|
||||
"modified": "2015-02-16 23:54:10.622839",
|
||||
"modified_by": "Administrator",
|
||||
"module": "CRM",
|
||||
"name": "Lead",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
"match": "",
|
||||
"permlevel": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "All",
|
||||
"submit": 0,
|
||||
"write": 0
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 0,
|
||||
"email": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Sales User",
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Sales Manager",
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 0,
|
||||
"email": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
"match": "",
|
||||
"permlevel": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Sales Manager",
|
||||
"submit": 0,
|
||||
"write": 0
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
"match": "",
|
||||
"permlevel": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Sales User",
|
||||
"submit": 0,
|
||||
"write": 0
|
||||
}
|
||||
],
|
||||
"search_fields": "lead_name,lead_owner,status",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "lead_name"
|
||||
}
|
||||
150
erpnext/crm/doctype/lead/lead.py
Normal file
150
erpnext/crm/doctype/lead/lead.py
Normal file
@@ -0,0 +1,150 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import cstr, validate_email_add, cint, comma_and
|
||||
from frappe import session
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
|
||||
from erpnext.controllers.selling_controller import SellingController
|
||||
from erpnext.utilities.address_and_contact import load_address_and_contact
|
||||
|
||||
class Lead(SellingController):
|
||||
def get_feed(self):
|
||||
return '{0}: {1}'.format(_(self.status), self.lead_name)
|
||||
|
||||
def set_sender(self, sender):
|
||||
"""Will be called by **Communication** when a Lead is created from an incoming email."""
|
||||
self.email_id = sender
|
||||
|
||||
def onload(self):
|
||||
customer = frappe.db.get_value("Customer", {"lead_name": self.name})
|
||||
self.get("__onload").is_customer = customer
|
||||
load_address_and_contact(self, "lead")
|
||||
|
||||
def validate(self):
|
||||
self._prev = frappe._dict({
|
||||
"contact_date": frappe.db.get_value("Lead", self.name, "contact_date") if \
|
||||
(not cint(self.get("__islocal"))) else None,
|
||||
"contact_by": frappe.db.get_value("Lead", self.name, "contact_by") if \
|
||||
(not cint(self.get("__islocal"))) else None,
|
||||
})
|
||||
|
||||
self.set_status()
|
||||
|
||||
if self.source == 'Campaign' and not self.campaign_name and session['user'] != 'Guest':
|
||||
frappe.throw(_("Campaign Name is required"))
|
||||
|
||||
if self.email_id:
|
||||
if not validate_email_add(self.email_id):
|
||||
frappe.throw(_('{0} is not a valid email id').format(self.email_id))
|
||||
|
||||
if self.email_id == self.lead_owner:
|
||||
# Lead Owner cannot be same as the Lead
|
||||
self.lead_owner = None
|
||||
|
||||
def on_update(self):
|
||||
self.check_email_id_is_unique()
|
||||
self.add_calendar_event()
|
||||
|
||||
def add_calendar_event(self, opts=None, force=False):
|
||||
super(Lead, self).add_calendar_event({
|
||||
"owner": self.lead_owner,
|
||||
"starts_on": self.contact_date,
|
||||
"subject": ('Contact ' + cstr(self.lead_name)),
|
||||
"description": ('Contact ' + cstr(self.lead_name)) + \
|
||||
(self.contact_by and ('. By : ' + cstr(self.contact_by)) or '')
|
||||
}, force)
|
||||
|
||||
def check_email_id_is_unique(self):
|
||||
if self.email_id:
|
||||
# validate email is unique
|
||||
email_list = frappe.db.sql("""select name from tabLead where email_id=%s""",
|
||||
self.email_id)
|
||||
if len(email_list) > 1:
|
||||
items = [e[0] for e in email_list if e[0]!=self.name]
|
||||
frappe.throw(_("Email id must be unique, already exists for {0}").format(comma_and(items)))
|
||||
|
||||
def on_trash(self):
|
||||
frappe.db.sql("""update `tabIssue` set lead='' where lead=%s""",
|
||||
self.name)
|
||||
|
||||
self.delete_events()
|
||||
|
||||
def has_customer(self):
|
||||
return frappe.db.get_value("Customer", {"lead_name": self.name})
|
||||
|
||||
def has_opportunity(self):
|
||||
return frappe.db.get_value("Opportunity", {"lead": self.name, "docstatus": 1,
|
||||
"status": ["!=", "Lost"]})
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_customer(source_name, target_doc=None):
|
||||
return _make_customer(source_name, target_doc)
|
||||
|
||||
def _make_customer(source_name, target_doc=None, ignore_permissions=False):
|
||||
def set_missing_values(source, target):
|
||||
if source.company_name:
|
||||
target.customer_type = "Company"
|
||||
target.customer_name = source.company_name
|
||||
else:
|
||||
target.customer_type = "Individual"
|
||||
target.customer_name = source.lead_name
|
||||
|
||||
target.customer_group = frappe.db.get_default("customer_group")
|
||||
|
||||
doclist = get_mapped_doc("Lead", source_name,
|
||||
{"Lead": {
|
||||
"doctype": "Customer",
|
||||
"field_map": {
|
||||
"name": "lead_name",
|
||||
"company_name": "customer_name",
|
||||
"contact_no": "phone_1",
|
||||
"fax": "fax_1"
|
||||
}
|
||||
}}, target_doc, set_missing_values, ignore_permissions=ignore_permissions)
|
||||
|
||||
return doclist
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_opportunity(source_name, target_doc=None):
|
||||
target_doc = get_mapped_doc("Lead", source_name,
|
||||
{"Lead": {
|
||||
"doctype": "Opportunity",
|
||||
"field_map": {
|
||||
"campaign_name": "campaign",
|
||||
"doctype": "enquiry_from",
|
||||
"name": "lead",
|
||||
"lead_name": "contact_display",
|
||||
"company_name": "customer_name",
|
||||
"email_id": "contact_email",
|
||||
"mobile_no": "contact_mobile"
|
||||
}
|
||||
}}, target_doc)
|
||||
|
||||
return target_doc
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_lead_details(lead):
|
||||
if not lead: return {}
|
||||
|
||||
from erpnext.accounts.party import set_address_details
|
||||
out = frappe._dict()
|
||||
|
||||
lead_doc = frappe.get_doc("Lead", lead)
|
||||
lead = lead_doc
|
||||
|
||||
out.update({
|
||||
"territory": lead.territory,
|
||||
"customer_name": lead.company_name or lead.lead_name,
|
||||
"contact_display": lead.lead_name,
|
||||
"contact_email": lead.email_id,
|
||||
"contact_mobile": lead.mobile_no,
|
||||
"contact_phone": lead.phone,
|
||||
})
|
||||
|
||||
set_address_details(out, lead, "Lead")
|
||||
|
||||
return out
|
||||
23
erpnext/crm/doctype/lead/test_lead.py
Normal file
23
erpnext/crm/doctype/lead/test_lead.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
test_records = frappe.get_test_records('Lead')
|
||||
|
||||
class TestLead(unittest.TestCase):
|
||||
def test_make_customer(self):
|
||||
from erpnext.crm.doctype.lead.lead import make_customer
|
||||
|
||||
frappe.delete_doc_if_exists("Customer", "_Test Lead")
|
||||
|
||||
customer = make_customer("_T-Lead-00001")
|
||||
self.assertEquals(customer.doctype, "Customer")
|
||||
self.assertEquals(customer.lead_name, "_T-Lead-00001")
|
||||
|
||||
customer.company = "_Test Company"
|
||||
customer.customer_group = "_Test Customer Group"
|
||||
customer.insert()
|
||||
27
erpnext/crm/doctype/lead/test_records.json
Normal file
27
erpnext/crm/doctype/lead/test_records.json
Normal file
@@ -0,0 +1,27 @@
|
||||
[
|
||||
{
|
||||
"doctype": "Lead",
|
||||
"email_id": "test_lead@example.com",
|
||||
"lead_name": "_Test Lead",
|
||||
"status": "Open",
|
||||
"territory": "_Test Territory"
|
||||
},
|
||||
{
|
||||
"doctype": "Lead",
|
||||
"email_id": "test_lead1@example.com",
|
||||
"lead_name": "_Test Lead 1",
|
||||
"status": "Open"
|
||||
},
|
||||
{
|
||||
"doctype": "Lead",
|
||||
"email_id": "test_lead2@example.com",
|
||||
"lead_name": "_Test Lead 2",
|
||||
"status": "Lead"
|
||||
},
|
||||
{
|
||||
"doctype": "Lead",
|
||||
"email_id": "test_lead3@example.com",
|
||||
"lead_name": "_Test Lead 3",
|
||||
"status": "Converted"
|
||||
}
|
||||
]
|
||||
1
erpnext/crm/doctype/opportunity/README.md
Normal file
1
erpnext/crm/doctype/opportunity/README.md
Normal file
@@ -0,0 +1 @@
|
||||
Potential sales opportunity (deal) from a Lead or Customer.
|
||||
0
erpnext/crm/doctype/opportunity/__init__.py
Normal file
0
erpnext/crm/doctype/opportunity/__init__.py
Normal file
153
erpnext/crm/doctype/opportunity/opportunity.js
Normal file
153
erpnext/crm/doctype/opportunity/opportunity.js
Normal file
@@ -0,0 +1,153 @@
|
||||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.ui.form.on_change("Opportunity", "customer", function(frm) {
|
||||
erpnext.utils.get_party_details(frm) });
|
||||
frappe.ui.form.on_change("Opportunity", "customer_address", erpnext.utils.get_address_display);
|
||||
frappe.ui.form.on_change("Opportunity", "contact_person", erpnext.utils.get_contact_details);
|
||||
|
||||
|
||||
frappe.provide("erpnext.crm");
|
||||
frappe.require("assets/erpnext/js/utils.js");
|
||||
cur_frm.email_field = "contact_email";
|
||||
|
||||
// TODO commonify this code
|
||||
erpnext.crm.Opportunity = frappe.ui.form.Controller.extend({
|
||||
onload: function() {
|
||||
if(!this.frm.doc.enquiry_from && this.frm.doc.customer)
|
||||
this.frm.doc.enquiry_from = "Customer";
|
||||
if(!this.frm.doc.enquiry_from && this.frm.doc.lead)
|
||||
this.frm.doc.enquiry_from = "Lead";
|
||||
|
||||
if(!this.frm.doc.status)
|
||||
set_multiple(cdt, cdn, { status:'Draft' });
|
||||
if(!this.frm.doc.date)
|
||||
this.frm.doc.transaction_date = date.obj_to_str(new Date());
|
||||
if(!this.frm.doc.company && frappe.defaults.get_user_default("company"))
|
||||
set_multiple(cdt, cdn, { company:frappe.defaults.get_user_default("company") });
|
||||
if(!this.frm.doc.fiscal_year && sys_defaults.fiscal_year)
|
||||
set_multiple(cdt, cdn, { fiscal_year:sys_defaults.fiscal_year });
|
||||
|
||||
|
||||
this.setup_queries();
|
||||
},
|
||||
|
||||
setup_queries: function() {
|
||||
var me = this;
|
||||
|
||||
if(this.frm.fields_dict.contact_by.df.options.match(/^User/)) {
|
||||
this.frm.set_query("contact_by", erpnext.queries.user);
|
||||
}
|
||||
|
||||
this.frm.set_query("customer_address", function() {
|
||||
if(me.frm.doc.lead) return {filters: { lead: me.frm.doc.lead } };
|
||||
else if(me.frm.doc.customer) return {filters: { customer: me.frm.doc.customer } };
|
||||
});
|
||||
|
||||
this.frm.set_query("item_code", "items", function() {
|
||||
return {
|
||||
query: "erpnext.controllers.queries.item_query",
|
||||
filters: me.frm.doc.enquiry_type === "Maintenance" ?
|
||||
{"is_service_item": "Yes"} : {"is_sales_item": "Yes"}
|
||||
};
|
||||
});
|
||||
|
||||
$.each([["lead", "lead"],
|
||||
["customer", "customer"],
|
||||
["contact_person", "customer_filter"],
|
||||
["territory", "not_a_group_filter"]], function(i, opts) {
|
||||
me.frm.set_query(opts[0], erpnext.queries[opts[1]]);
|
||||
});
|
||||
},
|
||||
|
||||
create_quotation: function() {
|
||||
frappe.model.open_mapped_doc({
|
||||
method: "erpnext.crm.doctype.opportunity.opportunity.make_quotation",
|
||||
frm: cur_frm
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
$.extend(cur_frm.cscript, new erpnext.crm.Opportunity({frm: cur_frm}));
|
||||
|
||||
cur_frm.cscript.refresh = function(doc, cdt, cdn) {
|
||||
erpnext.toggle_naming_series();
|
||||
|
||||
if(doc.docstatus === 1 && doc.status!=="Lost") {
|
||||
cur_frm.add_custom_button(__('Create Quotation'),
|
||||
cur_frm.cscript.create_quotation, frappe.boot.doctype_icons["Quotation"],
|
||||
"btn-default");
|
||||
if(doc.status!=="Quotation")
|
||||
cur_frm.add_custom_button(__('Opportunity Lost'),
|
||||
cur_frm.cscript['Declare Opportunity Lost'], "icon-remove", "btn-default");
|
||||
|
||||
cur_frm.add_custom_button(__('Send SMS'), cur_frm.cscript.send_sms,
|
||||
"icon-mobile-phone", true);
|
||||
}
|
||||
}
|
||||
|
||||
cur_frm.cscript.onload_post_render = function(doc, cdt, cdn) {
|
||||
if(doc.enquiry_from == 'Lead' && doc.lead)
|
||||
cur_frm.cscript.lead(doc, cdt, cdn);
|
||||
}
|
||||
|
||||
cur_frm.cscript.item_code = function(doc, cdt, cdn) {
|
||||
var d = locals[cdt][cdn];
|
||||
if (d.item_code) {
|
||||
return get_server_fields('get_item_details', d.item_code,
|
||||
'items', doc, cdt, cdn, 1);
|
||||
}
|
||||
}
|
||||
|
||||
cur_frm.cscript.lead = function(doc, cdt, cdn) {
|
||||
cur_frm.toggle_display("contact_info", doc.customer || doc.lead);
|
||||
frappe.model.map_current_doc({
|
||||
method: "erpnext.crm.doctype.lead.lead.make_opportunity",
|
||||
source_name: cur_frm.doc.lead,
|
||||
frm: cur_frm
|
||||
});
|
||||
}
|
||||
|
||||
cur_frm.cscript['Declare Opportunity Lost'] = function() {
|
||||
var dialog = new frappe.ui.Dialog({
|
||||
title: __("Set as Lost"),
|
||||
fields: [
|
||||
{"fieldtype": "Text", "label": __("Reason for losing"), "fieldname": "reason",
|
||||
"reqd": 1 },
|
||||
{"fieldtype": "Button", "label": __("Update"), "fieldname": "update"},
|
||||
]
|
||||
});
|
||||
|
||||
dialog.fields_dict.update.$input.click(function() {
|
||||
args = dialog.get_values();
|
||||
if(!args) return;
|
||||
return cur_frm.call({
|
||||
doc: cur_frm.doc,
|
||||
method: "declare_enquiry_lost",
|
||||
args: args.reason,
|
||||
callback: function(r) {
|
||||
if(r.exc) {
|
||||
msgprint(__("There were errors."));
|
||||
} else {
|
||||
dialog.hide();
|
||||
cur_frm.refresh();
|
||||
}
|
||||
},
|
||||
btn: this
|
||||
})
|
||||
});
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
cur_frm.cscript.send_sms = function() {
|
||||
frappe.require("assets/erpnext/js/sms_manager.js");
|
||||
var sms_man = new SMSManager(cur_frm.doc);
|
||||
}
|
||||
|
||||
cur_frm.cscript.company = function(doc, cdt, cdn) {
|
||||
erpnext.get_fiscal_year(doc.company, doc.transaction_date);
|
||||
}
|
||||
|
||||
cur_frm.cscript.transaction_date = function(doc, cdt, cdn){
|
||||
erpnext.get_fiscal_year(doc.company, doc.transaction_date);
|
||||
}
|
||||
436
erpnext/crm/doctype/opportunity/opportunity.json
Normal file
436
erpnext/crm/doctype/opportunity/opportunity.json
Normal file
@@ -0,0 +1,436 @@
|
||||
{
|
||||
"allow_import": 1,
|
||||
"autoname": "naming_series:",
|
||||
"creation": "2013-03-07 18:50:30",
|
||||
"description": "Potential Sales Deal",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Transaction",
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "from_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "From",
|
||||
"options": "icon-user",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "naming_series",
|
||||
"fieldtype": "Select",
|
||||
"label": "Series",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "naming_series",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "OPTY-",
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "enquiry_from",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 0,
|
||||
"label": "Opportunity From",
|
||||
"oldfieldname": "enquiry_from",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "\nLead\nCustomer",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.enquiry_from===\"Customer\"",
|
||||
"fieldname": "customer",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"in_filter": 1,
|
||||
"in_list_view": 0,
|
||||
"label": "Customer",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "customer",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Customer",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.enquiry_from===\"Lead\"",
|
||||
"fieldname": "lead",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"in_filter": 1,
|
||||
"in_list_view": 0,
|
||||
"label": "Lead",
|
||||
"oldfieldname": "lead",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Lead",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"depends_on": "",
|
||||
"fieldname": "customer_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"label": "Customer / Lead Name",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break0",
|
||||
"fieldtype": "Column Break",
|
||||
"oldfieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"fieldname": "enquiry_type",
|
||||
"fieldtype": "Select",
|
||||
"label": "Opportunity Type",
|
||||
"oldfieldname": "enquiry_type",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "\nSales\nMaintenance",
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"default": "Draft",
|
||||
"fieldname": "status",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 0,
|
||||
"label": "Status",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "status",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Draft\nSubmitted\nQuotation\nLost\nCancelled\nReplied\nOpen",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "items_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Items",
|
||||
"oldfieldtype": "Section Break",
|
||||
"options": "icon-shopping-cart",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"description": "Items which do not exist in Item master can also be entered on customer's request",
|
||||
"fieldname": "items",
|
||||
"fieldtype": "Table",
|
||||
"label": "Items",
|
||||
"oldfieldname": "enquiry_details",
|
||||
"oldfieldtype": "Table",
|
||||
"options": "Opportunity Item",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "fold",
|
||||
"fieldtype": "Fold",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.lead || doc.customer",
|
||||
"fieldname": "contact_info",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Contact Info",
|
||||
"options": "icon-bullhorn",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.customer || doc.lead",
|
||||
"fieldname": "customer_address",
|
||||
"fieldtype": "Link",
|
||||
"in_filter": 1,
|
||||
"label": "Customer / Lead Address",
|
||||
"options": "Address",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "address_display",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 1,
|
||||
"label": "Address",
|
||||
"oldfieldname": "address",
|
||||
"oldfieldtype": "Small Text",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "customer",
|
||||
"description": "",
|
||||
"fieldname": "territory",
|
||||
"fieldtype": "Link",
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Territory",
|
||||
"options": "Territory",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "customer",
|
||||
"description": "",
|
||||
"fieldname": "customer_group",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"in_filter": 1,
|
||||
"label": "Customer Group",
|
||||
"oldfieldname": "customer_group",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Customer Group",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break3",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.lead || doc.customer",
|
||||
"fieldname": "contact_person",
|
||||
"fieldtype": "Link",
|
||||
"in_filter": 1,
|
||||
"label": "Contact Person",
|
||||
"options": "Contact",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"depends_on": "customer",
|
||||
"fieldname": "contact_display",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "Contact",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.lead || doc.customer",
|
||||
"fieldname": "contact_email",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "Contact Email",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.lead || doc.customer",
|
||||
"fieldname": "contact_mobile",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "Contact Mobile No",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "more_info",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "More Info",
|
||||
"oldfieldtype": "Section Break",
|
||||
"options": "icon-file-text",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break1",
|
||||
"fieldtype": "Column Break",
|
||||
"oldfieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"default": "Today",
|
||||
"fieldname": "transaction_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Opportunity Date",
|
||||
"oldfieldname": "transaction_date",
|
||||
"oldfieldtype": "Date",
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 1,
|
||||
"width": "50px"
|
||||
},
|
||||
{
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"in_filter": 1,
|
||||
"label": "Company",
|
||||
"oldfieldname": "company",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Company",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "source",
|
||||
"fieldtype": "Select",
|
||||
"label": "Source",
|
||||
"oldfieldname": "source",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "\nExisting Customer\nReference\nAdvertisement\nCold Calling\nExhibition\nSupplier Reference\nMass Mailing\nCustomer's Vendor\nCampaign\nWalk In",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"description": "Enter name of campaign if source of enquiry is campaign",
|
||||
"fieldname": "campaign",
|
||||
"fieldtype": "Link",
|
||||
"label": "Campaign",
|
||||
"oldfieldname": "campaign",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Campaign",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "fiscal_year",
|
||||
"fieldtype": "Link",
|
||||
"in_filter": 1,
|
||||
"label": "Fiscal Year",
|
||||
"oldfieldname": "fiscal_year",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Fiscal Year",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:!doc.__islocal",
|
||||
"fieldname": "order_lost_reason",
|
||||
"fieldtype": "Text",
|
||||
"label": "Lost Reason",
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break2",
|
||||
"fieldtype": "Column Break",
|
||||
"oldfieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"description": "Your sales person who will contact the customer in future",
|
||||
"fieldname": "contact_by",
|
||||
"fieldtype": "Link",
|
||||
"in_filter": 1,
|
||||
"label": "Next Contact By",
|
||||
"oldfieldname": "contact_by",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "User",
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"width": "75px"
|
||||
},
|
||||
{
|
||||
"description": "Your sales person will get a reminder on this date to contact the customer",
|
||||
"fieldname": "contact_date",
|
||||
"fieldtype": "Datetime",
|
||||
"label": "Next Contact Date",
|
||||
"oldfieldname": "contact_date",
|
||||
"oldfieldtype": "Date",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "to_discuss",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "To Discuss",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "to_discuss",
|
||||
"oldfieldtype": "Small Text",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "amended_from",
|
||||
"fieldtype": "Link",
|
||||
"ignore_user_permissions": 1,
|
||||
"label": "Amended From",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "amended_from",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "Opportunity",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
"width": "150px"
|
||||
}
|
||||
],
|
||||
"icon": "icon-info-sign",
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"modified": "2015-02-16 23:52:23.489259",
|
||||
"modified_by": "Administrator",
|
||||
"module": "CRM",
|
||||
"name": "Opportunity",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 1,
|
||||
"apply_user_permissions": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Sales User",
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Sales Manager",
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"search_fields": "status,transaction_date,customer,lead,enquiry_type,territory,company",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "customer_name"
|
||||
}
|
||||
174
erpnext/crm/doctype/opportunity/opportunity.py
Normal file
174
erpnext/crm/doctype/opportunity/opportunity.py
Normal file
@@ -0,0 +1,174 @@
|
||||
# Copyright (c) 2013, Web Notes 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 cstr, cint
|
||||
from frappe import msgprint, _
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
|
||||
from erpnext.utilities.transaction_base import TransactionBase
|
||||
|
||||
class Opportunity(TransactionBase):
|
||||
|
||||
def validate(self):
|
||||
self._prev = frappe._dict({
|
||||
"contact_date": frappe.db.get_value("Opportunity", self.name, "contact_date") if \
|
||||
(not cint(self.get("__islocal"))) else None,
|
||||
"contact_by": frappe.db.get_value("Opportunity", self.name, "contact_by") if \
|
||||
(not cint(self.get("__islocal"))) else None,
|
||||
})
|
||||
|
||||
if not self.enquiry_from:
|
||||
frappe.throw(_("Opportunity From field is mandatory"))
|
||||
|
||||
self.set_status()
|
||||
self.validate_item_details()
|
||||
self.validate_uom_is_integer("uom", "qty")
|
||||
self.validate_lead_cust()
|
||||
self.validate_cust_name()
|
||||
|
||||
from erpnext.accounts.utils import validate_fiscal_year
|
||||
validate_fiscal_year(self.transaction_date, self.fiscal_year, "Opportunity Date")
|
||||
|
||||
def on_submit(self):
|
||||
if self.lead:
|
||||
frappe.get_doc("Lead", self.lead).set_status(update=True)
|
||||
|
||||
def on_cancel(self):
|
||||
if self.has_quotation():
|
||||
frappe.throw(_("Cannot Cancel Opportunity as Quotation Exists"))
|
||||
self.set_status(update=True)
|
||||
|
||||
def declare_enquiry_lost(self,arg):
|
||||
if not self.has_quotation():
|
||||
frappe.db.set(self, 'status', 'Lost')
|
||||
frappe.db.set(self, 'order_lost_reason', arg)
|
||||
else:
|
||||
frappe.throw(_("Cannot declare as lost, because Quotation has been made."))
|
||||
|
||||
def on_trash(self):
|
||||
self.delete_events()
|
||||
|
||||
def has_quotation(self):
|
||||
return frappe.db.get_value("Quotation Item", {"prevdoc_docname": self.name, "docstatus": 1})
|
||||
|
||||
def has_ordered_quotation(self):
|
||||
return frappe.db.sql("""select q.name from `tabQuotation` q, `tabQuotation Item` qi
|
||||
where q.name = qi.parent and q.docstatus=1 and qi.prevdoc_docname =%s and q.status = 'Ordered'""", self.name)
|
||||
|
||||
def validate_cust_name(self):
|
||||
self.customer_name = self.customer or self.lead
|
||||
|
||||
def get_item_details(self, item_code):
|
||||
item = frappe.db.sql("""select item_name, stock_uom, description_html, description, item_group, brand
|
||||
from `tabItem` where name = %s""", item_code, as_dict=1)
|
||||
ret = {
|
||||
'item_name': item and item[0]['item_name'] or '',
|
||||
'uom': item and item[0]['stock_uom'] or '',
|
||||
'description': item and item[0]['description_html'] or item[0]['description'] or '',
|
||||
'item_group': item and item[0]['item_group'] or '',
|
||||
'brand': item and item[0]['brand'] or ''
|
||||
}
|
||||
return ret
|
||||
|
||||
def get_cust_address(self,name):
|
||||
details = frappe.db.sql("""select customer_name, address, territory, customer_group
|
||||
from `tabCustomer` where name = %s and docstatus != 2""", (name), as_dict = 1)
|
||||
if details:
|
||||
ret = {
|
||||
'customer_name': details and details[0]['customer_name'] or '',
|
||||
'address' : details and details[0]['address'] or '',
|
||||
'territory' : details and details[0]['territory'] or '',
|
||||
'customer_group' : details and details[0]['customer_group'] or ''
|
||||
}
|
||||
# ********** get primary contact details (this is done separately coz. , in case there is no primary contact thn it would not be able to fetch customer details in case of join query)
|
||||
|
||||
contact_det = frappe.db.sql("""select contact_name, contact_no, email_id
|
||||
from `tabContact` where customer = %s and is_customer = 1
|
||||
and is_primary_contact = 'Yes' and docstatus != 2""", name, as_dict = 1)
|
||||
|
||||
ret['contact_person'] = contact_det and contact_det[0]['contact_name'] or ''
|
||||
ret['contact_no'] = contact_det and contact_det[0]['contact_no'] or ''
|
||||
ret['email_id'] = contact_det and contact_det[0]['email_id'] or ''
|
||||
|
||||
return ret
|
||||
else:
|
||||
frappe.throw(_("Customer {0} does not exist").format(name), frappe.DoesNotExistError)
|
||||
|
||||
def on_update(self):
|
||||
self.add_calendar_event()
|
||||
|
||||
def add_calendar_event(self, opts=None, force=False):
|
||||
if not opts:
|
||||
opts = frappe._dict()
|
||||
|
||||
opts.description = ""
|
||||
opts.contact_date = self.contact_date
|
||||
|
||||
if self.customer:
|
||||
if self.contact_person:
|
||||
opts.description = 'Contact '+cstr(self.contact_person)
|
||||
else:
|
||||
opts.description = 'Contact customer '+cstr(self.customer)
|
||||
elif self.lead:
|
||||
if self.contact_display:
|
||||
opts.description = 'Contact '+cstr(self.contact_display)
|
||||
else:
|
||||
opts.description = 'Contact lead '+cstr(self.lead)
|
||||
|
||||
opts.subject = opts.description
|
||||
opts.description += '. By : ' + cstr(self.contact_by)
|
||||
|
||||
if self.to_discuss:
|
||||
opts.description += ' To Discuss : ' + cstr(self.to_discuss)
|
||||
|
||||
super(Opportunity, self).add_calendar_event(opts, force)
|
||||
|
||||
def validate_item_details(self):
|
||||
if not self.get('items'):
|
||||
frappe.throw(_("Items required"))
|
||||
|
||||
def validate_lead_cust(self):
|
||||
if self.enquiry_from == 'Lead':
|
||||
if not self.lead:
|
||||
frappe.throw(_("Lead must be set if Opportunity is made from Lead"))
|
||||
else:
|
||||
self.customer = None
|
||||
elif self.enquiry_from == 'Customer':
|
||||
if not self.customer:
|
||||
msgprint("Customer is mandatory if 'Opportunity From' is selected as Customer", raise_exception=1)
|
||||
else:
|
||||
self.lead = None
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_quotation(source_name, target_doc=None):
|
||||
def set_missing_values(source, target):
|
||||
quotation = frappe.get_doc(target)
|
||||
quotation.run_method("set_missing_values")
|
||||
quotation.run_method("calculate_taxes_and_totals")
|
||||
|
||||
doclist = get_mapped_doc("Opportunity", source_name, {
|
||||
"Opportunity": {
|
||||
"doctype": "Quotation",
|
||||
"field_map": {
|
||||
"enquiry_from": "quotation_to",
|
||||
"enquiry_type": "order_type",
|
||||
"name": "enq_no",
|
||||
},
|
||||
"validation": {
|
||||
"docstatus": ["=", 1]
|
||||
}
|
||||
},
|
||||
"Opportunity Item": {
|
||||
"doctype": "Quotation Item",
|
||||
"field_map": {
|
||||
"parent": "prevdoc_docname",
|
||||
"parenttype": "prevdoc_doctype",
|
||||
"uom": "stock_uom"
|
||||
},
|
||||
"add_if_empty": True
|
||||
}
|
||||
}, target_doc, set_missing_values)
|
||||
|
||||
return doclist
|
||||
10
erpnext/crm/doctype/opportunity/opportunity_list.js
Normal file
10
erpnext/crm/doctype/opportunity/opportunity_list.js
Normal file
@@ -0,0 +1,10 @@
|
||||
frappe.listview_settings['Opportunity'] = {
|
||||
add_fields: ["customer_name", "enquiry_type", "enquiry_from", "status"],
|
||||
get_indicator: function(doc) {
|
||||
var indicator = [__(doc.status), frappe.utils.guess_colour(doc.status), "status,=," + doc.status];
|
||||
if(doc.status=="Quotation") {
|
||||
indicator[1] = "green";
|
||||
}
|
||||
return indicator;
|
||||
}
|
||||
};
|
||||
10
erpnext/crm/doctype/opportunity/test_opportunity.py
Normal file
10
erpnext/crm/doctype/opportunity/test_opportunity.py
Normal file
@@ -0,0 +1,10 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors and Contributors
|
||||
# See license.txt
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
test_records = frappe.get_test_records('Opportunity')
|
||||
|
||||
class TestOpportunity(unittest.TestCase):
|
||||
pass
|
||||
15
erpnext/crm/doctype/opportunity/test_records.json
Normal file
15
erpnext/crm/doctype/opportunity/test_records.json
Normal file
@@ -0,0 +1,15 @@
|
||||
[
|
||||
{
|
||||
"doctype": "Opportunity",
|
||||
"name": "_Test Opportunity 1",
|
||||
"enquiry_from": "Lead",
|
||||
"enquiry_type": "Sales",
|
||||
"lead": "_T-Lead-00001",
|
||||
"transaction_date": "2013-12-12",
|
||||
"fiscal_year": "_Test Fiscal Year 2013",
|
||||
"items": [{
|
||||
"item_name": "Test Item",
|
||||
"description": "Some description"
|
||||
}]
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user