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>&nbsp;"%(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
原文地址:https://www.cnblogs.com/alice-bj/p/9235412.html