wushaodong 4 years ago
parent
commit
6c77018452

+ 10 - 0
apps/account/models.py

@@ -115,6 +115,16 @@ class User(AbstractBaseUser, PermissionsMixin):
                 users.append(store.manage_user.id)
         return list(set(users))
 
+    def get_office_stores(self):
+        # 人员任职门店
+        stores = []
+        users = OfficeStoreUser.objects.filter(office_user=self)
+        for user in users:
+            stores.append(user.store.id)
+        if self.store:
+            stores.append(self.store.id)
+        return list(set(stores))
+
     def change_password(self, new_password, confirm_password, old_password):
         if new_password != confirm_password:
             raise CustomError(u'两次输入的密码不一致,请检查')

+ 1 - 1
apps/account/urls.py

@@ -11,7 +11,7 @@ urlpatterns = [
     url(r'^permission/dict/$', PermissionDictView.as_view()), # 人员管理,编辑,权限组
     url(r'^permission/all/$', PermissionsListView.as_view()), # 权限管理,编辑,加载所有权限
     url(r'^store/tree/$', StoreTreeView.as_view()), # 人员管理,管理门店,加载门店
-    url(r'^employee_tree/$', EmployeeTreeView.as_view()), #人员列表
+    url(r'^employee_tree/$', EmployeeTreeView.as_view()), #提醒人员列表
     url(r'^office_store/$', OfficeStoreView.as_view()), # 任职门店
 ]
 

+ 24 - 2
apps/account/views.py

@@ -1,6 +1,7 @@
 # coding=utf-8
 import traceback
 import json
+import datetime
 from django.db.models import Q
 from rest_framework.decorators import action
 from django.db import transaction
@@ -23,7 +24,7 @@ from apps.account.consts import PermissionMenu
 from collections import OrderedDict
 from apps.agent.models import Store, Agent,GeneralAgent
 from utils.exceptions import CustomError
-from apps.customer.models import ReportCustomer
+from apps.customer.models import ReportCustomer, NewCustomerRemind, NewCustomer
 
 class LoginView(ObtainJSONWebToken):
     serializer_class = JWTSerializer
@@ -152,6 +153,24 @@ class EmployeeViewSet(CustomModelViewSet):
                 ManageStoreUser.objects.filter(manage_user_id=pk).delete()
                 for row in data:
                     ManageStoreUser.objects.create(store_id=row, manage_user_id=pk)
+
+                # 给员工设置管理门店,把已取消管理门店下面的客户提醒删除
+                user = User.objects.filter(id=pk).first()
+                data.extend(user.get_office_stores())
+                # 删除不管理的门店提醒
+                NewCustomerRemind.objects.filter(remind_user=user).exclude(store__in=data).delete()
+                # 根据选择的人员所管理店面,创建内部跟踪提醒
+                #  把next_time用当前日期加上5天
+                if user.has_perm('customer.inner_review'):
+                    next_time = (timezone.now() + datetime.timedelta(days=5)).strftime('%Y-%m-%d')
+                    for store in data:
+                        customers = NewCustomer.objects.filter(store_id=store, status=NewCustomer.NORMAL).values('id')
+                        for customer in customers:
+                            remind = NewCustomerRemind.objects.filter(customer_id=customer['id'],remind_user_id=pk,store_id=store).first()
+                            if not remind:
+                                NewCustomerRemind.objects.create(customer_id=customer['id'], next_time=next_time, remind_user_id=pk,
+                                                         is_employee=False, store_id=store)
+
                 BizLog.objects.addnew(self.request.user, BizLog.INSERT,
                                       u'设置账号[%s]管理门店,id=%d' % (instance.username, instance.id), data)
             return response_ok()
@@ -169,6 +188,9 @@ class EmployeeViewSet(CustomModelViewSet):
                 OfficeStoreUser.objects.filter(office_user_id=pk).delete()
                 for row in data:
                     OfficeStoreUser.objects.create(store_id=row, office_user_id=pk)
+                # 删除不任职门店提醒
+                data.extend(instance.get_office_stores())
+                NewCustomerRemind.objects.filter(remind_user=instance).exclude(store__in=data).delete()
                 BizLog.objects.addnew(self.request.user, BizLog.INSERT,
                                       u'设置账号[%s]任职门店,id=%d' % (instance.username, instance.id), data)
             return response_ok()
@@ -331,7 +353,7 @@ class EmployeeTreeView(APIView):
             for employee in employees:
                 user_item = {
                     'title': employee['name'],
-                    'id': employee['id'],
+                    'id': '{0}_{1}'.format(store_id, employee['id']),# 门店_人员
                     'field': 'user',
                 }
                 store_item['children'].append(user_item)

+ 2 - 1
apps/customer/filters.py

@@ -24,7 +24,8 @@ class NewCustomerFilter(django_filters.FilterSet):
         if param[0] == 'store':
             queryset = queryset.filter(store_id=param[1])
         elif param[0] == 'user':
-            customer_ids = NewCustomerRemind.objects.filter(remind_user_id=param[1]).values_list('customer_id',flat=True)
+            # param=user_1_51 门店id_用户id
+            customer_ids = NewCustomerRemind.objects.filter(remind_user_id=param[2], store_id=param[1] ).values_list('customer_id',flat=True)
             queryset = queryset.filter(id__in=customer_ids)
         elif param[0] == 'agent':
             queryset = queryset.filter(store__agent_id=param[1])

+ 4 - 0
apps/customer/models.py

@@ -52,9 +52,11 @@ class ReportCustomer(models.Model):
 class NewCustomer(models.Model):
     NORMAL = 1
     ABANDONED = 2
+    DEAL = 3
     STATUS_CHOICES = (
         (NORMAL, u'正常'),
         (ABANDONED, u'放弃'),
+        (DEAL, u'成交'),
     )
     name = models.CharField(max_length=20, verbose_name=u"姓名")
     tel = models.CharField(max_length=15, verbose_name=u'电话')
@@ -99,6 +101,8 @@ class NewCustomerRemind(models.Model):
     remind_user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=u'提醒人', related_name='remind_user',
                                    editable=False, on_delete=models.PROTECT)
     is_employee = models.BooleanField(verbose_name=u'是否业务员', default=True)
+    store = models.ForeignKey(Store, verbose_name=u'门店', related_name='customer_remind_store',
+                              editable=False, on_delete=models.PROTECT)
 
     class Meta:
         db_table = 'new_customer_remind'

+ 1 - 0
apps/customer/serializers.py

@@ -120,6 +120,7 @@ class NewCustomerSerializer(serializers.ModelSerializer):
                                            read_only=True)
     next_time_f = DateCharField(source='next_time', read_only=True)
 
+    store_text = serializers.CharField(source='store.name', read_only=True)
     source_text = serializers.CharField(source='source.name', read_only=True)
     gender_text = serializers.SerializerMethodField()
     project_text = serializers.SerializerMethodField()

+ 18 - 14
apps/customer/views.py

@@ -77,7 +77,7 @@ class ReportCustomerViewSet(CustomModelViewSet):
                 instance.check_time = timezone.now()
                 instance.save()
                 BizLog.objects.addnew(request.user, BizLog.INSERT,
-                                      u'分配客户报备[%s],id=%d' % (instance.name, instance.id))
+                                      u'分配客户报备[%s],id=%d' % (instance.name, instance.id), user_id)
                 # 创建潜客跟踪表
                 stage_progress = Option.objects.filter(type=Option.STAGE_PROGRESS, enable=True).order_by('sort').first()
                 if not stage_progress.track_day:
@@ -94,14 +94,16 @@ class ReportCustomerViewSet(CustomModelViewSet):
                 projects = instance.project.all()
                 for project in projects:
                     customer.project.add(project.id)
-                NewCustomerRemind.objects.create(customer=customer, next_time=next_time, remind_user_id=user_id,)
+                NewCustomerRemind.objects.create(customer=customer,store=customer.store, next_time=next_time, remind_user_id=user_id,)
                 # 根据分配人所在店面,创建内部跟踪提醒
                 remind_users = request.user.get_remind_users()
+                # 跟踪人和提醒人是同一个人的,不需要在加提醒
+                remind_users.remove(int(user_id))
                 #  把next_time用当前日期加上5天
                 next_time = (timezone.now() + datetime.timedelta(days=5)).strftime('%Y-%m-%d')
                 for remind_user in remind_users:
                     NewCustomerRemind.objects.create(customer=customer, next_time=next_time, remind_user_id=remind_user,
-                                                     is_employee=False)
+                                                     is_employee=False, store=instance.store)
         except CustomError as e:
             return response_error(e.get_error_msg())
         except Exception as e:
@@ -355,9 +357,9 @@ class NewCustomerViewSet(CustomModelViewSet):
                 instance.save()
                 #  把原跟踪人提醒更新为新的跟踪人
                 NewCustomerRemind.objects.filter(customer=instance, remind_user=old_track_user).update(
-                                            next_time=next_time,remind_user=track_user_id)
+                                            next_time=next_time,track_user_id=track_user_id)
                 BizLog.objects.addnew(request.user, BizLog.INSERT,
-                                      u'重新分配客户经理[%s]为%s,id=%d' % (instance.name,track_user_id, instance.id))
+                                      u'重新分配客户经理[%s]为%s,id=%d' % (instance.name,track_user_id, instance.id), track_user_id)
 
         except CustomError as e:
             return response_error(e.get_error_msg())
@@ -373,6 +375,7 @@ class StageCountView(APIView):
     def get(self, request):
         type = request.query_params.get('type') or 'user'
         id = request.query_params.get('id') or request.user.id
+
         data = []
         stage_progress = Option.objects.filter(type=Option.STAGE_PROGRESS, enable=True).order_by('sort').values('id','name')
         time_now = timezone.now().strftime('%Y-%m-%d')
@@ -380,18 +383,19 @@ class StageCountView(APIView):
             # 查询正常状态客户
             reminds = NewCustomerRemind.objects.filter(customer__stage_progress=stage['id'], customer__status=NewCustomer.NORMAL)
             if type == 'store':
-                reminds = reminds.filter(customer__store_id=id, is_employee=True)
+                reminds = reminds.filter(store_id=id, is_employee=True)
             elif type == 'user':
-                reminds = reminds.filter(remind_user_id=id)
+                try:
+                    # 默认登录人没有门店,
+                    user_id = id.split('_')[1]
+                    store_id = id.split('_')[0]
+                    reminds = reminds.filter(remind_user_id=user_id, store_id=store_id)
+                except:
+                    reminds = reminds.filter(remind_user_id=id)
             elif type == 'agent':
-                reminds = reminds.filter(customer__store__agent_id=id, is_employee=True)
+                reminds = reminds.filter(store__agent_id=id, store_id__in=request.user.get_manager_range(), is_employee=True)
             elif type == 'general_agent':
-                reminds = reminds.filter(customer__store__agent__general_agent_id=id, is_employee=True)
-
-            # new_customers = NewCustomer.objects.filter(
-            #     Q(track_user=user) |
-            #     Q(track_user__store_id__in=request.user.get_manager_range()),
-            #     stage_progress=stage['id'])
+                reminds = reminds.filter(store__agent__general_agent_id=id, store_id__in=request.user.get_manager_range(), is_employee=True)
 
             stage_count = {
                 'stage_id': stage['id'],  # 阶段id

+ 1 - 1
apps/order/views.py

@@ -106,7 +106,7 @@ class OrderViewSet(CustomModelViewSet):
                     next_time=next_time,
                 )
                 if not stage_progress.end_stage:
-                    NewCustomerRemind.objects.create(customer=order.customer, remind_user_id=service, next_time=next_time)
+                    NewCustomerRemind.objects.create(customer=order.customer, store=order.customer.store, remind_user_id=service, next_time=next_time)
                 operation = u'分配服务人员为:{}'.format(order.service_user.name)
                 ProgressDetails.objects.create(order=order, user=request.user, operation=operation,)
         except CustomError as e:

+ 8 - 8
decorate/settings.py

@@ -127,14 +127,14 @@ DATABASES = {
         'HOST': '192.168.2.45',
         'PORT': 3306,
     },
-    # 'default': {
-    #     'ENGINE': 'django.db.backends.mysql',
-    #     'NAME': 'baoxiu',
-    #     'USER': 'baoxiu',
-    #     'PASSWORD': 'baoxiu!@#',
-    #     'HOST': '106.12.149.71',
-    #     'PORT': 3306,
-    # }
+    'default33': {
+        'ENGINE': 'django.db.backends.mysql',
+        'NAME': 'decorate',
+        'USER': 'carwin',
+        'PASSWORD': 'carwin!@#',
+        'HOST': '39.106.109.89',
+        'PORT': 3306,
+    }
 }
 
 # Password validation

+ 9 - 5
uis/views/customer/add_report.html

@@ -62,7 +62,7 @@
                         <div class="layui-hide" id="next_time_div">
                             <label class="layui-form-label"><font color='red' size="4">*</font>下次回访:</label>
                             <div class="layui-input-block">
-                                <input type="text" name="next_time" class="layui-input" id="next_time" lay-verify="required"
+                                <input type="text" name="next_time" class="layui-input" id="next_time"
                                        placeholder="修改下次回访日期">
                             </div>
                         </div>
@@ -93,17 +93,21 @@
         var customer_id = layui.view.getParameterByName('customer_id');
         // 自定义进度的排序,只有排序为1的,是潜客,可以修改客户等级
         var stage_progress_sort = layui.view.getParameterByName('stage_progress_sort');
-        if(stage_progress_sort && parseFloat(stage_progress_sort) === 1){
+        if (stage_progress_sort && parseFloat(stage_progress_sort) === 1) {
             $('#next_time_div').removeClass('layui-hide')
         }
 
         form.on('submit(component-form-element)', function (data) {
-            if(data.field.is_giveup === "1" && !data.field.instruction){
-                layer.msg('请填写放弃原因!',{icon: 2})
+            if (data.field.is_giveup === "1" && !data.field.instruction) {
+                layer.msg('请填写放弃原因!', {icon: 2})
+                return false
+            }
+            if (stage_progress_sort && parseFloat(stage_progress_sort) === 1 && !data.field.next_time) {
+                layer.msg('请选择下次回访日期!', {icon: 2})
                 return false
             }
             admin.req({
-                url: '/customer/new_customer/'+customer_id+'/add_review/'
+                url: '/customer/new_customer/' + customer_id + '/add_review/'
                 , data: data.field
                 , type: 'post'
                 , done: function (res) {

+ 2 - 2
uis/views/customer/check_index.html

@@ -74,7 +74,7 @@
                             <div class="seach_items">
                                 <select name="check_status">
                                      <option value="">请选择审核状态</option>
-                                     <option value="0">未审核</option>
+                                     <option value="0" selected>未审核</option>
                                      <option value="1">继续跟踪</option>
                                      <option value="2">放弃</option>
                                  </select>
@@ -109,7 +109,7 @@
 
         table.render({
             elem: '#customer_datagrid'
-            , url: '/customer/review/'
+            , url: '/customer/review/?check_status=0'
             , cols: [[
                 {field: 'name', title: '姓名', width: 100}
                 , {field: 'tel', title: '电话', width: 130}

+ 2 - 1
uis/views/customer/index.html

@@ -211,10 +211,11 @@
                 , {field: 'village', title: '小区', width: 150}
                 , {field: 'address', title: '地址', width: 200}
                 , {field: 'source_text', title: '来源', width: 100}
-                , {field: 'project_text', title: '项目', width: 100}
+                , {field: 'project_text', title: '项目', width: 150}
                 , {field: 'stage_progress_text', title: '阶段进度', width: 100}
                 , {field: 'status_text', title: '状态', width: 60}
                 , {field: 'track_user_text', title: '跟踪人', width: 120}
+                , {field: 'store_text', title: '门店', width: 150}
                 , {field: 'end_time_f', title: '最后跟踪时间', width: 150}
                 , {field: 'last_review', title: '最后跟踪情况', width: 200}
                 , {field: 'next_time_f', title: '下次跟踪时间', width: 120}

+ 0 - 235
uis/views/new_customer/index.html

@@ -1,235 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-    <meta charset="utf-8">
-    <title>客户报备</title>
-    <meta name="renderer" content="webkit">
-    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
-    <meta name="viewport"
-          content="width=customer-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
-    <link rel="stylesheet" href="../../layuiadmin/layui/css/layui.css" media="all">
-    <link rel="stylesheet" href="../../layuiadmin/style/admin.css" media="all">
-    <style type="text/css">
-        .seach_items {
-            float: right;
-            margin-left: 10px;
-        }
-    </style>
-    <style type="text/css">
-        .LAY-btns .layui-nav {
-            padding-left: 0;
-            padding-right: 10px;
-            top: -4px;
-            margin: 0 10px;
-            border: 0;
-            background-color: #009688;
-        }
-
-        .LAY-btns .layui-nav .layui-nav-item {
-            line-height: 40px;
-        }
-
-        .LAY-btns .layui-nav .layui-nav-child {
-            top: 34px;
-        }
-
-        .LAY-btns .layui-nav .layui-nav-bar {
-            display: none;
-        }
-
-        .LAY-btns .layui-nav .layui-nav-child dd.layui-this a {
-            color: #333;
-            background-color: #fff;
-        }
-
-        .LAY-btns .layui-nav .layui-nav-child dd.layui-this a:hover {
-            background-color: #f2f2f2;
-            color: #000;
-        }
-    </style>
-
-</head>
-<body>
-
-<div class="layui-fluid">
-    <div class="layui-card">
-        <div class="layui-card-body" pad15>
-            <div class="layui-row layui-col-space15">
-                <div class="layui-col-md12">
-                    <div class="LAY-btns" style="margin-bottom: 10px;">
-                        <div style="float: left">
-                            <button class="layui-btn" id="customer_add" data-permission="customer.add_report_customer"><i
-                                    class="layui-icon layui-icon-add-circle"></i>添加
-                            </button>
-                        </div>
-                        <form class="layui-form" lay-filter="query-form-element1">
-                            <div class="seach_items">
-                                <button class="layui-btn" lay-submit lay-filter="query-form-element1"><i
-                                        class="layui-icon layui-icon-search"></i>查询
-                                </button>
-                            </div>
-                            <div class="seach_items">
-                                <select name="source" id="id_source" style="width: 40px;">
-                                    <option value="">请选择来源</option>
-                                </select>
-                            </div>
-                            <div class="seach_items">
-                                <input type="text" name="name" autocomplete="off" class="layui-input"
-                                       placeholder="姓名"/>
-                            </div>
-                        </form>
-                        <div style="clear: both;"></div>
-                    </div>
-                    <table class="layui-hide" id="customer_datagrid" lay-filter="customer-operate"></table>
-
-                    <script type="text/html" id="customer-operate-bar">
-                        <div class="layui-btn-group">
-                            <a class="layui-btn layui-btn-xs" lay-event="customer_edit"
-                               data-permission="customer.add_report_customer"
-                            >修改</a>
-                        </div>
-                        <div class="layui-btn-group">
-                            <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="customer_del"
-                               data-permission="customer.delete_report_customer"
-                            >删除</a>
-                        </div>
-                    </script>
-                </div>
-            </div>
-        </div>
-    </div>
-</div>
-<script src="../../layuiadmin/layui/layui.js?t=1"></script>
-<script>
-    layui.config({
-        base: '../../../layuiadmin/' //静态资源所在路径
-    }).extend({
-        index: 'lib/index' //主入口模块
-    }).use(['index', 'table', 'form',], function () {
-        var $ = layui.$;
-        var table = layui.table
-            , form = layui.form
-            , admin = layui.admin;
-
-        table.render({
-            elem: '#customer_datagrid'
-            , url: '/customer/report_customer/'
-            , cols: [[
-                {field: 'name', title: '姓名', width: 120}
-                , {field: 'gender_text', title: "性别", width: 70}
-                , {field: 'tel', title: '电话', width: 120}
-                , {field: 'village', title: '小区', width: 150}
-                , {field: 'address', title: '地址', width: 200}
-                , {field: 'source_text', title: '来源', width: 100}
-                , {field: 'project_text', title: '项目', width: 200}
-                , {field: 'notes', title: '备注', width: 200}
-                , {field: 'report_status_text', title: '报备状态', width: 100}
-                , {field: 'check_user_text', title: '审核人', width: 100}
-                , {field: 'check_time', title: '审核时间', width: 160}
-                , {width: 130, align: 'center', fixed: 'right', toolbar: '#customer-operate-bar'}
-            ]]
-            , page: true
-            , height: 'full-108'
-        });
-
-        admin.req({
-            url: '/customer/dict/',
-            done: function (res) {
-                var data = res.data.source;
-                var source_node = $('#id_source');
-                for (var i in data) {
-                    var pid = data[i].id;
-                    var name = data[i].name;
-                    source_node.append("<option value='" + pid + "'>" + name + "</option>");
-                }
-                form.render('select');
-            }
-        });
-
-        //监听工具条
-        table.on('tool(customer-operate)', function (obj) {
-            var data = obj.data;
-            if (obj.event === 'customer_del') {
-                if(data.report_status !== 0){
-                    layer.msg("只有待审核才允许删除");
-                    return
-                }
-                layer.confirm('确定要删除吗?', function (index) {
-                    layer.close(index);
-                    admin.req({
-                        url: '/customer/report_customer/' + data.id + '/'
-                        , type: 'delete'
-                        , done: function (res) {
-                            if(res.code === 0){
-                                layer.msg('删除成功!', {icon: 1})
-                             }
-                            table.reload('customer_datagrid', {});
-                        }
-                    });
-                });
-            } else if (obj.event === 'customer_edit') {
-                if(data.report_status !== 0){
-                    layer.msg("只有待审核才允许修改");
-                    return
-                }
-                table.editdata = data;
-                layer.open({
-                    type: 2,
-                    title: '修改',
-                    shadeClose: false,
-                    area: ['45%', '80%'],
-                    btn: ['保存', '取消'],
-                    yes: function (index, dom) {
-                        layui.onSubmitChild = function (res) {
-                            if(res.code === 0){
-                                layer.msg('修改成功!', {icon: 1})
-                             }
-                            layer.close(index);
-                            table.reload('customer_datagrid', {});
-                        };
-                        layui.submitChild();
-                    },
-                    btn2: function (index, layero) {
-                        layer.close(index);//关闭当前按钮
-                    },
-                    content: 'edit.html?id=' + data.id
-                });
-            }
-        });
-
-        form.on('submit(query-form-element1)', function (data) {
-            table.reload('customer_datagrid', {
-                where: data.field
-                , page: {curr: 1}
-            });
-            layer.closeAll();
-            return false
-        });
-
-        $('#customer_add').on('click', function () {
-            layer.open({
-                type: 2,
-                title: '添加',
-                area: ['45%', '80%'],
-                btn: ['保存', '取消'],
-                yes: function (index, dom) {
-                    layui.onSubmitChild = function (res) {
-                        if(res.code === 0){
-                            layer.msg('添加成功!', {icon: 1})
-                        }
-                        layer.close(index);
-                        table.reload('customer_datagrid', {});
-                    };
-                    layui.submitChild();
-                },
-                btn2: function (index, layero) {
-                    layer.close(index);//关闭当前按钮
-                },
-                content: 'edit.html'
-            });
-        });
-    });
-
-</script>
-</body>
-</html>