class ClassListHandler(StarkConfig): def display_course(self, row=None, header=None): if header: return '班级' return "%s %s期" % ( row.course.name, row.semester, ) def display_course_record(self, obj=None, is_header=None, *args, **kwargs): if is_header: return '上课记录' record_url = reverse('stark:web_courserecord_list', kwargs={'class_id': obj.pk}) return mark_safe('<a target="_blank" href="%s">上课记录</a>' % record_url) list_display = [ 'school', display_course, 'price', get_datetime_text('开班日期', 'start_date'), 'tutor', get_m2m_text('任课老师', 'teachers'), display_course_record ] list_filter = [ Option('school'), Option('course'), ] model_form_class = ClassListModelForm
class PrivateCustomerHandler(StarkConfig): model_form_class = PrivateCustomerModelForm def display_record(self, row=None, header=None, *args, **kwargs): if header: return '跟进记录' record_url = reverse('stark:crm_consultrecord_changelist', kwargs={'customer_id': row.pk}) return mark_safe('<a target="_blank" href="%s">跟进记录</a>' % record_url) def display_pay_record(self, row=None, header=None, *args, **kwargs): if header: return '缴费' record_url = reverse('stark:web_paymentrecord_list', kwargs={'customer_id': row.pk}) return mark_safe('<a target="_blank" href="%s">缴费</a>' % record_url) list_display = [ 'name', 'qq', get_m2m_text('咨询课程', 'course'), 'status', display_record, display_pay_record ] def get_queryset(self, request, *args, **kwargs): current_user_id = self.request.session['user_info']['id'] return self.model_class.objects.filter(consultant_id=current_user_id) def record_view(self, request, pk): """ 查看跟进记录的视图 :param request: :param pk: :return: """ record_list = models.ConsultRecord.objects.filter(customer_id=pk) return render(request, 'record_view.html', {'record_list': record_list}) def save(self, form, request, modify=False, *args, **kwargs): if not modify: current_user_id = request.session['user_info']['id'] form.instance.consultant_id = current_user_id form.save() def multi_remove(self, request): ''' 批量移除私有客户 :param request: :return: ''' current_user_id = 1 # 以后要改成取session中获取当前登录用户的ID id_list = request.POST.getlist('pk') models.Customer.objects.filter( id__in=id_list, status=2, consultant_id=current_user_id).update(consultant=None)
class StudentHandler(StarkConfig): model_form_class = StudentModelForm def display_score(self, obj=None, is_header=None, *args, **kwargs): if is_header: return '积分管理' 'web_scorerecord_list' record_url = reverse('stark:web_scorerecord_list', kwargs={'student_id': obj.pk}) return mark_safe('<a target="_blank" href="%s">%s</a>' % (record_url, obj.score)) list_display = [ 'customer', 'qq', 'mobile', 'emergency_contract', get_m2m_text('已报班级', 'class_list'), display_score, 'student_status' ] def get_add_btn(self, request, *args, **kwargs): return None def get_list_display(self): value = [] if self.list_display: value.extend(self.list_display) value.append(type(self).display_edit) return value def get_urls(self): patterns = [ url(r'^list/$', self.wrapper(self.change_view), name=self.get_list_url_name), # url(r'^add/$', self.wrapper(self.add_view), name=self.get_add_url_name), url(r'^change/(?P<pk>\d+)/$', self.wrapper(self.change_view), name=self.get_edit_url_name), # url(r'^delete/(?P<pk>\d+)/$', self.wrapper(self.delete_view), name=self.get_delete_url_name), ] patterns.extend(self.extra_urls()) return patterns search_list = [ 'customer__name', 'qq', 'mobile', ] list_filter = [ Option('class_list', text_func=lambda x: '%s-%s' % (x.school.title, str(x))) ]
class PublicCustomerHandler(StarkConfig): def display_record(self, row=None, header=None): if header: return '跟进记录' record_url = self.reverse_commons_url(self.get_url_name('record_view'), pk=row.pk) return mark_safe('<a href="%s">查看跟进</a>' % record_url) list_display = ['name', 'qq', get_m2m_text('咨询课程', 'course'), display_record, 'status'] model_form_class = PublicCustomerModelForm def get_queryset(self, request, *args, **kwargs): return self.model_class.objects.filter(consultant__isnull=True) def extra_urls(self): patterns = [ url(r'^record/(?P<pk>\d+)/$', self.wrapper(self.record_view), name=self.get_url_name('record_view')), ] return patterns def record_view(self, request, pk): """ 查看跟进记录的视图 :param request: :param pk: :return: """ record_list = models.ConsultRecord.objects.filter(customer_id=pk) return render(request, 'record_view.html', {'record_list': record_list}) def multi_apply(self, request): ''' 批量申请共有客户 :param request: :return: ''' current_user_id = 1 # 以后要改成取session中获取当前登录用户的ID id_list = request.POST.getlist('pk') ''' 开启事务,避免并发时产生的问题 pymsql: select * from crm_custmoer where id in [11,22,33,44] for update; 结束事务 ''' # 获取自己为成单的客户数量 my_customer_count = models.Customer.objects.filter(consultant_id=current_user_id, status=2).count() if my_customer_count + len(id_list) > settings.PRIVATE_CUSTOMER: return HttpResponse('超过客户最大限制!') # 使用django orm加锁 flag = False with transaction.atomic(): origin = models.Customer.objects.filter(id__in=id_list, consultant__isnull=True, status=2).select_for_update() # 申请的数量要与公户查询到的数量相等 if origin.count() == len(id_list): # 可以申请 models.Customer.objects.filter(id__in=id_list).update(consultant_id=current_user_id) flag = True if not flag: return HttpResponse('已被其他顾问申请') multi_apply.text = "申请到我的私户" action_list = [multi_apply]
class PublicCustomerHandler(PermissionHandler, StarkHandler): """ stark配置:客户表(公有) """ # 获取自定义ModelForm model_form_class = PublicCustomerModelForm def display_record(self, obj=None, is_header=None, *args, **kwargs): """ 自定义跟进记录显示列 :param obj: 选则的客户对象 :param is_header: :return: """ if is_header: return '跟进记录' record_url = self.reverse_commons_url(self.get_url_name('record_view'), pk=obj.pk) return mark_safe('<a class="text-info" href="%s">查看</a>' % record_url) # 页面显示列:复选框|姓名|联系方式|咨询课程|状态|跟进记录 list_display = [ StarkHandler.display_checkbox, 'name', 'qq', get_m2m_text('咨询课程', 'course'), get_choice_text('状态', 'status'), display_record, ] def extra_urls(self): """ 预留钩子:新增URL :return: """ patterns = [ re_path(r'^record/(?P<pk>\d+)/$', self.wrapper(self.record_view), name=self.get_url_name('record_view')), ] return patterns def get_queryset(self, request, *args, **kwargs): """ 预留钩子:获取没有课程顾问的客户(公有客户) :param request: :param args: :param kwargs: :return: """ return self.model_class.objects.filter(consultant__isnull=True) def record_view(self, request, pk): """ 视图函数:查看跟进记录 :param request: :param pk: 要查看的客户的id :return: """ record_list = models.ConsultRecord.objects.filter(customer_id=pk) return render(request, 'record_view.html', {'record_list': record_list}) def action_multi_apply(self, request, *args, **kwargs): """ 批量操作:公户到私户 :param request: :param args: :param kwargs: :return: """ current_user_id = request.session['user_info']['id'] pk_list = request.POST.getlist('pk') # 私户个数限制 private_customer_count = models.Customer.objects.filter(consultant_id=current_user_id, status=2).count() if (private_customer_count + len(pk_list)) > models.Customer.MAX_PRIVATE_CUSTOMER_COUNT: return HttpResponse('做人不要太贪心,私户中已有%s个客户,最多还能申请%s' % ( private_customer_count, models.Customer.MAX_PRIVATE_CUSTOMER_COUNT - private_customer_count)) # 数据库中加锁 flag = False with transaction.atomic(): # 事务 # 在数据库中加锁,销售选定的客户中有已报名的、或被其他销售抢先的,则不允许添加 origin_queryset = models.Customer.objects.filter(id__in=pk_list, status=2, consultant__isnull=True).select_for_update() if len(origin_queryset) == len(pk_list): models.Customer.objects.filter(id__in=pk_list, status=2, consultant__isnull=True).update(consultant_id=current_user_id) flag = True if flag: # 添加成功刷新页面 return redirect(self.memory_reverse()) else: return HttpResponse('手速太慢了,选中的客户已被其他人申请,请重新选择') action_multi_apply.text = "添加到私户" # 批量操作:删除|公户到私户 action_list = [StarkHandler.action_multi_delete, action_multi_apply, ]
class ClassListHandler(PermissionHandler, StarkHandler): """ stark配置:班级表 """ # 获取自定义ModelForm model_form_class = ClassListModelForm def display_course(self, obj=None, is_header=None): """ 自定义的班级的显示列 :param obj: 当前记录对象 :param is_header: 是否是表头 :return: """ if is_header: return '班级' return "%s(%s期)" % ( obj.course.name, obj.semester, ) def display_course_record(self, obj=None, is_header=None, *args, **kwargs): """ 自定义的上课记录显示列 :param obj: :param is_header: :param args: :param kwargs: :return: """ if is_header: return '上课记录' record_url = reverse('stark:web_courserecord_list', kwargs={'class_id': obj.pk}) return mark_safe('<a href="%s">查看</a>' % record_url) # 页面显示列:校区|班级|学费|开班日期|班主任|任课老师|上课记录 list_display = [ 'school', display_course, 'price', get_datetime_text('开班日期', 'start_date'), 'class_teacher', get_m2m_text('任课老师', 'tech_teachers'), ] def get_list_display(self, request, *args, **kwargs): """ 预留钩子:增加自定义的上课记录显示列 :return: """ value = [] if self.list_display: value.extend(self.list_display) value.append(type(self).display_course_record) return value # 允许的组合搜索条件:学校|课程 search_group = [ Option('school'), Option('course'), ]
class StudentHandler(PermissionHandler, StarkHandler): """ 学生表:stark配置 """ # 获取自定义ModelForm model_form_class = StudentModelForm def display_score(self, obj=None, is_header=None, *args, **kwargs): """ 自定义的学生积分显示列 :param obj: :param is_header: :return: """ if is_header: return '积分管理' record_url = reverse('stark:web_scorerecord_list', kwargs={'student_id': obj.pk}) return mark_safe('<a href="%s">%s</a>' % (record_url, obj.score)) # 页面展示列:客户信息|QQ号|手机号|紧急联系人电话|已报班级|状态|积分管理|编辑 list_display = [ 'customer', 'qq', 'mobile', 'emergency_contract', get_m2m_text('已报班级', 'class_list'), get_choice_text('状态', 'student_status'), display_score, ] def get_list_display(self, request, *args, **kwargs): """ 预留钩子:进展示编辑列 :return: """ value = [] if self.list_display: value.extend(self.list_display) value.append(type(self).display_edit) return value def get_urls(self): """ 预留钩子:重写URL(学生信息不允许被增删) :return: """ patterns = [ re_path(r'^list/$', self.wrapper(self.list_view), name=self.get_list_url_name), re_path(r'^edit/(?P<pk>\d+)/$', self.wrapper(self.edit_view), name=self.get_edit_url_name), ] patterns.extend(self.extra_urls()) return patterns # 添加按钮配置:取消 has_add_btn = False # 允许的条件搜索范围:姓名|qq|电话 search_list = [ 'customer__name', 'qq', 'mobile', ] # 允许的组合搜索条件:班级 search_group = [ Option('class_list', text_func=lambda x: '%s-%s' % (x.school.title, str(x))) ]
class PrivateCustomerHandler(PermissionHandler, StarkHandler): """ stark配置:客户表(私有) """ # 获取自定义ModelForm model_form_class = PrivateCustomerModelForm def display_record(self, obj=None, is_header=None, *args, **kwargs): """ 自定义跟进记录显示列 :param obj: 选择的客户对象 :param is_header: :return: """ if is_header: return '跟进记录' record_url = reverse('stark:web_consultrecord_list', kwargs={'customer_id': obj.pk}) return mark_safe('<a href="%s">管理</a>' % record_url) def display_pay_record(self, obj=None, is_header=None, *args, **kwargs): """ 自定义缴费显示列 :param obj: :param is_header: :param args: :param kwargs: :return: """ if is_header: return '缴费' record_url = reverse('stark:web_paymentrecord_list', kwargs={'customer_id': obj.pk}) return mark_safe('<a href="%s">管理</a>' % record_url) # 页面显示列:复选框|姓名|联系方式|咨询课程|状态|跟进记录|缴费 list_display = [ StarkHandler.display_checkbox, 'name', 'qq', get_m2m_text('咨询课程', 'course'), get_choice_text('状态', 'status'), display_record, display_pay_record, ] def get_queryset(self, request, *args, **kwargs): """ 预留钩子:获取当前用户的私有客户 :param request: :param args: :param kwargs: :return: """ current_user_id = request.session['user_info']['id'] return self.model_class.objects.filter(consultant_id=current_user_id) def save(self, request, form, is_update, *args, **kwargs): """ 钩子方法:保存前设置默认课程顾问为当前登录用户 :param request: :param form: :param is_update: :param args: :param kwargs: :return: """ if not is_update: current_user_id = request.session['user_info']['id'] form.instance.consultant_id = current_user_id form.save() def action_multi_remove(self, request, *args, **kwargs): """ 批量操作:私户到公户 :return: """ current_user_id = request.session['user_info']['id'] pk_list = request.POST.getlist('pk') self.model_class.objects.filter( id__in=pk_list, consultant_id=current_user_id).update(consultant=None) return redirect(self.memory_reverse(*args, **kwargs)) action_multi_remove.text = "移除到公户" # 批量操作:删除|私户到公户 action_list = [StarkHandler.action_multi_delete, action_multi_remove]