CRM - 销售与客户
一、销售与客户 - 表结构
---公共客户(公共资源)
1、没有报名
2、3天没有跟进
3、15天没有成单 客户分布表
龙泰 男 yuan 2018-5-1 3天未跟进
龙泰 男 三江 2018-5-5 15天未成单
龙泰 男 暴雨 2018-5-21 正在跟进 ---我的客户(抢单)
crontab:
2018-5-15 12:00 龙泰 男 三江 2018-5-15 正在跟进 2018-5-16 0:0
2018-5-17 0:0
2018-5-18 0:0
2018-5-19 0:0 龙泰 男 三江 2018-5-19 3天未跟进 key: CustomerDistrbute为什么创建 ,为什么不能直接用Customer 因为:销售可以查看,自己的客户是否已过期,是否正在跟进,月底可以算业绩!
不能说没谈成,就没有业绩!! 一过期,就改了。定时脚本来完成!!
linux 固定时间,执行脚本 os 去做,
每天00:00去监测! 隔半天或隔一天,脚本每天凌晨监测一遍过期就放到公共客户。 新增客户分布表:
class CustomerDistrbute(models.Model):
customer = models.ForeignKey("Customer", related_name="customers")
consultant = models.ForeignKey(verbose_name="课程顾问", to="UserInfo", limit_choices_to={"depart_id":1001})
date = models.DateField()
status_choices = (
(1, '正在跟进'),
(2, '已报名'),
(3, '三天未跟进'),
(4, '15天未成单'),
)
status = models.IntegerField(choices=status_choices, default=1)
meno = models.CharField(max_length=255) def __str__(self):
return self.customer.name + ":" + self.consultant.name
新的表结构

二、公共客户

知识点
1. 新增url
temp.append(url(r'^public/', self.public_customer))
2. datetime.timedelta ( 时间 + - )
datetime.datetime
datetime.date
datetime.time
datetime.timedelta(days=7) now = datetime.datetime.now()
delta_day3 = datetime.timedelta(days=3)
delta_day15 = datetime.timedelta(days=15)
3. 未报名且3天未跟进或者15天未成单
# 3天未跟进 now - last_consult_date > 3 --> last_consult_date < now - 3
# 15天未成单 now - recv_date > 15 --> recv_date < now - 15 Q查询 last_consult_date__lt recv_date__lt customer_list = Customer.objects.filter(
Q(last_consult_date__lt=now-delta_day3)|Q(recv_date__lt=now-delta_day15),status=2)
4. exclude(排除)
# 不应该让之前的课程顾问 再看到这个已经放到公共名单的人了
user_id = 3
customer_list = Customer.objects.filter(
Q(last_consult_date__lt=now - delta_day3) | Q(recv_date__lt=now - delta_day15),
status=2).exclude(consultant=user_id)
5. customer_list.query( sql 语句 )
# print(customer_list.query)
"""
SELECT "crm_customer"."id", "crm_customer"."qq",
"crm_customer"."name", "crm_customer"."gender",
"crm_customer"."education", "crm_customer"."graduation_school",
"crm_customer"."major", "crm_customer"."experience",
"crm_customer"."work_status", "crm_customer"."company",
"crm_customer"."salary", "crm_customer"."source",
"crm_customer"."referral_from_id", "crm_customer"."status",
"crm_customer"."consultant_id", "crm_customer"."date",
"crm_customer"."recv_date", "crm_customer"."last_consult_date"
FROM "crm_customer"
WHERE (("crm_customer"."last_consult_date" < 2018-06-24
OR "crm_customer"."recv_date" < 2018-06-12)
AND "crm_customer"."status" = 2) """
def public_customer(self, request):
# 未报名且3天未跟进或者15天未成单
from django.db.models import Q
import datetime
"""
datetime.datetime
datetime.date
datetime.time
datetime.timedelta(days=7)
"""
now = datetime.datetime.now()
delta_day3 = datetime.timedelta(days=3)
delta_day15 = datetime.timedelta(days=15)
# 3天未跟进 now - last_consult_date > 3 --> last_consult_date < now - 3
# 15天未成单 now - recv_date > 15 --> recv_date < now - 15 # customer_list = Customer.objects.filter(
# Q(last_consult_date__lt=now-delta_day3)|Q(recv_date__lt=now-delta_day15),status=2) # 不应该让之前的课程顾问 再看到这个人已经放到公共名单的人了
user_id = 3
customer_list = Customer.objects.filter(
Q(last_consult_date__lt=now - delta_day3) | Q(recv_date__lt=now - delta_day15), status=2).exclude(consultant=user_id) # print(customer_list.query)
"""
SELECT "crm_customer"."id", "crm_customer"."qq",
"crm_customer"."name", "crm_customer"."gender",
"crm_customer"."education", "crm_customer"."graduation_school",
"crm_customer"."major", "crm_customer"."experience",
"crm_customer"."work_status", "crm_customer"."company",
"crm_customer"."salary", "crm_customer"."source",
"crm_customer"."referral_from_id", "crm_customer"."status",
"crm_customer"."consultant_id", "crm_customer"."date",
"crm_customer"."recv_date", "crm_customer"."last_consult_date"
FROM "crm_customer"
WHERE (("crm_customer"."last_consult_date" < 2018-06-24
OR "crm_customer"."recv_date" < 2018-06-12)
AND "crm_customer"."status" = 2) """
print("----->>:", customer_list) return render(request, 'public.html', locals()) ------------------------
temp.append(url(r'^public/', self.public_customer))
public.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css"> </head>
<body>
<h3>公共客户</h3> <div class="container">
<div class="row">
<div class="col-md-6">
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>ID</th>
<th>姓名</th>
<th>QQ</th>
<th>课程顾问</th>
<th>跟进详情</th>
<th>确认跟进</th>
</tr>
</thead>
<tbody>
{% for customer in customer_list %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ customer.name }}</td>
<td>{{ customer.qq }}</td>
<td>{{ customer.consultant }}</td>
<td><a href="/stark/crm/consultrecord/?customer={{ customer.pk }}">跟进记录</a></td>
<td><a href="/stark/crm/customer/further/{{ customer.pk }}">确认跟进</a></td>
</tr>
{% endfor %} </tbody>
</table>
</div>
</div>
</div> </body>
</html>
public.html
三、确认跟进

知识点
1. 新增url
temp.append(url(r'^further/(\d+)', self.further))
2. 更改课程顾问和对应的时间
一定要先过滤;防止多个用户同时抢单,给了 最后一个抢单的人;先过滤之后再抢单,注意提示已经被跟进了。
ret = Customer.objects.filter(pk=customer_id).filter(
Q(last_consult_date__lt=now-delta_day3)|Q(recv_date__lt=now-delta_day15),status=2).update(
consultant=user_id,last_consult_date = now,recv_date=now
)
3. 创建一条客户分布表
为我的客户页面做准备
CustomerDistrbute.objects.create(
customer_id=customer_id,consultant_id=user_id,
date=now,status=1,
)
temp.append(url(r'^further/(\d+)', self.further))
-------------------------------------------------------
def further(self, request,customer_id):
"""确认跟进"""
user_id = 3
now = datetime.datetime.now()
delta_day3 = datetime.timedelta(days=3)
delta_day15 = datetime.timedelta(days=15)
# 为该客户更改课程顾问 和对应得时间,
ret = Customer.objects.filter(pk=customer_id).filter(
Q(last_consult_date__lt=now-delta_day3)|Q(recv_date__lt=now-delta_day15),status=2).update(
consultant=user_id,last_consult_date = now,recv_date=now
)
if not ret:
return HttpResponse('已经被跟进了')
CustomerDistrbute.objects.create(
customer_id=customer_id,consultant_id=user_id,
date=now,status=1,
)
return HttpResponse('跟进成功')
四、我的客户

知识点
1. 新增url
temp.append(url(r'^mycustomer/', self.mycustomer))
2. 客户分布表查询
不能再 Customer表查询,这里查到的只是正在跟踪的客户信息
但是,之前跟踪过的客户,状态也要显示
customer_distrubute_list = CustomerDistrbute.objects.filter(consultant_id=user_id)
temp.append(url(r'^mycustomer/', self.mycustomer))
---------------------------------------------
def mycustomer(self, request):
user_id = 3
customer_distrubute_list = CustomerDistrbute.objects.filter(consultant_id=user_id)
return render(request,'mycustomer.html', locals())
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h4>我的客户</h4>
<ul>
{% for customer_distrubute in customer_distrubute_list %}
<li>
{{ customer_distrubute.customer }}
-----{{ customer_distrubute.date|date:'Y-m-d' }}
-----{{ customer_distrubute.get_status_display }}
</li>
{% endfor %} </ul> </body>
</html>
mycustomer.html
五、code
crm/stark.py
# -*- coding:utf-8 -*- from .models import *
from stark.service.stark import site, ModelStark
from django.utils.safestring import mark_safe
from django.conf.urls import url
from django.shortcuts import HttpResponse,reverse,redirect,render
import datetime
from django.db.models import Q class DepartmentConfig(ModelStark):
list_display = ['title', 'code'] site.register(Department, DepartmentConfig) class UserInfoConfig(ModelStark):
list_display = ["name", 'email', 'depart'] site.register(UserInfo, UserInfoConfig) class ClassListConfig(ModelStark):
def display_classname(self,obj=None,header=False):
if header:
return "班级名称"
return "%s(%s)"%(obj.course.name, obj.semester) list_display = [display_classname, 'tutor', 'teachers'] site.register(ClassList, ClassListConfig) class CustomerConfig(ModelStark):
def display_course(self, obj=None, header=False):
if header:
return "咨询课程" temp = []
for course in obj.course.all():
temp.append("<a href='/stark/crm/customer/cancel_course/%s/%s' style='border:1px solid #369; padding:3px 6px;'><span>%s</span></a> "%(obj.pk,course.pk,course.name)) return mark_safe("".join(temp)) def cancel_course(self, request, customer_id, course_id):
customer_obj = Customer.objects.filter(pk=customer_id).first()
customer_obj.course.remove(course_id)
return redirect(self.get_list_url()) # 重定向到当前表得查看页面 def public_customer(self, request):
# 未报名且3天未跟进或者15天未成单
from django.db.models import Q
import datetime
"""
datetime.datetime
datetime.date
datetime.time
datetime.timedelta(days=7)
"""
now = datetime.datetime.now()
delta_day3 = datetime.timedelta(days=3)
delta_day15 = datetime.timedelta(days=15)
# 3天未跟进 now - last_consult_date > 3 --> last_consult_date < now - 3
# 15天未成单 now - recv_date > 15 --> recv_date < now - 15 # customer_list = Customer.objects.filter(
# Q(last_consult_date__lt=now-delta_day3)|Q(recv_date__lt=now-delta_day15),status=2) # 不应该让之前的课程顾问 再看到这个已经放到公共名单的人了
user_id = 3
customer_list = Customer.objects.filter(
Q(last_consult_date__lt=now - delta_day3) | Q(recv_date__lt=now - delta_day15), status=2).exclude(consultant=user_id) # print(customer_list.query)
"""
SELECT "crm_customer"."id", "crm_customer"."qq",
"crm_customer"."name", "crm_customer"."gender",
"crm_customer"."education", "crm_customer"."graduation_school",
"crm_customer"."major", "crm_customer"."experience",
"crm_customer"."work_status", "crm_customer"."company",
"crm_customer"."salary", "crm_customer"."source",
"crm_customer"."referral_from_id", "crm_customer"."status",
"crm_customer"."consultant_id", "crm_customer"."date",
"crm_customer"."recv_date", "crm_customer"."last_consult_date"
FROM "crm_customer"
WHERE (("crm_customer"."last_consult_date" < 2018-06-24
OR "crm_customer"."recv_date" < 2018-06-12)
AND "crm_customer"."status" = 2) """
print("----->>:", customer_list) return render(request, 'public.html', locals()) def further(self, request,customer_id):
"""确认跟进"""
user_id = 3 now = datetime.datetime.now()
delta_day3 = datetime.timedelta(days=3)
delta_day15 = datetime.timedelta(days=15) # 为该客户更改课程顾问 和对应得时间,
ret = Customer.objects.filter(pk=customer_id).filter(
Q(last_consult_date__lt=now-delta_day3)|Q(recv_date__lt=now-delta_day15),status=2).update(
consultant=user_id,last_consult_date = now,recv_date=now
)
if not ret:
return HttpResponse('已经被跟进了') CustomerDistrbute.objects.create(
customer_id=customer_id,consultant_id=user_id,
date=now,status=1,
)
return HttpResponse('跟进成功') def mycustomer(self, request):
user_id = 3 customer_distrubute_list = CustomerDistrbute.objects.filter(consultant_id=user_id) return render(request,'mycustomer.html', locals()) def extra_url(self):
temp = []
temp.append(url(r'^cancel_course/(\d+)/(\d+)', self.cancel_course))
temp.append(url(r'^public/', self.public_customer))
temp.append(url(r'^further/(\d+)', self.further))
temp.append(url(r'^mycustomer/', self.mycustomer))
return temp list_display = ["name", "gender",display_course ,"consultant"] site.register(Customer, CustomerConfig) class ConsultRecordConfig(ModelStark):
list_display = ["customer", 'consultant','date','note'] site.register(ConsultRecord, ConsultRecordConfig) from django.http import JsonResponse
class StudentConfig(ModelStark):
def score_view(self,request,sid):
if request.is_ajax():
# print(request.GET)
cid = request.GET.get('cid')
sid = request.GET.get('sid') # 跨表查
study_record_list = StudyRecord.objects.filter(student=sid,course_record__class_obj=cid) data_list = []
for study_record in study_record_list:
day_num = study_record.course_record.day_num
data_list.append(["day%s"%day_num,study_record.score])
# # [['day94', 85], ['day95', 85], ['day96', -1]]
return JsonResponse(data_list,safe=False) else:
student = Student.objects.filter(pk=sid).first()
class_list = student.class_list.all()
return render(request,'score_view.html', locals()) def extra_url(self):
temp = []
temp.append(url(r"^score_view/(\d+)",self.score_view))
return temp def score_show(self, obj=None, header=False):
if header:
return "查看成绩"
return mark_safe("<a href='score_view/%s'>查看成绩</a>"%obj.pk) list_display = ['customer','class_list',score_show]
list_display_links = ['customer'] site.register(Student,StudentConfig) class CourseRecordConfig(ModelStark): def score(self,request, course_record_id):
if request.method == "POST":
print('post::::', request.POST)
"""
<QueryDict: {'csrfmiddlewaretoken': ['muIrf7pwbxIueSJcKADRlZEGVbzzRZOaiGVkBV8DGYC2V9gmxZtyZgujddFtTojk'],
'score_33': ['100'], 'homework_note_33': ['很好'],
'score_34': ['85'], 'homework_note_34': ['棒'],
'score_35': ['60'], 'homework_note_35': ['None']}>
"""
data = {} # data={"33":{"score":100,"homework_note":'xxx'},}
for key,value in request.POST.items():
if key == "csrfmiddlewaretoken":continue
field, pk = key.rsplit('_', 1) if pk in data:
data[pk][field] = value
else:
data[pk] = {field:value} print("data-->",data)
"""
{'33': {'score': '90', 'homework_note': '很好'},
'34': {'score': '80', 'homework_note': '帮帮哒'},
'35': {'score': '50', 'homework_note': '没问题'}} """
for pk,update_data in data.items():
StudyRecord.objects.filter(pk=pk).update(**update_data) return redirect(request.path) else:
study_record_list = StudyRecord.objects.filter(course_record__id=course_record_id)
score_choices = StudyRecord.score_choices
return render(request,'score.html',locals()) def extra_url(self):
temp = []
temp.append(url(r'^record_score/(\d+)', self.score))
return temp def record(self, obj=None, header=False):
if header:
return "学习记录"
return mark_safe("<a href='/stark/crm/studyrecord/?course_record=%s'>记录</a>"%(obj.pk)) def record_score(self, obj=None, header=False):
if header:
return "录入成绩"
return mark_safe("<a href='record_score/%s'>录入成绩</a>"%obj.pk) list_display = ["class_obj", 'day_num', "teacher", record, record_score ] def patch_studyrecord(self,request,queryset):
# print('queryset:--》',queryset)
temp = []
for course_record in queryset:
# 与course_record 关联得班级对应得学生
students_list = Student.objects.filter(class_list__id = course_record.class_obj.pk)
for student in students_list:
student_obj = StudyRecord(course_record=course_record,student=student)
temp.append(student_obj) StudyRecord.objects.bulk_create(temp) actions = [patch_studyrecord]
patch_studyrecord.short_description = "批量生成学习记录" site.register(CourseRecord,CourseRecordConfig) class StudyRecordConfig(ModelStark):
list_display = ['student','course_record','record','score'] def patch_late(self, request, queryset):
queryset.update(record="late") patch_late.short_description = "迟到"
actions = [patch_late] site.register(StudyRecord,StudyRecordConfig) site.register(Course)
site.register(School) class CustomerDistrbuteConfig(ModelStark):
list_display = ["customer",'consultant','date','status'] site.register(CustomerDistrbute,CustomerDistrbuteConfig)
stark.py
CRM - 销售与客户的更多相关文章
- 3 CRM 销售与客户 我的客户,公共客户池
1.销售与客户的表结构 1.公共客户与我的客户 ---公共客户(公共资源) 1.没有报名 2.3天没有跟进 3.15天没有成单 客户分布表 龙泰 男 yuan 2018-5-1 3天未跟进 龙泰 男 ...
- CRM——销售与客户
一.销售与客户——表结构 1.客户类型 (1)公共客户(公共资源) 必备条件:没有报名: 在必备条件满足的情况下,满足以下任意条件都是公共客户: 3天没有跟进:15天没有成单. (2)我的客户 原销售 ...
- 如何借助CRM销售管理系统提升业绩?
与传统企业销售模式不同,现代企业在网络背书下,销售活动与网络密切相关.销售数据需要网络保存,销售渠道需要网络挖掘.在线的销售软件让销售活动起到了事半功倍的效果.CRM销售管理系统是企业必不可少的在线软 ...
- 企业管理CRM不只是客户录入系统
企业在举办营销活动或者展会之后,将会收集到大量的客户信息,将这些信息有效地整理.完善.储存也是一个不小的工程.如果您的企业经常面遇到这样的情况,不妨使用Zoho CRM系统来帮您完成.但是,Zoho ...
- 【JAVAEE学习笔记】hibernate01:简介、搭建、配置文件详解、API详解和CRM练习:保存客户
今日学习:hibernate是什么 一.hibernate是什么 框架是什么: 1.框架是用来提高开发效率的 2.封装了好了一些功能.我们需要使用这些功能时,调用即可.不需要再手动实现. 3.所以框架 ...
- JAVAEE学习——hibernate01:简介、搭建、配置文件详解、API详解和CRM练习:保存客户
今日学习:hibernate是什么 一.hibernate是什么 框架是什么: 1.框架是用来提高开发效率的 2.封装了好了一些功能.我们需要使用这些功能时,调用即可.不需要再手动实现. 3.所以框架 ...
- crm销售管理系统一
一.环境配置 1.首先配置pip,环境变量配置 pip 9.0.1 from c:\users\administrator\envs\crm\lib\site-packages (python 3.6 ...
- CRM系统对管理客户的帮助
我们可以把客户关系看做是一种长期的投资,在资源有限的基础上,把人力财力物力放到那些能够持续创造价值的客户身上,从而为企业带来源源不断的收益.通过进行客户关系管理,能够让企业与客户之间建立沟通的渠道,形 ...
- Hibernate框架:CRM练习--保存客户
crm:customer ralation manager 客户关系管理系统 一.准备 1.创建web项目 2.导包 最终为: 3.引入静态页面 将文件复制放入项目的WebContent目录下面: 4 ...
随机推荐
- MultiplyVector方法
该方法的功能是用来对方向向量v进行矩阵变换,当矩阵与v进行变换时,只是对v的方向进行转换.那么系统就会对参与变换的Matrix4x4矩阵M进行特殊处理. 例如:经过系统处理后就变为 其中n002 + ...
- Unity+高通Vuforia SDK——AR
一.AR概念: 增强现实(Augmented Reality,简称AR),是在虚拟现实的基础上发展起来的新技术,也被称之为混合现实.是通过计算机系统提供的信息增加用户对现实世界感知的技术,将虚拟的信息 ...
- mybatis由浅入深day01_4.9删除用户_4.10更新用户
4.9 删除用户 4.9.1 映射文件 4.9.2 代码: 控制台: 4.10 更新用户 4.10.1 映射文件 4.10.2 代码 控制台:
- Effective C++ Item 16 Use the same form in corresponding uses of new and delete
1. When you created an array and want to return the memory to system. You need to explicitly add [] ...
- ios 开发之本地推送
网络推送可能被人最为重视,但是本地推送有时候项目中也会运用到: 闲话少叙,代码如下: 1.添加根视图 self.window.rootViewController = [[UINavigationCo ...
- shell基础篇(九)函数
函数可以让我们将一个复杂功能划分成若干模块,让程序结构更加清晰,代码重复利用率更高.像其他编程语言一样,Shell 也支持函数.Shell 函数必须先定义后使用1. Shell 函数的定义格式如下: ...
- Python 入门(六)Dict和Set类型
什么是dict 我们已经知道,list 和 tuple 可以用来表示顺序集合,例如,班里同学的名字: ['Adam', 'Lisa', 'Bart'] 或者考试的成绩列表: [95, 85, 59] ...
- CentOS 6.3下部署LVS(NAT模式)+keepalived实现高性能高可用负载均衡
一.简介 VS/NAT原理图: 二.系统环境 实验拓扑: 系统平台:CentOS 6.3 Kernel:2.6.32-279.el6.i686 LVS版本:ipvsadm-1.26 keepalive ...
- 关于MCU的烧录,下载与其他接口的比较(一)
今天呢,犯了一个很严重的错误,我不知道这会产生什么样的影响,但我知道,如果我以后再没有具体的了解,仔细认真地观察,认证,只会滑到无底的深渊.做技术来不得半点虚假,切记一知半解,凡事都要弄得清楚明白,认 ...
- 说说M451例程讲解之LED
/**************************************************************************//** * @file main.c * @ve ...