|
|
|
@ -17,18 +17,19 @@ import json |
|
|
|
import natsort |
|
|
|
import natsort |
|
|
|
import pydash as _; _.map = _.map_; _.filter = _.filter_ |
|
|
|
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 .forms import TeamForm, ContractorResumeFilesForm, ContractorResumeForm |
|
|
|
|
|
|
|
from .mixins import CheckForUserMixin |
|
|
|
|
|
|
|
from .models import User, Team, UserFinancialInfo, ContractorResume, ContractorResumeFiles, TeamInvitation |
|
|
|
from archilance import util |
|
|
|
from archilance import util |
|
|
|
from archilance.mixins import BaseMixin |
|
|
|
from archilance.mixins import BaseMixin |
|
|
|
|
|
|
|
from chat.models import Message |
|
|
|
|
|
|
|
from common.mixins import CustomerRequiredMixin, ContractorRequiredMixin, NoCsrfMixin |
|
|
|
from projects.forms import PortfolioForm |
|
|
|
from projects.forms import PortfolioForm |
|
|
|
from projects.models import Project, Portfolio, Order |
|
|
|
from projects.models import Project, Portfolio, Order |
|
|
|
from reviews.models import Review |
|
|
|
from reviews.models import Review |
|
|
|
from specializations.models import Specialization |
|
|
|
from specializations.models import Specialization |
|
|
|
from work_sell.forms import WorkSellForm |
|
|
|
from work_sell.forms import WorkSellForm |
|
|
|
from work_sell.models import WorkSell, Picture |
|
|
|
from work_sell.models import WorkSell, Picture |
|
|
|
from chat.models import Message |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from .forms import ( |
|
|
|
from .forms import ( |
|
|
|
ContractorFilterForm, |
|
|
|
ContractorFilterForm, |
|
|
|
@ -386,9 +387,20 @@ class ContractorProfileView(BaseMixin, DetailView): |
|
|
|
def get_context_data(self, **kwargs): |
|
|
|
def get_context_data(self, **kwargs): |
|
|
|
context = super().get_context_data(**kwargs) |
|
|
|
context = super().get_context_data(**kwargs) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
request_user = self.request.user |
|
|
|
|
|
|
|
contractor = self.object |
|
|
|
|
|
|
|
|
|
|
|
context['worksell_form'] = self.worksell_form_class |
|
|
|
context['worksell_form'] = self.worksell_form_class |
|
|
|
context['portfolio_form'] = self.portfolio_form_class |
|
|
|
context['portfolio_form'] = self.portfolio_form_class |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
display_team_invitation_button = \ |
|
|
|
|
|
|
|
request_user.is_contractor() and \ |
|
|
|
|
|
|
|
contractor != request_user and \ |
|
|
|
|
|
|
|
request_user.has_team() and \ |
|
|
|
|
|
|
|
contractor not in request_user.team.contractors.all() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
context['display_team_invitation_button'] = display_team_invitation_button |
|
|
|
|
|
|
|
|
|
|
|
resume = self.object.contractor_resume |
|
|
|
resume = self.object.contractor_resume |
|
|
|
|
|
|
|
|
|
|
|
if resume: |
|
|
|
if resume: |
|
|
|
@ -432,7 +444,6 @@ class ContractorOfficeView(BaseMixin, DetailView): |
|
|
|
# for c in members: |
|
|
|
# for c in members: |
|
|
|
# compl_proj.extend(tuple(o.project for o in c.orders.filter(status='completed'))) |
|
|
|
# compl_proj.extend(tuple(o.project for o in c.orders.filter(status='completed'))) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
grouped_projects = _get_projects_grouped(contractor) |
|
|
|
grouped_projects = _get_projects_grouped(contractor) |
|
|
|
|
|
|
|
|
|
|
|
private_open_projects = grouped_projects['private_open_projects'] |
|
|
|
private_open_projects = grouped_projects['private_open_projects'] |
|
|
|
@ -447,9 +458,11 @@ class ContractorOfficeView(BaseMixin, DetailView): |
|
|
|
len(private_open_projects) + len(private_archived_projects) + \ |
|
|
|
len(private_open_projects) + len(private_archived_projects) + \ |
|
|
|
len(team_open_projects) + len(team_archived_projects) |
|
|
|
len(team_open_projects) + len(team_archived_projects) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
compl_proj = tuple(o.project for o in team.orders.filter(status='completed')) |
|
|
|
compl_proj = tuple(o.project for o in team.orders.filter(status='completed')) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
team_invitation_exclude_contractor_ids = tuple(itertools.chain((contractor.pk,), tuple(c.pk for c in contractor.team.contractors.all()))) |
|
|
|
|
|
|
|
context['team_invitation_exclude_contractor_ids'] = team_invitation_exclude_contractor_ids |
|
|
|
|
|
|
|
|
|
|
|
context['completed_project_count'] = len(compl_proj) |
|
|
|
context['completed_project_count'] = len(compl_proj) |
|
|
|
context['reviews'] = Review.objects.filter(target_contractor=contractor) |
|
|
|
context['reviews'] = Review.objects.filter(target_contractor=contractor) |
|
|
|
|
|
|
|
|
|
|
|
@ -764,6 +777,7 @@ def contractor_resumefile_create(request): |
|
|
|
else: |
|
|
|
else: |
|
|
|
raise Http404 |
|
|
|
raise Http404 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CustomerProfileReviewsView(BaseMixin, View): |
|
|
|
class CustomerProfileReviewsView(BaseMixin, View): |
|
|
|
template_name = 'customer_profile_reviews.html' |
|
|
|
template_name = 'customer_profile_reviews.html' |
|
|
|
|
|
|
|
|
|
|
|
@ -780,15 +794,35 @@ class CustomerProfileReviewsView(BaseMixin, View): |
|
|
|
|
|
|
|
|
|
|
|
return render(request, self.template_name, context) |
|
|
|
return render(request, self.template_name, context) |
|
|
|
|
|
|
|
|
|
|
|
class AddTeamMember(NoCsrfMixin, LoginRequiredMixin, View): |
|
|
|
|
|
|
|
def post(self, request, *args, **kwargs): |
|
|
|
|
|
|
|
# import code; code.interact(local=dict(globals(), **locals())) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# if request.user.is_contractor()... |
|
|
|
class CreateTeamInvitation(NoCsrfMixin, ContractorRequiredMixin, View): |
|
|
|
# kwargs.get('pk') |
|
|
|
def post(self, request, *args, contractor_id, **kwargs): |
|
|
|
# |
|
|
|
contractor1 = request.user |
|
|
|
|
|
|
|
contractor2 = get_object_or_404(User.contractor_objects, pk=contractor_id) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try: |
|
|
|
|
|
|
|
TeamInvitation.objects.create(contractor1=contractor1, contractor2=contractor2) |
|
|
|
|
|
|
|
return JsonResponse({'status': 'success'}) |
|
|
|
|
|
|
|
except: |
|
|
|
|
|
|
|
return JsonResponse({'status': 'error'}) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class AcceptTeamInvitation(NoCsrfMixin, ContractorRequiredMixin, View): |
|
|
|
|
|
|
|
# TODO: Users can accept invitations by clicking a link, hence the "get": |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get(self, request, *args, owner_id, **kwargs): |
|
|
|
|
|
|
|
contractor1 = get_object_or_404(User.contractor_objects, pk=owner_id) |
|
|
|
|
|
|
|
contractor2 = request.user |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
team_invitation = util.get_or_none(TeamInvitation, contractor1=contractor1, contractor2=contractor2) |
|
|
|
|
|
|
|
team = util.get_related_or_none(contractor1, 'team') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if team_invitation and team: |
|
|
|
|
|
|
|
team.contractors.add(contractor2) |
|
|
|
|
|
|
|
team_invitation.delete() |
|
|
|
return JsonResponse({'status': 'success'}) |
|
|
|
return JsonResponse({'status': 'success'}) |
|
|
|
|
|
|
|
else: |
|
|
|
|
|
|
|
return JsonResponse({'status': 'error'}) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# import code; code.interact(local=dict(globals(), **locals())) |
|
|
|
# import code; code.interact(local=dict(globals(), **locals())) |
|
|
|
|