zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    Docker-Compose搭建单体SkyWalking 6.2
    Docker搭建MySQL主从集群,基于GTID
    【简记】修改Docker数据目录位置,包含镜像位置
    【拆分版】Docker-compose构建Kibana单实例,基于7.1.0
    【拆分版】Docker-compose构建Logstash多实例,基于7.1.0
    【拆分版】Docker-compose构建Zookeeper集群管理Kafka集群
    命令行模式和python交互模式
    详解 HTTPS、TLS、SSL、HTTP区别和关系
    windows下如何查看进程、端口占用、杀死进程教程
    pycharm最常用的快捷键总结
  • 原文地址:https://www.cnblogs.com/alice-bj/p/9235412.html
Copyright © 2011-2022 走看看