diff --git a/projects/forms.py b/projects/forms.py index a94c7cd..2e7a293 100644 --- a/projects/forms.py +++ b/projects/forms.py @@ -168,18 +168,40 @@ class ContractorProjectAnswerForm(forms.ModelForm): class Meta: model = Answer + # ('author', 'Relation? True', 'Null? None', 'Blank? None'), + # ('content_type', 'Relation? True', 'Null? False', 'Blank? False'), + # ('portfolios', 'Relation? True', 'Null? False', 'Blank? True'), + # ('project', 'Relation? True', 'Null? False', 'Blank? False'), + # + # ('candidates', 'Relation? True', 'Null? True', 'Blank? None'), + # ('files', 'Relation? True', 'Null? True', 'Blank? None'), + # + # + # ('budget', 'Relation? False', 'Null? False', 'Blank? False'), + # ('created', 'Relation? False', 'Null? False', 'Blank? False'), + # ('currency', 'Relation? False', 'Null? False', 'Blank? False'), + # ('object_id', 'Relation? False', 'Null? False', 'Blank? False'), + # ('term', 'Relation? False', 'Null? False', 'Blank? False'), + # ('term_type', 'Relation? False', 'Null? False', 'Blank? False'), + # ('text', 'Relation? False', 'Null? False', 'Blank? False'), + # ('secure_deal_only', 'Relation? False', 'Null? False', 'Blank? True'), + fields = ( 'budget', 'currency', 'term', 'term_type', 'text', + 'secure_deal_only', + + # 'portfolios', + # 'files', ) - widgets = { - 'currency': forms.Select(attrs={'class': 'selectpicker'}), - 'term_type': forms.Select(attrs={'class': 'selectpicker'}), - } + # widgets = { + # 'currency': forms.Select(attrs={'class': 'selectpicker'}), + # 'term_type': forms.Select(attrs={'class': 'selectpicker'}), + # } class StageForm(forms.ModelForm): diff --git a/projects/migrations/0012_merge.py b/projects/migrations/0012_merge.py new file mode 100644 index 0000000..f684b9f --- /dev/null +++ b/projects/migrations/0012_merge.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-08-02 17:12 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('projects', '0009_auto_20160802_1226'), + ('projects', '0011_auto_20160802_1653'), + ] + + operations = [ + ] diff --git a/projects/templates/project_detail.html b/projects/templates/project_detail.html index ffa3556..f54f489 100644 --- a/projects/templates/project_detail.html +++ b/projects/templates/project_detail.html @@ -144,200 +144,502 @@ {% endif %} + + + + + + + + + + + + + + + + + + + + {% if request.user.is_contractor and True %} +
+ {% csrf_token %} + + +
+
+
+

Стоимость

+ +
+
+ +
+
+ {{ form.currency }} +
+
+ +
+
+

Срок

+ +
+
+ +
+
+ {{ form.term_type }} +
+
+
+ +
+
+
+

Текст

+ +
+
+
+
+ +
+
+

Портфолио

+ +
    + {% for p in request.user.portfolios.all %} +
  • {{ p.name }}
  • + {% endfor %} +
+
+
+ +
+
+ Не более 10 файлов общим объемом до 500 Мб +
+
+ +
+
+ Работаю только по безопасной сделке +
+
+ +
+
+ +
+
+ +
+
+ {% elif request.user.is_contractor and False %} - {% if request.user.is_contractor %} -
- {% csrf_token %} - - -
+ + + + + + +{# {% with answer=tmp_answer %}#} +{#
#} +{#
#} +{#
#} +{# #} +{#
#} +{# execitor-image#} +{#
#} +{#
#} +{#

#} +{# {{ answer.contractor.get_full_name }} []#} +{#

#} +{# #} +{#
Свободен
#} +{#
#} +{#
#} +{# #} +{#
#} +{#
#} +{#

Есть допуск СРО

#} +{#
#} +{#
#} +{#
#} +{#

Цена:#} +{# {{ answer.cost|intcomma }}#} +{# #} +{#

#} +{#

#} +{# Срок: {{ answer.term }} {{ answer.term_type }}#} +{#

#} +{#

Опубликован: {{ answer.created }}

#} +{#
#} +{# #} +{#
#} +{#
#} +{#
#} +{#
#} +{#
#} +{#
#} +{#
#} +{#
#} +{#
#} +{#
#} +{#
#} +{#
#} +{#

#} +{# Иванов Петр Иванович#} +{#

#} +{# #} +{# 13.01.2016 / 21:05#} +{# #} +{#
#} +{# #} +{# #} +{# #} +{# #} +{# #} +{#
#} +{#

Lorem ipsum dolor sit amet

#} +{#
#} +{#
#} +{#
#} +{#
#} +{#
#} +{# {% endwith %}#} + + + + + + + + + +
+
+
+ +
+ execitor-image +
+
+

+ Иванов Петр Иванович [ivanov_petr] +

+ +
Свободен
+
+
+ +
+
+

Есть допуск СРО

+
+
+
+

Цена: + 35 000 + +

+

+ Срок: 3 недели +

+

Опубликован: 22.04.2016

+
+ +
-
-

Стоимость

- +
+
+
+
-
-
-

Бюджет

- {{ form.currency }} +
+
+
+
- -
-
-
-
-

Срок

- - +
+
+
+
-
-
-

Тип срока

- {{ form.term_type }} +
+
+
+
- -
-
-
-
-

Текст

- +
+
+
+

+ Иванов Петр Иванович +

+ + 13.01.2016 / 21:05 + +
+ + + + + +
+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean euismod bibendum laoreet. Proin gravida dolor sit amet lacus accumsan et viverra justo commodo. Proin sodales pulvinar tempor. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nam fermentum, nulla luctus pharetra vulputate, felis tellus mollis orci, sed rhoncus sapien nunc eget odio. +

-
-
- -
-
-
- {% for p in user.portfolio.all %} -

{{ p }}

- {% endfor %} +
+
+

+ Иванов Петр Иванович +

+ + 13.01.2016 / 21:05 + +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean euismod bibendum laoreet. Proin gravida dolor sit amet lacus accumsan et viverra justo commodo. Proin sodales pulvinar tempor. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nam fermentum, nulla luctus pharetra vulputate, felis tellus mollis orci, sed rhoncus sapien nunc eget odio. +

+ + Ответить +
-
- -
-
+
+
+ + + + + + {% elif request.user.is_customer %} + + + + + +
+
+

Исполнители

+
+
+
+ + +
- - - - - - - {% elif request.user.is_customer %} - - - - - -
-
-

Исполнители

+
+
+ +
+
+

Сравнить кандидатов

+
+
+ +
+

Новые исполнители

+
+ + + + + + + + + + + +
+
+
+ +
+ execitor-image +
+
+

+ Иванов Петр Иванович [ivanov_petr] +

+ +
Свободен
-
-
- - - +
+ +
+
+

Есть допуск СРО

-
-
-
-

Сравнить кандидатов

+
+

Цена: + 35 000 + +

+

+ Срок: 3 недели +

+

Опубликован: 22.04.2016

-
-
-

Новые исполнители

-
-
- {% for answer in project.answers.all %} -
-
-
- execitor-image -
-

- {{ answer.contractor.get_full_name }} [] -

- -
Свободен
+ +
+
+
+
+
+
-
- -
-
-

Есть допуск СРО

+
+
+
+
+
-
-

Цена: - {{ answer.cost|intcomma }} - -

-

- Срок: {{ answer.term }} {{ answer.term_type }} -

-

Опубликован: {{ answer.created }}

+
+
+
+
+
+
- +
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+

+ Иванов Петр Иванович +

+ + 13.01.2016 / 21:05 + +
+ + + + +
+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean euismod bibendum laoreet. Proin gravida dolor sit amet lacus accumsan et viverra justo commodo. Proin sodales pulvinar tempor. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nam fermentum, nulla luctus pharetra vulputate, felis tellus mollis orci, sed rhoncus sapien nunc eget odio. +

-
-{#
#} -{#
#} -{#

#} -{# Иванов Петр Иванович#} -{#

#} -{# #} -{# 13.0.2016 / 21:05#} -{# #} -{#
#} -{# #} -{# #} -{# #} -{# #} -{# #} -{#
#} -{#

Lorem ipsum dolor sit amet

#} -{#
#} -{#
#} +
+
+
+

+ Иванов Петр Иванович +

+ + 13.01.2016 / 21:05 + +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean euismod bibendum laoreet. Proin gravida dolor sit amet lacus accumsan et viverra justo commodo. Proin sodales pulvinar tempor. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nam fermentum, nulla luctus pharetra vulputate, felis tellus mollis orci, sed rhoncus sapien nunc eget odio. +

+ + Ответить +
- {% endfor %} +
- {% endif %} -
+
+ {% endif %} diff --git a/projects/urls.py b/projects/urls.py index 5ff98e1..684450e 100644 --- a/projects/urls.py +++ b/projects/urls.py @@ -30,6 +30,7 @@ urlpatterns = [ urls.url(r'^(?P\d+)/delete/$', CustomerProjectDeleteView.as_view(), name='customer-project-delete'), urls.url(r'^(?P\d+)/answer/$', ContractorProjectAnswerView.as_view(), name='contractor-project-answer'), + urls.url(r'^portfolio/create/$', contractor_portfolio_create, name='contractor-portfolio-create'), urls.url(r'^portfolio/(?P\d+)/edit/$', ContractorPortfolioUpdateView.as_view(), name='contractor-portfolio-edit'), diff --git a/projects/views.py b/projects/views.py index 157bd98..f063389 100644 --- a/projects/views.py +++ b/projects/views.py @@ -42,6 +42,8 @@ class ProjectView(BaseMixin, View): project = get_object_or_404(Project, pk=kwargs.get('pk')) context.update({'project': project}) + # context.update({'tmp_answer': Answer.objects.order_by('?').first()}) + # import code; code.interact(local=dict(globals(), **locals())) if request.user.is_authenticated() and request.user.is_contractor(): @@ -323,21 +325,40 @@ class CustomerProjectEditView(BaseMixin, View): class ContractorProjectAnswerView(BaseMixin, View): form_class = ContractorProjectAnswerForm - def post(self, request, *args, **kwargs): - if not request.user.is_authenticated(): - return HttpResponseForbidden() - form = self.form_class(request.POST) - project = get_object_or_404(Project, pk=kwargs.get('pk')) + def dispatch(self, request, *args, **kwargs): + if request.user.is_authenticated() and request.user.is_contractor(): + return super().dispatch(request, *args, **kwargs) + else: + return HttpResponseForbidden('403 Forbidden') + + def post(self, req, *args, **kwargs): + form = self.form_class(_.merge({}, req.POST, kwargs), req=req) + if form.is_valid(): - return self.form_valid(request, form, project) - return render(request, self.template_name, {'project': project, 'form': self.form_class}) + project = form.cleaned_data.get('pk') + project.state = 'trashed' + project.save() + + messages.info(req, 'OK') + else: + messages.info(req, 'Произошла ошибка:
{msg}
'.format(msg=pformat(form.errors))) + + redirect_to = req.POST.get('next') + return redirect(redirect_to) + + - def form_valid(self, request, form, project): - answer = form.save(commit=False) - answer.contractor = request.user - answer.project = project - answer.save() - return HttpResponseRedirect(reverse('projects:detail', kwargs={'pk': project.pk})) + # def post(self, request, *args, **kwargs): + # form = self.form_class(request.POST) + # project = get_object_or_404(Project, pk=kwargs.get('pk')) + # if form.is_valid(): + # answer = form.save(commit=False) + # answer.contractor = request.user + # answer.project = project + # answer.save() + # return HttpResponseRedirect(reverse('projects:detail', kwargs={'pk': project.pk})) + # return render(request, self.template_name, {'project': project, 'form': self.form_class}) + class CustomerProjectTrashView(View): @@ -350,19 +371,16 @@ class CustomerProjectTrashView(View): return HttpResponseForbidden('403 Forbidden') def post(self, req, *args, **kwargs): - if req.user.is_authenticated(): - form = self.form_class(_.merge({}, req.POST, kwargs), req=req) - - if form.is_valid(): - project = form.cleaned_data.get('pk') - project.state = 'trashed' - project.save() - - messages.info(req, 'Проект перемещён в корзину') - else: - messages.info(req, 'Произошла ошибка:
{msg}
'.format(msg=pformat(form.errors))) + form = self.form_class(_.merge({}, req.POST, kwargs), req=req) + + if form.is_valid(): + project = form.cleaned_data.get('pk') + project.state = 'trashed' + project.save() + + messages.info(req, 'Проект перемещён в корзину') else: - return HttpResponseForbidden('403 Forbidden') + messages.info(req, 'Произошла ошибка:
{msg}
'.format(msg=pformat(form.errors))) redirect_to = req.POST.get('next') return redirect(redirect_to) @@ -371,20 +389,23 @@ class CustomerProjectTrashView(View): class CustomerProjectRestoreView(View): form_class = CustomerProjectRestoreForm - def post(self, req, *args, **kwargs): - if req.user.is_authenticated(): - form = self.form_class(_.merge({}, req.POST, kwargs), req=req) - - if form.is_valid(): - project = form.cleaned_data.get('pk') - project.state = 'active' - project.save() - - messages.info(req, 'Проект восстановлен из корзины') - else: - messages.info(req, 'Произошла ошибка:
{msg}
'.format(msg=pformat(form.errors))) + def dispatch(self, request, *args, **kwargs): + if request.user.is_authenticated() and request.user.is_customer(): + return super().dispatch(request, *args, **kwargs) else: return HttpResponseForbidden('403 Forbidden') + + def post(self, req, *args, **kwargs): + form = self.form_class(_.merge({}, req.POST, kwargs), req=req) + + if form.is_valid(): + project = form.cleaned_data.get('pk') + project.state = 'active' + project.save() + + messages.info(req, 'Проект восстановлен из корзины') + else: + messages.info(req, 'Произошла ошибка:
{msg}
'.format(msg=pformat(form.errors))) redirect_to = req.POST.get('next') return redirect(redirect_to) @@ -393,19 +414,22 @@ class CustomerProjectRestoreView(View): class CustomerProjectDeleteView(View): form_class = CustomerProjectDeleteForm - def post(self, req, *args, **kwargs): - if req.user.is_authenticated(): - form = self.form_class(_.merge({}, req.POST, kwargs), req=req) - - if form.is_valid(): - project = form.cleaned_data.get('pk') - project.state = 'deleted' - project.save() - messages.info(req, 'Проект удалён навсегда') - else: - messages.info(req, 'Произошла ошибка:
{msg}
'.format(msg=pformat(form.errors))) + def dispatch(self, request, *args, **kwargs): + if request.user.is_authenticated() and request.user.is_customer(): + return super().dispatch(request, *args, **kwargs) else: return HttpResponseForbidden('403 Forbidden') + + def post(self, req, *args, **kwargs): + form = self.form_class(_.merge({}, req.POST, kwargs), req=req) + + if form.is_valid(): + project = form.cleaned_data.get('pk') + project.state = 'deleted' + project.save() + messages.info(req, 'Проект удалён навсегда') + else: + messages.info(req, 'Произошла ошибка:
{msg}
'.format(msg=pformat(form.errors))) redirect_to = req.POST.get('next') return redirect(redirect_to)