from django.conf import settings from django.contrib import messages from django.core.exceptions import PermissionDenied from django.core.files.base import ContentFile from django.core.mail import send_mail from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from django.core.urlresolvers import reverse from django.db.models import Q from django.http import HttpResponse, HttpResponseForbidden, JsonResponse, Http404 from django.shortcuts import render, get_object_or_404, redirect from django.views.generic import ListView, DetailView, View, UpdateView, CreateView from pprint import pprint, pformat import itertools import json import natsort import pydash as _; _.map = _.map_; _.filter = _.filter_ from .mixins import CheckForUserMixin from .models import User, Team, UserFinancialInfo, ContractorResume, ContractorResumeFiles from .forms import TeamForm, ContractorResumeFilesForm, ContractorResumeForm from archilance import util from archilance.mixins import BaseMixin from projects.forms import PortfolioForm from projects.models import Project, Portfolio from reviews.models import Review from specializations.models import Specialization from work_sell.forms import WorkSellForm from work_sell.models import WorkSell, Picture from .forms import ( ContractorFilterForm, CustomerProfileProjectRealtyForm, UserFinancialInfoEditForm, UserProfileBasicInfoEditForm, UserProfileEditForm, ) class UserProfileEditView(BaseMixin, View): form_class = UserProfileEditForm template_name = 'user_profile_edit.html' def dispatch(self, request, *args, **kwargs): if request.user.is_authenticated() and request.user.pk == int(kwargs.get('pk')): return super().dispatch(request, *args, **kwargs) else: raise PermissionDenied def get(self, request, *args, **kwargs): context = self.get_context_data(**_.merge({}, request.GET, kwargs)) form = self.form_class(request=request, instance=request.user) context.update({'form': form}) return render(request, self.template_name, context) def post(self, request, *args, **kwargs): context = self.get_context_data(**kwargs) specs = request.POST.getlist('contractor_specializations') request.POST.setlist('contractor_specializations', _.compact(specs)) # Ignore empty input values form = self.form_class(request.POST, request.FILES, request=request, instance=request.user) if form.is_valid(): form.save() messages.info(request, 'Пользователь успешно отредактирован') redirect_to = request.POST.get('next') return redirect(redirect_to) else: if form.errors: messages.info(request, ( '

Произошла ошибка (form)

' '
{form}
' ).format(form=pformat(form.errors))) context.update({'form': form}) return render(request, self.template_name, context) class UserFinancialInfoEditView(BaseMixin, View): form_class = UserProfileBasicInfoEditForm fin_info_form_class = UserFinancialInfoEditForm template_name = 'user_financial_info_edit.html' def dispatch(self, request, *args, **kwargs): if request.user.is_authenticated() and request.user.pk == int(kwargs.get('pk')): return super().dispatch(request, *args, **kwargs) else: raise PermissionDenied def get(self, request, *args, **kwargs): context = self.get_context_data(**_.merge({}, request.GET, kwargs)) form = self.form_class(request=request, instance=request.user) fin_info_form = self.fin_info_form_class(request=request, instance=request.user.financial_info, prefix='fin_info') context.update({ 'form': form, 'fin_info_form': fin_info_form, }) return render(request, self.template_name, context) def post(self, request, *args, **kwargs): context = self.get_context_data(**kwargs) specs = request.POST.getlist('contractor_specializations') request.POST.setlist('contractor_specializations', _.compact(specs)) # Ignore empty input values form = self.form_class(request.POST, request.FILES, request=request, instance=request.user) fin_info_form = self.fin_info_form_class(request.POST, request.FILES, request=request, instance=request.user.financial_info, prefix='fin_info') if form.is_valid() and fin_info_form.is_valid(): user = form.save() fin_info = fin_info_form.save() user.financial_info = fin_info user.save() messages.info(request, 'Финансовая информация успешно отредактирована') redirect_to = request.POST.get('next') return redirect(redirect_to) else: if form.errors: messages.info(request, ( '

Произошла ошибка (form)

' '
{form}
' ).format(form=pformat(form.errors))) if fin_info_form.errors: messages.info(request, ( '

Произошла ошибка (fin_info_form)

' '
{form}
' ).format(form=pformat(fin_info_form.errors))) context.update({ 'form': form, 'fin_info_form': fin_info_form, }) return render(request, self.template_name, context) class ContractorFilterView(BaseMixin, View): template_name = 'contractor_filter.html' form_class = ContractorFilterForm def get(self, request, *args, **kwargs): form = self.form_class(request.GET, request=request) context = self.get_context_data(**_.merge({}, request.GET, kwargs)) coll = [] if form.is_valid(): contractors = teams = None contr_count = team_count = None get_contractors = get_teams = None ord = None cro = form.cleaned_data.get('cro') specialization = form.cleaned_data.get('specialization') location = form.cleaned_data.get('location') work_type = form.cleaned_data.get('work_type') build_classif = form.cleaned_data.get('building_classification') constr_type = form.cleaned_data.get('construction_type') party_types = form.cleaned_data.get('party_types') last_party_types = form.cleaned_data.get('last_party_types') if party_types == 'all': get_contractors = get_teams = True elif party_types == 'contractors': get_contractors = True elif party_types == 'teams': get_teams = True elif not party_types: if last_party_types == 'contractors': get_contractors = True elif last_party_types == 'teams': get_teams = True else: get_contractors = get_teams = True if party_types: last_party_types = party_types context.update({'last_party_types': last_party_types}) if get_contractors: contractors = User.contractor_objects.all() if cro: contractors = contractors.filter(cro=cro) if specialization: contractors = contractors.filter( contractor_specializations__lft__gte=specialization.lft, contractor_specializations__rght__lte=specialization.rght, ) if location: contractors = contractors.filter( location__lft__gte=location.lft, location__rght__lte=location.rght, ) if work_type: contractors = contractors.filter(orders__project__work_type=work_type) if build_classif: contractors = contractors.filter(orders__project__realty__building_classification=build_classif) if constr_type: contractors = contractors.filter(orders__project__realty__construction_type=constr_type) if get_teams: teams = Team.objects.all() if cro: teams = teams.filter(Q(contractors__cro=cro) | Q(owner__cro=cro)) if specialization: teams = teams.filter( ( Q(contractors__contractor_specializations__lft__gte=specialization.lft) & Q(contractors__contractor_specializations__rght__lte=specialization.rght) ) | ( Q(owner__contractor_specializations__lft__gte=specialization.lft) & Q(owner__contractor_specializations__rght__lte=specialization.rght) ), ) if location: teams = teams.filter( ( Q(contractors__location__lft__gte=location.lft) & Q(contractors__location__rght__lte=location.rght) ) | ( Q(owner__location__lft__gte=location.lft) & Q(owner__location__rght__lte=location.rght) ), ) if work_type: teams = teams.filter( Q(contractors__orders__project__work_type=work_type) | Q(owner__orders__project__work_type=work_type), ) if build_classif: teams = teams.filter( Q(contractors__orders__project__realty__building_classification=build_classif) | Q(owner__orders__project__realty__building_classification=build_classif), ) if constr_type: teams = teams.filter( Q(contractors__orders__project__realty__construction_type=constr_type) | Q(owner__orders__project__realty__construction_type=constr_type), ) if get_contractors and get_teams: coll = tuple(itertools.chain(contractors.distinct(), teams.distinct())) count = len(coll) display_msg = 'Найдено %s элементов' % count if count > 0 else 'Ничего не найдено' elif get_contractors: coll = contractors.distinct() count = coll.count() display_msg = 'Найдено %s исполнителей' % count if count > 0 else 'Ничего не найдено' elif get_teams: coll = teams.distinct() count = coll.count() display_msg = 'Найдено %s групп' % count if count > 0 else 'Ничего не найдено' order_by = form.cleaned_data.get('order_by') last_order_by = form.cleaned_data.get('last_order_by') reverse_order = form.cleaned_data.get('reverse_order') if order_by: reverse_order = not reverse_order if order_by == last_order_by else False ord = order_by last_order_by = ord elif last_order_by: ord = last_order_by if ord: if ord == 'name': coll = natsort.natsorted(coll, key=lambda obj: getattr(obj, 'username', None) or obj.name, reverse=reverse_order) elif ord =='created': coll = natsort.natsorted(coll, key=lambda obj: obj.created, reverse=reverse_order) context.update({ 'last_order_by': last_order_by, 'reverse_order': reverse_order, }) else: display_msg = 'Пожалуйста, введите корректные данные' if form.errors: messages.info(request, ( '

Произошла ошибка (form)

' '
{form}
' ).format(form=pformat(form.errors))) paginator = Paginator(coll, settings.PAGE_SIZE) page = request.GET.get('page') try: coll = paginator.page(page) except PageNotAnInteger: coll = paginator.page(1) except EmptyPage: coll = paginator.page(paginator.num_pages) context.update({ 'form': form, 'coll': coll, 'is_paginated': True, 'page_obj': coll, 'display_msg': display_msg, }) return render(request, self.template_name, context) class ContractorProfileDetailView(DetailView): model = User worksell_form_class = WorkSellForm portfolio_form_class = PortfolioForm template_name = 'contractor_profile.html' context_object_name = 'contractor' queryset = User.contractor_objects def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['worksell_form'] = self.worksell_form_class context['portfolio_form'] = self.portfolio_form_class resume = self.object.contractor_resume if resume: context['resume_diploms'] = resume.resume_files.filter(type='diplom') context['resume_cro'] = resume.resume_files.filter(type='cro') else: resume = ContractorResume() resume.save() self.object.contractor_resume = resume self.object.save() return context class ContractorOfficeView(DetailView): model = User template_name = 'contractor_office.html' context_object_name = 'contractor' form_class = TeamForm def dispatch(self, request, *args, **kwargs): if request.user.is_authenticated() and request.user.is_contractor() and request.user.pk == int(kwargs.get('pk')): return super().dispatch(request, *args, **kwargs) else: raise PermissionDenied def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) contractor = self.object if util.get_related_or_none(contractor, 'team'): members = contractor.team.contractors.all() context['team_members'] = members context['team_member_count'] = len(members) compl_proj = [] # portfolios = [] # Fetched via DRF # work_sells = [] # Fetched via DRF compl_proj.extend(tuple(o.project for o in contractor.orders.filter(status='completed'))) # portfolios.extend(contractor.portfolios.all()) # work_sells.extend(contractor.work_sell.all()) for c in members: compl_proj.extend(tuple(o.project for o in c.orders.filter(status='completed'))) # portfolios.extend(c.portfolios.all()) # work_sells.extend(c.work_sell.all()) context['completed_project_count'] = len(compl_proj) # context['portfolios'] = portfolios # context['work_sells'] = work_sells context['reviews'] = Review.objects.filter(target_contractor__in=itertools.chain((contractor,), members)) context['form_team'] = self.form_class return context class ContractorOfficeProjectsView(BaseMixin, View): template_name = 'contractor_office_open_projects.html' def dispatch(self, request, *args, **kwargs): if request.user.is_authenticated() and request.user.is_contractor() and request.user.pk == int(kwargs.get('pk')): return super().dispatch(request, *args, **kwargs) else: raise PermissionDenied def get(self, request, *args, **kwargs): context = self.get_context_data(**kwargs) contractor = get_object_or_404(User.contractor_objects, pk=kwargs.get('pk')) context['contractor'] = contractor private_open_projects = tuple(a.project for a in contractor.contractor_answers.filter(project__state='active', rejected=False)) private_archived_projects = tuple(a.project for a in contractor.contractor_answers.filter(project__state='active', rejected=True)) try: team_open_projects = tuple(a.project for a in contractor.team.answers.filter(project__state='active', rejected=False)) team_archived_projects = tuple(a.project for a in contractor.team.answers.filter(project__state='active', rejected=True)) except: team_open_projects = () team_archived_projects = () context['all_project_count'] = \ len(private_open_projects) + len(private_archived_projects) + \ len(team_open_projects) + len(team_archived_projects) context['open_project_count'] = len(private_open_projects) + len(team_open_projects) context['archived_project_count'] = len(private_archived_projects) + len(team_archived_projects) if request.GET.get('owner') == 'private': if request.GET.get('archived') == 'on': projects = private_archived_projects else: projects = private_open_projects elif request.GET.get('owner') == 'teams': if request.GET.get('archived') == 'on': projects = team_archived_projects else: projects = team_open_projects else: if request.GET.get('archived') == 'on': projects = itertools.chain(private_archived_projects, team_archived_projects) else: projects = itertools.chain(private_open_projects, team_open_projects) context['projects'] = projects return render(request, self.template_name, context) class CustomerProfileOpenProjectsView(BaseMixin, View): template_name = 'customer_profile_open_projects.html' form_class = CustomerProfileProjectRealtyForm def get(self, request, *args, **kwargs): context = self.get_context_data(**_.merge({}, request.GET, kwargs)) customer = get_object_or_404(User.customer_objects, pk=kwargs.get('pk')) form = self.form_class(request.GET, request=request, customer=customer) projects = customer.projects.filter(state='active') trashed_projects = customer.projects.filter(state='trashed') if form.is_valid(): realty = form.cleaned_data.get('realty') if realty: projects = projects.filter(realty=realty) trashed_projects = trashed_projects.filter(realty=realty) else: if form.errors: messages.info(request, ( '

Произошла ошибка (form)

' '
{form}
' ).format(form=pformat(form.errors))) paginator = Paginator(projects, settings.PAGE_SIZE) page = request.GET.get('page') try: projects = paginator.page(page) except PageNotAnInteger: projects = paginator.page(1) except EmptyPage: projects = paginator.page(paginator.num_pages) context.update({ 'form': form, 'projects': projects, 'customer': customer, 'open_project_count': projects.paginator.count, 'trashed_project_count': trashed_projects.count(), 'is_paginated': True, 'page_obj': projects, }) return render(request, self.template_name, context) class CustomerProfileTrashedProjectsView(BaseMixin, View): template_name = 'customer_profile_trashed_projects.html' form_class = CustomerProfileProjectRealtyForm def get(self, request, *args, **kwargs): context = self.get_context_data(**_.merge({}, request.GET, kwargs)) customer = get_object_or_404(User.customer_objects, pk=kwargs.get('pk')) form = self.form_class(request.GET, request=request, customer=customer) projects = customer.projects.filter(state='trashed') open_projects = customer.projects.filter(state='active') if form.is_valid(): realty = form.cleaned_data.get('realty') if realty: projects = projects.filter(realty=realty) open_projects = open_projects.filter(realty=realty) else: if form.errors: messages.info(request, ( '

Произошла ошибка (form)

' '
{form}
' ).format(form=pformat(form.errors))) paginator = Paginator(projects, settings.PAGE_SIZE) page = request.GET.get('page') try: projects = paginator.page(page) except PageNotAnInteger: projects = paginator.page(1) except EmptyPage: projects = paginator.page(paginator.num_pages) context.update({ 'form': form, 'projects': projects, 'customer': customer, 'open_project_count': open_projects.count(), 'trashed_project_count': projects.paginator.count, 'is_paginated': True, 'page_obj': projects, }) return render(request, self.template_name, context) class CustomerProfileCurrentProjectsView(BaseMixin, DetailView): model = User template_name = 'customer_profile_current_projects.html' context_object_name = 'customer' def join_user_in_team(request): pass class TeamCreateView(View): form_class = TeamForm def post(self, request, *args, **kwargs): form = self.form_class(request.POST) # import code; code.interact(local=dict(globals(), **locals())) if form.is_valid(): instance = form.save(commit=False) instance.owner = request.user instance.save() return redirect('users:contractor-office', pk=request.user.pk) class ContractorResumeUpdateView(UpdateView): model = ContractorResume form_class = ContractorResumeForm def form_valid(self, form): if self.request.is_ajax(): self.object = form.save() data = { 'text': self.object.text, 'status': 'ok', } return JsonResponse(data) return super().form_valid(form) def form_invalid(self, form): if self.request.is_ajax(): return JsonResponse(form.errors, status=400) return super().form_invalid(form) class ContractorResumeFileCreateView(CreateView): model = ContractorResumeFiles form_class = ContractorResumeFilesForm def form_valid(self, request, form): if self.request.is_ajax(): img_id = request.POST.get('img_id') picture = Picture.objects.get(pk=img_id) temp_file = ContentFile(picture.file.read()) temp_file.name = picture.file.name instance = form.save(commit=False) instance.img = temp_file instance.save() data = { 'pk': instance.pk, 'status': 'ok', } return JsonResponse(data) return super().form_valid(form) def form_invalid(self, form): if self.request.is_ajax(): return JsonResponse(form.errors, status=400) return super().form_invalid(form) def contractor_resumefile_create(request): if request.is_ajax(): form = ContractorResumeFilesForm(data=request.POST) # import code; code.interact(local=dict(globals(), **locals())) if form.is_valid(): # import code; code.interact(local=dict(globals(), **locals())) img_id = request.POST.get('img_id') picture = Picture.objects.get(pk=img_id) temp_file = ContentFile(picture.file.read()) temp_file.name = picture.file.name instance = form.save(commit=False) instance.img = temp_file instance.save() data = {'status': 'ok', 'pk': instance.pk} else: data = {'status': 'no', 'form_errors': form.errors} return HttpResponse(json.dumps(data), content_type='application/json') else: raise Http404 class CustomerProfileReviewsView(BaseMixin, View): template_name = 'customer_profile_reviews.html' def get(self, request, *args, **kwargs): context = self.get_context_data(**_.merge({}, self.request.GET, kwargs)) customer = get_object_or_404(User.customer_objects, pk=self.kwargs['pk']) reviews = Review.objects.filter(target_customer=customer) context.update({ 'reviews': reviews, 'customer': customer, }) return render(request, self.template_name, context) # import code; code.interact(local=dict(globals(), **locals()))