remotes/origin/setup
ArturBaybulatov 10 years ago
parent 6c5a2779e6
commit 88f32d0d63
  1. 4
      archilance/util.py
  2. 22
      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. 402
      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)

@ -136,8 +136,8 @@ class RealtyForm(forms.ModelForm):
) )
widgets = { widgets = {
'construction_type': forms.Select(attrs={'class':'selectpicker'}), 'construction_type': forms.Select(attrs={'class': 'selectpicker'}),
'building_classification': forms.Select(attrs={'class':'selectpicker'}), 'building_classification': forms.Select(attrs={'class': 'selectpicker'}),
} }
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@ -158,19 +158,13 @@ class PortfolioForm(forms.ModelForm):
fields = '__all__' fields = '__all__'
widgets = { widgets = {
'construction_type': forms.Select(attrs={'class':'selectpicker'}), 'construction_type': forms.Select(attrs={'class': 'selectpicker'}),
'building_classification': forms.Select(attrs={'class':'selectpicker'}), 'building_classification': forms.Select(attrs={'class': 'selectpicker'}),
'currency': forms.Select(attrs={'class':'selectpicker'}), 'currency': forms.Select(attrs={'class': 'selectpicker'}),
'term_type': forms.Select(attrs={'class':'selectpicker'}), 'term_type': forms.Select(attrs={'class': 'selectpicker'}),
} }
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
@ -183,8 +177,8 @@ class ContractorProjectAnswerForm(forms.ModelForm):
) )
widgets = { widgets = {
'currency': forms.Select(attrs={'class':'selectpicker'}), 'currency': forms.Select(attrs={'class': 'selectpicker'}),
'term_type': forms.Select(attrs={'class':'selectpicker'}), 'term_type': forms.Select(attrs={'class': 'selectpicker'}),
} }

@ -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,37 +9,62 @@
<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>
<div class="col-lg-12 new-p">
<p>{{ project.budget|intcomma }} <i class="fa fa-rub"></i></p> {% if request.user.is_contractor %}
</div> <div class="col-lg-12 new-p">
<p>{{ project.budget|intcomma }} <i class="fa fa-rub"></i></p>
</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">
<img src="{% static 'img/profile.jpg' %}" alt="execitor-image"> {% if project.customer.avatar %}
<img src="{{ project.customer.avatar.url }}" alt="execitor-image">
{% else %}
<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>
<div class="col-lg-3 retts">
<ul class="rettList restList2"> {% if request.user.is_contractor %}
<li>Рейтинг: <span> 0</span></li> <div class="col-lg-3 retts">
<li>Безопасные сделки: <span> 0</span></li> <ul class="rettList restList2">
<li> <li>Рейтинг: <span> 0</span></li>
<a href="javascript:void(0)">Отзывы: <li>Безопасные сделки: <span> 0</span></li>
<span> + 0</span> <li>
<small> 0</small> <a href="javascript:void(0)">Отзывы:
<mark> - 0</mark> <span> + 0</span>
</a> <small> 0</small>
</li> <mark> - 0</mark>
</ul> </a>
</div> </li>
</ul>
</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>
<div class="sroUser sroExecutor sroPro">
<div class="iconSRO"></div> {% if project.cro %}
<p>Есть допуск СРО</p> <div class="sroUser sroExecutor sroPro">
</div> <div class="iconSRO"></div>
<p>Есть допуск СРО</p>
</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,161 +118,228 @@
</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> Ответить на проект
<div class="polsF1 pols-new disTab"> </a>
<div class="col-lg-3"> <div class="polsF1 pols-new disTab">
<select class="selectpicker"> <div class="col-lg-3">
<option value="{{ user.id }}">Ответ от своего имени</option> <select class="selectpicker">
<option value="{{ user.team.id }}">{{ user.team.name }}</option> <option>Бла-бла</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>
<form action="{% url 'projects:contractor-project-answer' pk=pk %}" method="POST">
{% csrf_token %}
<input type="hidden" name="next" value="{% url 'projects:detail' pk=pk %}">
<div class="polsF1 disTab">
<div class="col-lg-3">
<div class="textAreaBlock2 text-nn box-sizing disTab"> {% if request.user.is_contractor %}
<p>Стоимость</p> <form action="{% url 'projects:contractor-project-answer' pk=pk %}" method="POST">
<input type="text" class="box-sizing" name="{{ form.budget.name }}"/> {% csrf_token %}
<input type="hidden" name="next" value="{% url 'projects:detail' pk=pk %}">
<div class="polsF1 disTab">
<div class="col-lg-3">
<div class="textAreaBlock2 text-nn box-sizing disTab">
<p>Стоимость</p>
<input type="text" class="box-sizing" name="{{ form.budget.name }}"/>
</div>
</div> </div>
</div>
<div class="col-lg-3"> <div class="col-lg-3">
<div class="textAreaBlock2 text-nn box-sizing disTab"> <div class="textAreaBlock2 text-nn box-sizing disTab">
<p>Бюджет</p> <p>Бюджет</p>
{{ form.currency }} {{ form.currency }}
</div>
</div> </div>
<div class="col-lg-6"></div>
</div> </div>
<div class="polsF1 disTab">
<div class="col-lg-3">
<div class="textAreaBlock2 text-nn box-sizing disTab">
<p>Срок</p>
<input type="text" class="box-sizing" name="{{ form.term.name }}"/>
<div class="col-lg-6"></div> </div>
</div> </div>
<div class="polsF1 disTab">
<div class="col-lg-3">
<div class="textAreaBlock2 text-nn box-sizing disTab">
<p>Срок</p>
<input type="text" class="box-sizing" name="{{ form.term.name }}"/>
<div class="col-lg-3">
<div class="textAreaBlock2 text-nn box-sizing disTab">
<p>Тип срока</p>
{{ form.term_type }}
</div>
</div> </div>
</div>
<div class="col-lg-3"> <div class="col-lg-6"></div>
<div class="textAreaBlock2 text-nn box-sizing disTab"> </div>
<p>Тип срока</p> <div class="polsF1 disTab">
{{ form.term_type }} <div class="col-lg-9">
<div class="textAreaBlock2 text-nn box-sizing disTab">
<p>Текст</p>
<textarea name="{{ form.text.name }}" id="text-new"></textarea>
</div>
</div> </div>
<div class="col-lg-3"></div>
</div> </div>
<div class="col-lg-6"></div> <div class="polsF1 disTab">
</div> <div class="col-lg-9">
<div class="polsF1 disTab"> <div class="textAreaBlock2 text-nn box-sizing disTab">
<div class="col-lg-9"> {% for p in user.portfolio.all %}
<div class="textAreaBlock2 text-nn box-sizing disTab"> <h3>{{ p }}</h3>
<p>Текст</p> {% endfor %}
<textarea name="{{ form.text.name }}" id="text-new"></textarea> </div>
</div> </div>
<div class="col-lg-3"></div>
</div> </div>
<div class="col-lg-3"></div>
</div>
<div class="polsF1 disTab"> <div class="polsF1 disTab">
<div class="col-lg-9"> <div class="col-lg-3"><input type="submit" value="Создать"/></div>
<div class="textAreaBlock2 text-nn box-sizing disTab">
{% for p in user.portfolio.all %}
<h3>{{ p }}</h3>
{% endfor %}
</div>
</div> </div>
<div class="col-lg-3"></div> </form>
</div>
<div class="polsF1 disTab"> {% elif request.user.is_customer %}
<div class="col-lg-3"><input type="submit" value="Создать"/></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>
</form> <div class="col-lg-12 compareBlock">
</div> <div class="col-lg-2 col-lg-offset-5">
<div class="candidateBlock disTab"> <p>Сравнить кандидатов</p>
{% for answer in project.answers.all %}
<div class="candidate can-new">
<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 }} [{{ answer.contractor }}]</a>
</p>
<p class="navv2">{{ answer.contractor.created }}</p>
</div> </div>
<div class="col-lg-3 retts"> </div>
<ul class="rettList restList2"> <div class="col-lg-12 exNew">
<li>Рейтинг: <span> 0</span></li> <p>Новые исполнители</p>
<li>Безопасные сделки: <span> 0</span></li> </div>
<li> <div class="candidateBlock disTab">
<a href="javascript:void(0)">Отзывы: {% for answer in project.answers.all %}
<span> + 0</span> <div class="candidate">
<small> 0</small> <div class="col-lg-4">
<mark> - 0</mark> <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> </a>
</li>
</ul>
{% if answer.contractor.cro %}
<div class="sroUser sroExecutor">
<div class="iconSRO"></div>
<p>Есть допуск СРО</p>
</div> </div>
{% endif %} <div class="gallMini disTab">
</div> <div class="col-lg-3">
<div class="col-lg-2 listCens"> <div class="insetCol box-sizing disTab">
<p>Цена: <div class="imgGal">
<span> {{ answer.budget }}</span> <div class="imgFigure"></div>
<i class="fa fa-rub"></i> </div>
</p> </div>
<p> </div>
Срок: <span>{{ answer.term }} {{ answer.term_type }}</span> </div>
</p> <div class="commBlock44 disTab">
<p>Опубликован: {{ answer.created }}</p> {# <div class="comm44 disTab">#}
</div> {# <div class="col-lg-10 col-lg-offset-1">#}
<div class="col-lg-3 retts"> {# <p class="nameComm">#}
<a href="" class="candLink candLink3"> {# Иванов Петр Иванович#}
отказ {# </p>#}
</a> {# <span class="dateComm44">#}
</div> {# 13.0.2016 / 21:05#}
<div class="commBlock44 comm-new disTab"> {# </span>#}
{# <div class="comm44 disTab">#} {# <div class="stars box-sizing">#}
{# <div class="col-lg-10 col-lg-offset-1">#} {# <span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span>#}
{# <p class="nameComm">#} {# <span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span>#}
{# Иванов Петр Иванович#} {# <span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span>#}
{# </p>#} {# <span class="glyphicon glyphicon-star" aria-hidden="true"></span>#}
{# <span class="dateComm44">#} {# <span class="glyphicon glyphicon-star" aria-hidden="true"></span>#}
{# 13.0.2016 / 21:05#} {# </div>#}
{# </span>#} {# <p class="textComm44">Lorem ipsum dolor sit amet</p>#}
{# <div class="stars box-sizing">#} {# </div>#}
{# <span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span>#} {# </div>#}
{# <span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span>#} </div>
{# <span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span>#} </div>
{# <span class="glyphicon glyphicon-star" aria-hidden="true"></span>#} {% endfor %}
{# <span class="glyphicon glyphicon-star" aria-hidden="true"></span>#}
{# </div>#}
{# <p class="textComm44">#}
{# Text#}
{# </p>#}
{# </div>#}
{# </div>#}
</div>
</div> </div>
{% endfor %} {% endif %}
</div> </div>
<div class="col-lg-12 pagin">
{% include 'partials/pagination.html' %}
</div>
{% include 'partials/footer.html' %} {% include 'partials/footer.html' %}
</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