remotes/origin/setup
ArturBaybulatov 10 years ago
parent 6c5a2779e6
commit 88f32d0d63
  1. 4
      archilance/util.py
  2. 6
      projects/forms.py
  3. 43
      projects/migrations/0009_auto_20160802_1414.py
  4. 29
      projects/migrations/0010_answerfiles.py
  5. 25
      projects/migrations/0011_auto_20160802_1653.py
  6. 30
      projects/models.py
  7. 215
      projects/templates/customer_project_detail.html
  8. 142
      projects/templates/project_detail.html
  9. 9
      projects/urls.py
  10. 48
      projects/views.py
  11. 8
      users/models.py
  12. 18
      users/urls.py

@ -65,8 +65,8 @@ def model_fields(model, width=200):
pprint([( pprint([(
f.name, f.name,
'Relation? %s' % f.is_relation, 'Relation? %s' % f.is_relation,
'Null? %s' % f.null, 'Null? %s' % getattr(f, 'null', None),
'Blank? %s' % f.blank if not f.is_relation else '(relation)', 'Blank? %s' % getattr(f, 'blank', None),
) for f in fields], width=width) ) for f in fields], width=width)

@ -165,12 +165,6 @@ class PortfolioForm(forms.ModelForm):
} }
class ContractorProjectAnswerForm(forms.ModelForm): class ContractorProjectAnswerForm(forms.ModelForm):
# def __init__(self, *args, **kwargs):
# # import code; code.interact(local=dict(globals(), **locals()))
# self.project_id = kwargs.pop('project_id')
# super().__init__(*args, **kwargs)
# self.fields["project"].initial = self.project_id
class Meta: class Meta:
model = Answer model = Answer

@ -0,0 +1,43 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-08-02 11:14
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('contenttypes', '0002_remove_content_type_name'),
('projects', '0008_merge'),
]
operations = [
migrations.AlterModelOptions(
name='answer',
options={'ordering': ('-created',), 'verbose_name': 'Отклик на проект', 'verbose_name_plural': 'Отклики на проекты'},
),
migrations.RemoveField(
model_name='answer',
name='contractor',
),
migrations.AddField(
model_name='answer',
name='content_type',
field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType'),
preserve_default=False,
),
migrations.AddField(
model_name='answer',
name='object_id',
field=models.IntegerField(default=None),
preserve_default=False,
),
migrations.AlterField(
model_name='stage',
name='created',
field=models.DateTimeField(default=django.utils.timezone.now),
),
]

@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-08-02 13:34
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('projects', '0009_auto_20160802_1414'),
]
operations = [
migrations.CreateModel(
name='AnswerFiles',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255)),
('file', models.FileField(upload_to='projects/answer_files')),
('answer', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='files', to='projects.Answer')),
],
options={
'verbose_name_plural': 'Файлы для откликов',
'verbose_name': 'Файл для отклика',
},
),
]

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-08-02 13:53
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('projects', '0010_answerfiles'),
]
operations = [
migrations.AddField(
model_name='answer',
name='portfolios',
field=models.ManyToManyField(blank=True, related_name='answers', to='projects.Portfolio'),
),
migrations.AddField(
model_name='answer',
name='secure_deal_only',
field=models.BooleanField(default=False),
),
]

@ -1,7 +1,9 @@
from mptt.models import TreeForeignKey from django.contrib.contenttypes.fields import GenericForeignKey
from datetime import datetime from django.contrib.contenttypes.models import ContentType
from django.db import models from django.db import models
from django.db.models import Q
from django.utils import timezone from django.utils import timezone
from mptt.models import TreeForeignKey
from users.models import User, Team from users.models import User, Team
from specializations.models import Specialization from specializations.models import Specialization
@ -117,23 +119,41 @@ class ProjectFile(models.Model):
class Answer(models.Model): class Answer(models.Model):
budget = models.DecimalField(max_digits=10, decimal_places=0) budget = models.DecimalField(max_digits=10, decimal_places=0)
contractor = models.ForeignKey(User, related_name='answers')
created = models.DateTimeField(default=timezone.now) created = models.DateTimeField(default=timezone.now)
currency = models.CharField(max_length=5, choices=CURRENCIES, default='rur') currency = models.CharField(max_length=5, choices=CURRENCIES, default='rur')
portfolios = models.ManyToManyField('Portfolio', related_name ='answers', blank=True)
project = models.ForeignKey(Project, related_name='answers') project = models.ForeignKey(Project, related_name='answers')
secure_deal_only = models.BooleanField(default=False)
term = models.IntegerField(default=0) term = models.IntegerField(default=0)
term_type = models.CharField(max_length=10, choices=TERMS, default='hour') term_type = models.CharField(max_length=10, choices=TERMS, default='hour')
text = models.TextField() text = models.TextField()
content_type = models.ForeignKey(ContentType, limit_choices_to=Q(app_label='users', model='user') | Q(app_label='users', model='team'))
object_id = models.IntegerField()
author = GenericForeignKey('content_type', 'object_id')
def __str__(self): def __str__(self):
return self.text return self.text
class Meta: class Meta:
verbose_name = 'Ответ к проекту' verbose_name = 'Отклик на проект'
verbose_name_plural = 'Ответы к проектам' verbose_name_plural = 'Отклики на проекты'
ordering = ('-created',) ordering = ('-created',)
class AnswerFiles(models.Model):
answer = models.ForeignKey(Answer, related_name='files', blank=True, null=True)
name = models.CharField(max_length=255)
file = models.FileField(upload_to='projects/answer_files')
class Meta:
verbose_name = 'Файл для отклика'
verbose_name_plural = 'Файлы для откликов'
def __str__(self):
return self.file and self.file.url or self.pk
class Order(models.Model): class Order(models.Model):
contractor = models.ForeignKey(User, null=True, blank=True, related_name='orders') contractor = models.ForeignKey(User, null=True, blank=True, related_name='orders')
created = models.DateTimeField(default=timezone.now) created = models.DateTimeField(default=timezone.now)

@ -1,215 +0,0 @@
{% extends 'partials/base.html' %}
{% block content %}
{% include 'partials/header.html' %}
{% load staticfiles %}
{% load humanize %}
<div class="container mainScore">
<div class="row">
<div class="col-lg-12">
<p class="titleScore">{{ project }}</p>
</div>
<div class="doneBlock disTab">
<div class="triangle1"></div>
<div class="col-lg-4">
<a href="#" class="aLinkExe"><div class="imgExecutor">
<img src="{% static 'img/profile.jpg' %}" alt="execitor-image">
</div></a>
<p class="nameExecutor">
<a href="#">{{ project.contractor.get_full_name }} [ivanov_petr]</a>
</p>
<p class="navv2">На сайте {{ project.contractor.created | naturaltime }}</p>
<ul class="rettList restList3">
<li>
<a href="javascript:void(0)">Отзывы:
<span> + 0</span>
<small> 0</small>
<mark> - 0</mark>
</a>
</li>
</ul>
</div>
<div class="col-lg-3 col-lg-offset-1">
<div class="dashedCol4 dashedCol44 dashedColColor">
<p class="specUser">
Специализации:
</p>
<div class="insetSpec">
<span>{{ project.specialization }}</span>
</div>
</div>
</div>
<div class="col-lg-4 retts">
<ul class="desListPro">
<li>
{{ project.created }}
</li>
<li>
{{ project.type_work }}
</li>
</ul>
{% if project.secure_transaction %}
<div class="sroUser sroExecutor sroPro">
<div class="iconSRO"></div>
<p>Есть допуск СРО</p>
</div>
{% endif %}
</div>
</div>
<div class="infoProjectBlock disTab">
<div class="triangle2"></div>
<div class="col-lg-10 col-lg-offset-1">
<ul class="listProjectIn">
<li>
<span>Местоположение:</span> {{ project.realty.country }}, {{ project.realty.city }}
</li>
<li>
<span>Классификация здания:</span> {{ project.realty.building_classification }}
</li>
<li>
<span>Вид строительства:</span> {{ project.realty.type_construction }}
</li>
</ul>
</div>
<div class="col-lg-10 col-lg-offset-1">
<p class="textProIn">
{{ project.text }}
</p>
</div>
<div class="col-lg-10 col-lg-offset-1">
<a href="{% url 'projects:customer-project-edit' pk=project.pk %}?back={{ request.path }}" class="linkProIn linkProIn1">
Редактировать
</a>
<form action="{% url 'projects:customer-project-trash' pk=project.pk %}" method="POST">
{% csrf_token %}
<input type="hidden" name="next" value="{{ request.path }}">
<a href="#" onclick="$(this).closest('form').submit(); return false" class="linkProIn linkProIn2">
Снять с публикации
</a>
</form>
</div>
</div>
<div class="exBigBlock disTab">
<div class="col-lg-12">
<p class="titleEx">Исполнители</p>
</div>
<div class="col-lg-12 exButton">
<div class="btn-group" role="group" aria-label="...">
<button type="button" class="btn btn-default">
Новые <span>+0</span>
</button>
<button type="button" class="btn btn-default">
Кандидаты <span>0</span>
</button>
<button type="button" class="btn btn-default">
Отказал <span>0</span>
</button>
</div>
</div>
</div>
<div class="col-lg-12 compareBlock">
<div class="col-lg-2 col-lg-offset-5">
<p>Сравнить кандидатов</p>
</div>
</div>
<div class="col-lg-12 exNew">
<p>Новые исполнители</p>
</div>
<div class="candidateBlock disTab">
{% for answer in project.answers.all %}
<div class="candidate">
<div class="col-lg-4">
<a href="#" class="aLinkExe"><div class="imgExecutor">
<img src="{% static 'img/profile.jpg' %}" alt="execitor-image">
</div></a>
<p class="nameExecutor">
<a href="#"> {{ answer.contractor.get_full_name }} []</a>
</p>
<p class="navv2">На сайте {{ answer.contractor.created }}</p>
<div class="statusUser">Свободен</div>
</div>
<div class="col-lg-3 retts">
<ul class="rettList restList2">
<li>Рейтинг: <span> 0</span></li>
<li>Безопасные сделки: <span> 0</span></li>
<li>
<a href="javascript:void(0)">Отзывы:
<span> + 0</span>
<small> 0</small>
<mark> - 0</mark>
</a>
</li>
</ul>
<div class="sroUser sroExecutor">
<div class="iconSRO"></div>
<p>Есть допуск СРО</p>
</div>
</div>
<div class="col-lg-2 listCens">
<p>Цена:
<span> {{ answer.cost| intcomma }}</span>
<i class="fa fa-rub"></i>
</p>
<p>
Срок: <span>{{ answer.term }} {{ answer.term_type }}</span>
</p>
<p>Опубликован: {{ answer.created }}</p>
</div>
<div class="col-lg-3 retts">
<a href="{% url 'projects:add-candidate' answer_id=answer.id project_id=project.id %}" class="candLink candLink1">
Кандидат
</a>
<a href="{% url 'projects:offer-order' answer_id=answer.id project_id=project.id %}" class="candLink candLink2">
предложить проект
</a>
<a href="javascript:void(0)" class="candLink candLink3">
отказ
</a>
</div>
<div class="gallMini disTab">
<div class="col-lg-3">
<div class="insetCol box-sizing disTab">
<div class="imgGal">
<div class="imgFigure"></div>
</div>
</div>
</div>
</div>
<div class="commBlock44 disTab">
{# <div class="comm44 disTab">#}
{# <div class="col-lg-10 col-lg-offset-1">#}
{# <p class="nameComm">#}
{# Иванов Петр Иванович#}
{# </p>#}
{# <span class="dateComm44">#}
{# 13.0.2016 / 21:05#}
{# </span>#}
{# <div class="stars box-sizing">#}
{# <span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span>#}
{# <span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span>#}
{# <span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span>#}
{# <span class="glyphicon glyphicon-star" aria-hidden="true"></span>#}
{# <span class="glyphicon glyphicon-star" aria-hidden="true"></span>#}
{# </div>#}
{# <p class="textComm44">Lorem ipsum dolor sit amet</p>#}
{# </div>#}
{# </div>#}
</div>
</div>
{% endfor %}
</div>
<div class="col-lg-12 pagin">
{% include 'partials/pagination.html' %}
</div>
{% include 'partials/footer.html' %}
</div>
</div>
{% endblock %}

@ -9,24 +9,47 @@
<div class="container mainScore"> <div class="container mainScore">
<div class="row"> <div class="row">
<div class="col-lg-12"> <div class="col-lg-12">
<p class="titleScore">{{ project }}</p> <p class="titleScore">{{ project.name }}</p>
</div> </div>
<div class="doneBlock new-done disTab"> <div class="doneBlock new-done disTab">
<div class="triangle1"></div> <div class="triangle1"></div>
{% if request.user.is_contractor %}
<div class="col-lg-12 new-p"> <div class="col-lg-12 new-p">
<p>{{ project.budget|intcomma }} <i class="fa fa-rub"></i></p> <p>{{ project.budget|intcomma }} <i class="fa fa-rub"></i></p>
</div> </div>
{% endif %}
<div class="col-lg-4"> <div class="col-lg-4">
<a href="#" class="aLinkExe"> <a href="#" class="aLinkExe">
<div class="imgExecutor"> <div class="imgExecutor">
{% if project.customer.avatar %}
<img src="{{ project.customer.avatar.url }}" alt="execitor-image">
{% else %}
<img src="{% static 'img/profile.jpg' %}" alt="execitor-image"> <img src="{% static 'img/profile.jpg' %}" alt="execitor-image">
{% endif %}
</div> </div>
</a> </a>
<p class="nameExecutor"> <p class="nameExecutor">
<a href="#">{{ project.customer.get_full_name }} [{{ project.customer }}]</a> <a href="#">{{ project.customer.get_full_name }} [{{ project.customer.username }}]</a>
</p> </p>
<p class="navv2">На сайте {{ project.created|naturaltime }}</p> <p class="navv2">На сайте {{ project.created|naturaltime }}</p>
{% if not request.user.is_contractor %}
<ul class="rettList restList3">
<li>
<a href="javascript:void(0)">Отзывы:
<span> + 0</span>
<small> 0</small>
<mark> - 0</mark>
</a>
</li>
</ul>
{% endif %}
</div> </div>
{% if request.user.is_contractor %}
<div class="col-lg-3 retts"> <div class="col-lg-3 retts">
<ul class="rettList restList2"> <ul class="rettList restList2">
<li>Рейтинг: <span> 0</span></li> <li>Рейтинг: <span> 0</span></li>
@ -40,6 +63,8 @@
</li> </li>
</ul> </ul>
</div> </div>
{% endif %}
<div class="col-lg-2 new-dashed"> <div class="col-lg-2 new-dashed">
<div class="dashedCol4 dashedCol44 dashedColColor"> <div class="dashedCol4 dashedCol44 dashedColColor">
<p class="specUser"> <p class="specUser">
@ -56,24 +81,28 @@
<div class="col-lg-3 retts new-list"> <div class="col-lg-3 retts new-list">
<ul class="desListPro"> <ul class="desListPro">
<li> <li>
13.0.2016 {{ project.created }}
</li> </li>
<li> <li>
Техническое сопровождение {{ project.get_work_type_display }}
</li> </li>
</ul> </ul>
{% if project.cro %}
<div class="sroUser sroExecutor sroPro"> <div class="sroUser sroExecutor sroPro">
<div class="iconSRO"></div> <div class="iconSRO"></div>
<p>Есть допуск СРО</p> <p>Есть допуск СРО</p>
</div> </div>
{% endif %}
</div> </div>
</div> </div>
<div class="infoProjectBlock info-new disTab"> <div class="infoProjectBlock info-new disTab">
<div class="triangle2"></div> <div class="triangle2"></div>
<div class="col-lg-10 col-lg-offset-1"> <div class="col-lg-10 col-lg-offset-1">
<ul class="listProjectIn"> <ul class="listProjectIn">
<li> <li>
<span>Местоположение:</span> <span>Местоположение:</span> {{ project.realty.country }}, {{ project.realty.city }}
</li> </li>
<li> <li>
<span>Классификация здания:</span> {{ project.realty.building_classification }} <span>Классификация здания:</span> {{ project.realty.building_classification }}
@ -89,23 +118,41 @@
</p> </p>
</div> </div>
<div class="col-lg-10 col-lg-offset-1"> <div class="col-lg-10 col-lg-offset-1">
<a href="javascript:void(0)" class="new-answer"> {% if request.user.is_contractor %}
<a href="#" class="new-answer">
Ответить на проект Ответить на проект
</a> </a>
<div class="polsF1 pols-new disTab"> <div class="polsF1 pols-new disTab">
<div class="col-lg-3"> <div class="col-lg-3">
<select class="selectpicker"> <select class="selectpicker">
<option value="{{ user.id }}">Ответ от своего имени</option> <option>Бла-бла</option>
<option value="{{ user.team.id }}">{{ user.team.name }}</option>
</select> </select>
</div> </div>
</div> </div>
{% elif request.user.is_customer %}
<a href="{% url 'projects:customer-project-edit' pk=project.pk %}?back={{ request.path }}" class="linkProIn linkProIn1">
Редактировать
</a>
<form action="{% url 'projects:customer-project-trash' pk=project.pk %}" method="POST">
{% csrf_token %}
<input type="hidden" name="next" value="{{ request.path }}">
<a href="#" onclick="$(this).closest('form').submit(); return false" class="linkProIn linkProIn2">
Снять с публикации
</a>
</form>
{% endif %}
</div> </div>
{% if request.user.is_contractor %}
<form action="{% url 'projects:contractor-project-answer' pk=pk %}" method="POST"> <form action="{% url 'projects:contractor-project-answer' pk=pk %}" method="POST">
{% csrf_token %} {% csrf_token %}
<input type="hidden" name="next" value="{% url 'projects:detail' pk=pk %}"> <input type="hidden" name="next" value="{% url 'projects:detail' pk=pk %}">
<div class="polsF1 disTab"> <div class="polsF1 disTab">
@ -168,18 +215,55 @@
<div class="col-lg-3"><input type="submit" value="Создать"/></div> <div class="col-lg-3"><input type="submit" value="Создать"/></div>
</div> </div>
</form> </form>
{% elif request.user.is_customer %}
<div class="exBigBlock disTab">
<div class="col-lg-12">
<p class="titleEx">Исполнители</p>
</div>
<div class="col-lg-12 exButton">
<div class="btn-group" role="group" aria-label="...">
<button type="button" class="btn btn-default">
Новые <span>+0</span>
</button>
<button type="button" class="btn btn-default">
Кандидаты <span>0</span>
</button>
<button type="button" class="btn btn-default">
Отказал <span>0</span>
</button>
</div>
</div>
</div>
<div class="col-lg-12 compareBlock">
<div class="col-lg-2 col-lg-offset-5">
<p>Сравнить кандидатов</p>
</div>
</div>
<div class="col-lg-12 exNew">
<p>Новые исполнители</p>
</div> </div>
<div class="candidateBlock disTab"> <div class="candidateBlock disTab">
{% for answer in project.answers.all %} {% for answer in project.answers.all %}
<div class="candidate can-new"> <div class="candidate">
<div class="col-lg-4"> <div class="col-lg-4">
<a href="#" class="aLinkExe"><div class="imgExecutor"> <a href="#" class="aLinkExe"><div class="imgExecutor">
<img src="{% static 'img/profile.jpg' %}" alt="execitor-image"> <img src="{% static 'img/profile.jpg' %}" alt="execitor-image">
</div></a> </div></a>
<p class="nameExecutor"> <p class="nameExecutor">
<a href="#">{{ answer.contractor.get_full_name }} [{{ answer.contractor }}]</a> <a href="#"> {{ answer.contractor.get_full_name }} []</a>
</p> </p>
<p class="navv2">{{ answer.contractor.created }}</p> <p class="navv2">На сайте {{ answer.contractor.created }}</p>
<div class="statusUser">Свободен</div>
</div> </div>
<div class="col-lg-3 retts"> <div class="col-lg-3 retts">
<ul class="rettList restList2"> <ul class="rettList restList2">
@ -193,16 +277,14 @@
</a> </a>
</li> </li>
</ul> </ul>
{% if answer.contractor.cro %}
<div class="sroUser sroExecutor"> <div class="sroUser sroExecutor">
<div class="iconSRO"></div> <div class="iconSRO"></div>
<p>Есть допуск СРО</p> <p>Есть допуск СРО</p>
</div> </div>
{% endif %}
</div> </div>
<div class="col-lg-2 listCens"> <div class="col-lg-2 listCens">
<p>Цена: <p>Цена:
<span> {{ answer.budget }}</span> <span> {{ answer.cost|intcomma }}</span>
<i class="fa fa-rub"></i> <i class="fa fa-rub"></i>
</p> </p>
<p> <p>
@ -211,11 +293,27 @@
<p>Опубликован: {{ answer.created }}</p> <p>Опубликован: {{ answer.created }}</p>
</div> </div>
<div class="col-lg-3 retts"> <div class="col-lg-3 retts">
<a href="" class="candLink candLink3">
<a href="{% url 'projects:add-candidate' answer_id=answer.id project_id=project.id %}" class="candLink candLink1">
Кандидат
</a>
<a href="{% url 'projects:offer-order' answer_id=answer.id project_id=project.id %}" class="candLink candLink2">
предложить проект
</a>
<a href="javascript:void(0)" class="candLink candLink3">
отказ отказ
</a> </a>
</div> </div>
<div class="commBlock44 comm-new disTab"> <div class="gallMini disTab">
<div class="col-lg-3">
<div class="insetCol box-sizing disTab">
<div class="imgGal">
<div class="imgFigure"></div>
</div>
</div>
</div>
</div>
<div class="commBlock44 disTab">
{# <div class="comm44 disTab">#} {# <div class="comm44 disTab">#}
{# <div class="col-lg-10 col-lg-offset-1">#} {# <div class="col-lg-10 col-lg-offset-1">#}
{# <p class="nameComm">#} {# <p class="nameComm">#}
@ -231,20 +329,18 @@
{# <span class="glyphicon glyphicon-star" aria-hidden="true"></span>#} {# <span class="glyphicon glyphicon-star" aria-hidden="true"></span>#}
{# <span class="glyphicon glyphicon-star" aria-hidden="true"></span>#} {# <span class="glyphicon glyphicon-star" aria-hidden="true"></span>#}
{# </div>#} {# </div>#}
{# <p class="textComm44">#} {# <p class="textComm44">Lorem ipsum dolor sit amet</p>#}
{# Text#}
{# </p>#}
{# </div>#} {# </div>#}
{# </div>#} {# </div>#}
</div> </div>
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
{% endif %}
<div class="col-lg-12 pagin">
{% include 'partials/pagination.html' %}
</div> </div>
{% include 'partials/footer.html' %} {% include 'partials/footer.html' %}
</div> </div>
</div> </div>

@ -21,19 +21,22 @@ app_name = 'projects'
urlpatterns = [ urlpatterns = [
urls.url(r'^$', ProjectFilterView.as_view(), name='project-filter'), urls.url(r'^$', ProjectFilterView.as_view(), name='project-filter'),
urls.url(r'^(?P<pk>\d+)/$', ProjectView.as_view(), name='detail'),
urls.url(r'^create/$', CustomerProjectCreateView.as_view(), name='customer-project-create'), urls.url(r'^create/$', CustomerProjectCreateView.as_view(), name='customer-project-create'),
urls.url(r'^(?P<pk>\d+)/$', ProjectView.as_view(), name='detail'),
urls.url(r'^(?P<pk>\d+)/edit/$', CustomerProjectEditView.as_view(), name='customer-project-edit'), urls.url(r'^(?P<pk>\d+)/edit/$', CustomerProjectEditView.as_view(), name='customer-project-edit'),
urls.url(r'^(?P<pk>\d+)/trash/$', CustomerProjectTrashView.as_view(), name='customer-project-trash'), urls.url(r'^(?P<pk>\d+)/trash/$', CustomerProjectTrashView.as_view(), name='customer-project-trash'),
urls.url(r'^(?P<pk>\d+)/restore/$', CustomerProjectRestoreView.as_view(), name='customer-project-restore'), urls.url(r'^(?P<pk>\d+)/restore/$', CustomerProjectRestoreView.as_view(), name='customer-project-restore'),
urls.url(r'^(?P<pk>\d+)/delete/$', CustomerProjectDeleteView.as_view(), name='customer-project-delete'), urls.url(r'^(?P<pk>\d+)/delete/$', CustomerProjectDeleteView.as_view(), name='customer-project-delete'),
urls.url(r'^(?P<pk>\d+)/answer/$', ContractorProjectAnswerView.as_view(), name='contractor-project-answer'), urls.url(r'^(?P<pk>\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/create/$', contractor_portfolio_create, name='contractor-portfolio-create'),
urls.url(r'^portfolio/(?P<pk>\d+)/edit/$', ContractorPortfolioUpdateView.as_view(), name='contractor-portfolio-edit'), urls.url(r'^portfolio/(?P<pk>\d+)/edit/$', ContractorPortfolioUpdateView.as_view(), name='contractor-portfolio-edit'),
urls.url(r'^candidate/add/(?P<answer_id>(\d+))/(?P<project_id>(\d+))/$', add_candidate, name='add-candidate'), urls.url(r'^candidate/add/(?P<answer_id>(\d+))/(?P<project_id>(\d+))/$', add_candidate, name='add-candidate'),
urls.url(r'^candidate/comparison/(?P<pk>\d+)$', ProjectComparisonView.as_view(), name='comparison'), urls.url(r'^candidate/comparison/(?P<pk>\d+)$', ProjectComparisonView.as_view(), name='comparison'),
urls.url(r'^offerorder/(?P<answer_id>(\d+))/(?P<project_id>(\d+))/$', OfferOrderView.as_view(), name='offer-order'),
# urls.url(r'^portfolio/create/$', PortfolioCreateView.as_view(), name='portfolio-create'), # urls.url(r'^portfolio/create/$', PortfolioCreateView.as_view(), name='portfolio-create'),
urls.url(r'offerorder/(?P<answer_id>(\d+))/(?P<project_id>(\d+))/$', OfferOrderView.as_view(), name='offer-order'),
] ]

@ -32,6 +32,25 @@ from .forms import (
) )
class ProjectView(BaseMixin, View):
template_name = 'project_detail.html'
form_class = ContractorProjectAnswerForm
def get(self, request, *args, **kwargs):
context = self.get_context_data(**_.merge({}, request.GET, kwargs))
project = get_object_or_404(Project, pk=kwargs.get('pk'))
context.update({'project': project})
# import code; code.interact(local=dict(globals(), **locals()))
if request.user.is_authenticated() and request.user.is_contractor():
form = self.form_class()
context.update({'form': form})
return render(request, self.template_name, context)
class ProjectFilterView(BaseMixin, View): class ProjectFilterView(BaseMixin, View):
template_name = 'project_filter.html' template_name = 'project_filter.html'
form_class = ProjectFilterForm form_class = ProjectFilterForm
@ -144,27 +163,6 @@ class ProjectFilterView(BaseMixin, View):
return render(request, self.template_name, context) return render(request, self.template_name, context)
class ProjectView(BaseMixin, View):
template_name = 'project_detail.html'
customer_template_name = 'customer_project_detail.html'
form_class = ContractorProjectAnswerForm
def get(self, request, *args, **kwargs):
project = get_object_or_404(Project, pk=kwargs.get('pk'))
context = self.get_context_data(**_.merge({}, request.GET, kwargs))
context.update({'project': project})
# import code; code.interact(local=dict(globals(), **locals()))
if request.user.is_authenticated() and request.user.is_customer():
return render(request, self.customer_template_name, context)
else:
form = self.form_class()
context.update({'form': form})
return render(request, self.template_name, context)
class CustomerProjectCreateView(BaseMixin, View): class CustomerProjectCreateView(BaseMixin, View):
form_class = CustomerProjectEditForm form_class = CustomerProjectEditForm
realty_form = RealtyForm realty_form = RealtyForm
@ -246,7 +244,7 @@ class CustomerProjectEditView(BaseMixin, View):
template_name = 'customer_project_edit.html' template_name = 'customer_project_edit.html'
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
if request.user.is_authenticated() and request.user.is_customer() and request.user.pk == int(kwargs.get('pk')): if request.user.is_authenticated() and request.user.is_customer():
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
else: else:
return HttpResponseForbidden('403 Forbidden') return HttpResponseForbidden('403 Forbidden')
@ -345,6 +343,12 @@ class ContractorProjectAnswerView(BaseMixin, View):
class CustomerProjectTrashView(View): class CustomerProjectTrashView(View):
form_class = CustomerProjectTrashForm form_class = CustomerProjectTrashForm
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): def post(self, req, *args, **kwargs):
if req.user.is_authenticated(): if req.user.is_authenticated():
form = self.form_class(_.merge({}, req.POST, kwargs), req=req) form = self.form_class(_.merge({}, req.POST, kwargs), req=req)

@ -1,8 +1,8 @@
from mptt.models import TreeForeignKey, TreeManyToManyField from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, AbstractUser, Group, PermissionsMixin
from datetime import datetime from django.contrib.contenttypes.fields import GenericRelation
from django.db import models from django.db import models
from django.utils import timezone from django.utils import timezone
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, AbstractUser, Group, PermissionsMixin from mptt.models import TreeForeignKey, TreeManyToManyField
from specializations.models import Specialization from specializations.models import Specialization
@ -117,6 +117,7 @@ class User(AbstractBaseUser, PermissionsMixin):
) )
avatar = models.ImageField(upload_to='users/avatars/', blank=True) avatar = models.ImageField(upload_to='users/avatars/', blank=True)
contractor_answers = GenericRelation('projects.Answer')
contractor_resume = models.OneToOneField(ContractorResume, related_name='contractor', blank=True, null=True) contractor_resume = models.OneToOneField(ContractorResume, related_name='contractor', blank=True, null=True)
contractor_specializations = TreeManyToManyField(Specialization, related_name='contractors', blank=True) contractor_specializations = TreeManyToManyField(Specialization, related_name='contractors', blank=True)
contractor_status = models.CharField(default='free', max_length=20, choices=STATUSES) contractor_status = models.CharField(default='free', max_length=20, choices=STATUSES)
@ -182,6 +183,7 @@ class User(AbstractBaseUser, PermissionsMixin):
class Team(models.Model): class Team(models.Model):
answers = GenericRelation('projects.Answer')
created = models.DateTimeField(default=timezone.now) created = models.DateTimeField(default=timezone.now)
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
owner = models.OneToOneField(User, related_name='team', blank=True, null=True) owner = models.OneToOneField(User, related_name='team', blank=True, null=True)

@ -21,24 +21,18 @@ app_name = 'users'
urlpatterns = [ urlpatterns = [
urls.url(r'^password/', include('password_reset.urls')), urls.url(r'^password/', include('password_reset.urls')),
urls.url(r'^(?P<pk>\d+)/edit/$', UserProfileEditView.as_view(), name='user-profile-edit'),
urls.url(r'^(?P<pk>\d+)/financial-info/edit/$', UserFinancialInfoEditView.as_view(), name='user-financial-info-edit'),
urls.url(r'^customers/(?P<pk>\d+)/$', CustomerProfileOpenProjectsView.as_view(), name='customer-profile-open-projects'), urls.url(r'^customers/(?P<pk>\d+)/$', CustomerProfileOpenProjectsView.as_view(), name='customer-profile-open-projects'),
urls.url(r'^customers/(?P<pk>\d+)/trashed-projects/$', CustomerProfileTrashedProjectsView.as_view(), name='customer-profile-trashed-projects'), urls.url(r'^customers/(?P<pk>\d+)/trashed-projects/$', CustomerProfileTrashedProjectsView.as_view(), name='customer-profile-trashed-projects'),
urls.url(r'^customers/(?P<pk>\d+)/current-projects/$', CustomerProfileCurrentProjectsView.as_view(), name='customer-profile-current-projects'), urls.url(r'^customers/(?P<pk>\d+)/current-projects/$', CustomerProfileCurrentProjectsView.as_view(), name='customer-profile-current-projects'),
urls.url(r'^customers/(?P<pk>\d+)/reviews/$', CustomerProfileReviewsView.as_view(), name='customer-profile-reviews'), urls.url(r'^customers/(?P<pk>\d+)/reviews/$', CustomerProfileReviewsView.as_view(), name='customer-profile-reviews'),
urls.url(r'contractors/$', ContractorFilterView.as_view(), name='contractor-filter'), urls.url(r'^contractors/$', ContractorFilterView.as_view(), name='contractor-filter'),
urls.url(r'^contractors/(?P<pk>\d+)/$', ContractorProfileDetailView.as_view(), name='contractor-profile'), urls.url(r'^contractors/(?P<pk>\d+)/$', ContractorProfileDetailView.as_view(), name='contractor-profile'),
urls.url(r'^contractor-office/(?P<pk>\d+)/$', ContractorOfficeDetailView.as_view(), name='contractor-office'), urls.url(r'^contractor-office/(?P<pk>\d+)/$', ContractorOfficeDetailView.as_view(), name='contractor-office'),
# urls.url(r'^profile/$', UserDetailView.as_view(), name='user-detail'),
urls.url(r'^$', UserListView.as_view(), name='users_list'),
urls.url(r'^test/$', send_mail_test),
# urls.url(r'^info$', UserInfoListView.as_view(), name='users_info_list'),
# urls.url(r'^(?P<pk>\d+)/$', UserView.as_view(), name='user_view'),
# urls.url(r'contractors/(?P<pk>\d+)/edit/$', ContractorProfileEditView.as_view(), name='contractor-profile-edit'), urls.url(r'^test/$', send_mail_test),
urls.url(r'(?P<pk>\d+)/edit/$', UserProfileEditView.as_view(), name='user-profile-edit'),
urls.url(r'(?P<pk>\d+)/financial-info/edit/$', UserFinancialInfoEditView.as_view(), name='user-financial-info-edit'),
# urls.url(r'contractors/(?P<pk>\d+)/financialinfo/edit/$', UserFinancialInfoEditView.as_view(), name='contractor-financical'),
] ]

Loading…
Cancel
Save