remotes/origin/PR-39
ArturBaybulatov 10 years ago
parent ea9d8920c0
commit 1a7cab1757
  1. 4
      archilance/management/commands/generate_portfolios.py
  2. 4
      archilance/management/commands/generate_projects.py
  3. 4
      archilance/management/commands/generate_work_sells.py
  4. 2
      archilance/management/commands/tmp.py
  5. 6
      common/templatetags/common_tags.py
  6. 30
      projects/models.py
  7. 10
      projects/templates/comparison.html
  8. 24
      projects/templates/project_detail.html
  9. 27
      projects/views.py
  10. 78
      templates/partials/header.html
  11. 11
      users/models.py
  12. 4
      work_sell/models.py

@ -7,7 +7,7 @@ import random
from archilance import util from archilance import util
from common.models import Location from common.models import Location
from projects.models import Portfolio, PortfolioPhoto, CURRENCIES, TERMS, BuildingClassfication , ConstructionType from projects.models import Portfolio, PortfolioPhoto, CURRENCIES, TERM_TYPES, BuildingClassfication , ConstructionType
from specializations.models import Specialization from specializations.models import Specialization
from users.models import User, Team, GENDERS from users.models import User, Team, GENDERS
@ -42,7 +42,7 @@ class Command(BaseCommand):
budget=util.random_amount(), budget=util.random_amount(),
currency=_.sample(CURRENCIES)[0], currency=_.sample(CURRENCIES)[0],
term=_.random(0, 20), term=_.random(0, 20),
term_type=_.sample(TERMS)[0], term_type=_.sample(TERM_TYPES)[0],
worksell=_.sample((True, False)), worksell=_.sample((True, False)),
) )

@ -6,7 +6,7 @@ import pydash as _; _.map = _.map_; _.filter = _.filter_
import random import random
from archilance import util from archilance import util
from projects.models import Project, Order, CURRENCIES, TERMS, Specialization, Realty from projects.models import Project, Order, CURRENCIES, TERM_TYPES, Specialization, Realty
from users.models import User from users.models import User
@ -62,7 +62,7 @@ class Command(BaseCommand):
price_and_term_required=_.sample((True, False)), price_and_term_required=_.sample((True, False)),
deal_type=_.sample(Project.DEAL_TYPES)[0], deal_type=_.sample(Project.DEAL_TYPES)[0],
term=_.random(0, 20), term=_.random(0, 20),
term_type=_.sample(TERMS)[0], term_type=_.sample(TERM_TYPES)[0],
text=util.lorem(_.random(5, 30)), text=util.lorem(_.random(5, 30)),
work_type=_.sample(Project.WORK_TYPES)[0], work_type=_.sample(Project.WORK_TYPES)[0],
state='active', state='active',

@ -7,7 +7,7 @@ import random
from archilance import util from archilance import util
from common.models import Location from common.models import Location
from projects.models import TERMS, CURRENCIES, BuildingClassfication, ConstructionType from projects.models import TERM_TYPES, CURRENCIES, BuildingClassfication, ConstructionType
from specializations.models import Specialization from specializations.models import Specialization
from users.models import User from users.models import User
from work_sell.models import WorkSell, WorkSellPhoto from work_sell.models import WorkSell, WorkSellPhoto
@ -27,7 +27,7 @@ class Command(BaseCommand):
description=util.lorem(), description=util.lorem(),
name=util.lorem(words=_.random(2, 20), sentences=1), name=util.lorem(words=_.random(2, 20), sentences=1),
term=_.random(0, 20), term=_.random(0, 20),
term_type=_.sample(TERMS)[0], term_type=_.sample(TERM_TYPES)[0],
) )
ws.save() ws.save()

@ -7,7 +7,7 @@ import random
from archilance import util from archilance import util
from common.models import Location from common.models import Location
from projects.models import Project, Order, CURRENCIES, TERMS, Specialization, Realty from projects.models import Project, Order, CURRENCIES, TERM_TYPES, Specialization, Realty
from users.models import User, Team from users.models import User, Team

@ -124,4 +124,10 @@ def fa_currency_classes(currency):
return 'fa fa-%s' % currency_class return 'fa fa-%s' % currency_class
@register.filter
def get(dic, key):
if isinstance(dic, dict):
return dic.get(key)
# import code; code.interact(local=dict(globals(), **locals())) # import code; code.interact(local=dict(globals(), **locals()))

@ -17,13 +17,20 @@ CURRENCIES = (
('eur', 'EUR'), ('eur', 'EUR'),
) )
TERMS = ( TERM_TYPES = (
('project', 'За проект'),
('hour', 'За час'),
('day', 'За день'), ('day', 'За день'),
('hour', 'За час'),
('month', 'За месяц'), ('month', 'За месяц'),
('project', 'За проект'),
) )
TERM_TYPE_MORPHS = {
'day': 'день,дня,дней',
'hour': 'час,часа,часов',
'month': 'месяц,месяца,месяцев',
'project': 'проект,проекта,проектов'
}
class BuildingClassfication(models.Model): class BuildingClassfication(models.Model):
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
@ -92,7 +99,7 @@ class Project(models.Model, HitCountMixin):
specialization = TreeForeignKey(Specialization, related_name='projects') specialization = TreeForeignKey(Specialization, related_name='projects')
state = models.CharField(default='active', max_length=20, choices=STATES) state = models.CharField(default='active', max_length=20, choices=STATES)
term = models.IntegerField(default=0) term = models.IntegerField(default=0)
term_type = models.CharField(max_length=20, choices=TERMS, default='hour') term_type = models.CharField(max_length=20, choices=TERM_TYPES, default='hour')
text = models.TextField(blank=True) text = models.TextField(blank=True)
work_type = models.IntegerField(default=1, choices=WORK_TYPES) work_type = models.IntegerField(default=1, choices=WORK_TYPES)
@ -131,7 +138,7 @@ class Answer(models.Model):
project = models.ForeignKey(Project, related_name='answers') project = models.ForeignKey(Project, related_name='answers')
secure_deal_only = models.BooleanField(default=False) secure_deal_only = models.BooleanField(default=False)
term = models.IntegerField(blank=True, null=True) term = models.IntegerField(blank=True, null=True)
term_type = models.CharField(max_length=10, choices=TERMS, blank=True, null=True) term_type = models.CharField(max_length=10, choices=TERM_TYPES, blank=True, null=True)
is_archive = models.BooleanField(default=False) is_archive = models.BooleanField(default=False)
rejected = models.BooleanField(default=False) rejected = models.BooleanField(default=False)
@ -141,15 +148,6 @@ class Answer(models.Model):
def get_first_message(self): def get_first_message(self):
return self.messages.first().text return self.messages.first().text
def get_term_type_labels(self):
term_type_labels = {
'hour': 'час,часа,часов',
'day': 'день,дня,дней',
'month': 'месяц,месяца,месяцев',
'project': 'проект,проект,проект'
}
return term_type_labels.get(self.term_type)
def __str__(self): def __str__(self):
return "{author}'s answer ({id})".format(author=type(self.author).__name__, id=self.pk) return "{author}'s answer ({id})".format(author=type(self.author).__name__, id=self.pk)
@ -252,7 +250,7 @@ class Stage(models.Model):
order = models.ForeignKey(Order, related_name='stages') order = models.ForeignKey(Order, related_name='stages')
result = models.CharField(max_length=255) result = models.CharField(max_length=255)
term = models.DateField() term = models.DateField()
term_type = models.CharField(max_length=10, choices=TERMS, default='hour') term_type = models.CharField(max_length=10, choices=TERM_TYPES, default='hour')
status = models.CharField(choices=STATUSES, max_length=30, default='not_agreed') status = models.CharField(choices=STATUSES, max_length=30, default='not_agreed')
created = models.DateTimeField(default=timezone.now) created = models.DateTimeField(default=timezone.now)
pos = models.IntegerField(default=0, null=True, blank=True) pos = models.IntegerField(default=0, null=True, blank=True)
@ -295,7 +293,7 @@ class Portfolio(models.Model):
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
specialization = TreeForeignKey(Specialization, related_name='portfolios', null=True, blank=True) specialization = TreeForeignKey(Specialization, related_name='portfolios', null=True, blank=True)
term = models.IntegerField(default=0, null=True, blank=True) term = models.IntegerField(default=0, null=True, blank=True)
term_type = models.CharField(max_length=20, choices=TERMS, default='hour', null=True, blank=True) term_type = models.CharField(max_length=20, choices=TERM_TYPES, default='hour', null=True, blank=True)
user = models.ForeignKey(User, related_name='portfolios', null=True, blank=True) user = models.ForeignKey(User, related_name='portfolios', null=True, blank=True)
worksell = models.BooleanField(default=False) worksell = models.BooleanField(default=False)

@ -45,13 +45,15 @@
<td>{{ cand.answer.budget }} <i class="{% fa_currency_classes cand.answer.currency %}"></i></td> <td>{{ cand.answer.budget }} <i class="{% fa_currency_classes cand.answer.currency %}"></i></td>
<td> <td>
{{ cand.answer.term }}<br> <span> {% if cand.answer.term_type == 'project' %}
{% morph_words cand.answer.term cand.answer.get_term_type_labels %} За проект
</span> {% else %}
{% morph cand.answer.term TERM_TYPE_MORPHS|get:cand.answer.term_type %}
{% endif %}
</td> </td>
<td> <td>
<span class="glyphicon glyphicon-info-sign" aria-hidden="true" data-toggle="tooltip" data-placement="right" title="{{ cand.answer.get_first_message }}"></span> <span class="glyphicon glyphicon-info-sign" aria-hidden="true" data-tooltip data-placement="right" title="{{ cand.answer.get_first_message }}"></span>
</td> </td>
<td> <td>

@ -240,7 +240,11 @@
<i class="{% fa_currency_classes answer.currency %}"></i> <i class="{% fa_currency_classes answer.currency %}"></i>
</p> </p>
<p> <p>
Срок: <span>{{ answer.term }} {{ answer.get_currency_display }} {{ answer.get_term_type_display|decap }}</span> {% if answer.term_type == 'project' %}
Срок: <span>За проект</span>
{% else %}
Срок: <span>{% morph answer.term TERM_TYPE_MORPHS|get:answer.term_type %}</span>
{% endif %}
</p> </p>
<p>Опубликован: {{ answer.created|date:'M d, Y' }}</p> <p>Опубликован: {{ answer.created|date:'M d, Y' }}</p>
</div> </div>
@ -566,7 +570,11 @@
<i class="{% fa_currency_classes answer.currency %}"></i> <i class="{% fa_currency_classes answer.currency %}"></i>
</p> </p>
<p> <p>
Срок: <span>{{ answer.term }} {{ answer.get_currency_display }} {{ answer.get_term_type_display|decap }}</span> {% if answer.term_type == 'project' %}
Срок: <span>За проект</span>
{% else %}
Срок: <span>{% morph answer.term TERM_TYPE_MORPHS|get:answer.term_type %}</span>
{% endif %}
</p> </p>
<p>Опубликован: {{ answer.created|date:'M d, Y' }}</p> <p>Опубликован: {{ answer.created|date:'M d, Y' }}</p>
</div> </div>
@ -722,7 +730,11 @@
<i class="{% fa_currency_classes answer.currency %}"></i> <i class="{% fa_currency_classes answer.currency %}"></i>
</p> </p>
<p> <p>
Срок: <span>{{ answer.term }} {{ answer.get_currency_display }} {{ answer.get_term_type_display|decap }}</span> {% if answer.term_type == 'project' %}
Срок: <span>За проект</span>
{% else %}
Срок: <span>{% morph answer.term TERM_TYPE_MORPHS|get:answer.term_type %}</span>
{% endif %}
</p> </p>
<p>Опубликован: {{ answer.created|date:'M d, Y' }}</p> <p>Опубликован: {{ answer.created|date:'M d, Y' }}</p>
</div> </div>
@ -876,7 +888,11 @@
<i class="{% fa_currency_classes answer.currency %}"></i> <i class="{% fa_currency_classes answer.currency %}"></i>
</p> </p>
<p> <p>
Срок: <span>{{ answer.term }} {{ answer.get_currency_display }} {{ answer.get_term_type_display|decap }}</span> {% if answer.term_type == 'project' %}
Срок: <span>За проект</span>
{% else %}
Срок: <span>{% morph answer.term TERM_TYPE_MORPHS|get:answer.term_type %}</span>
{% endif %}
</p> </p>
<p>Опубликован: {{ answer.created|date:'M d, Y' }}</p> <p>Опубликован: {{ answer.created|date:'M d, Y' }}</p>
</div> </div>

@ -18,12 +18,26 @@ import pydash as _; _.map = _.map_; _.filter = _.filter_
import re import re
from .mixins import LastAccessMixin from .mixins import LastAccessMixin
from .models import Arbitration, Project, ProjectFile, Portfolio, PortfolioPhoto, Candidate, Answer, AnswerFile, AnswerMessage, Realty, Order
from archilance import util from archilance import util
from archilance.mixins import BaseMixin from archilance.mixins import BaseMixin
from users.models import User, Team from users.models import User, Team
from work_sell.models import Picture, WorkSell, WorkSellPhoto from work_sell.models import Picture, WorkSell, WorkSellPhoto
from .models import (
Answer,
AnswerFile,
AnswerMessage,
Arbitration,
Candidate,
Order,
Portfolio,
PortfolioPhoto,
Project,
ProjectFile,
Realty,
TERM_TYPE_MORPHS,
)
from .forms import ( from .forms import (
ContractorPortfolioTrashForm, ContractorPortfolioTrashForm,
CustomerProjectDeleteForm, CustomerProjectDeleteForm,
@ -45,7 +59,9 @@ class ProjectDetailWithAnswerView(BaseMixin, View):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
context = self.get_context_data(**_.merge({}, request.GET, kwargs)) context = self.get_context_data(**_.merge({}, request.GET, kwargs))
context.update({'TERM_TYPE_MORPHS': TERM_TYPE_MORPHS})
project = get_object_or_404(Project, pk=kwargs.get('pk')) project = get_object_or_404(Project, pk=kwargs.get('pk'))
context.update({'project': project}) context.update({'project': project})
@ -594,6 +610,13 @@ class CustomerProjectDeleteView(View):
class ProjectComparisonView(DetailView): class ProjectComparisonView(DetailView):
model = Project model = Project
template_name = 'comparison.html' template_name = 'comparison.html'
def get_context_data(self, **kwargs):
c = super().get_context_data(**kwargs)
c['TERM_TYPE_MORPHS'] = TERM_TYPE_MORPHS
return c
def add_candidate(request, answer_id, project_id): def add_candidate(request, answer_id, project_id):

@ -7,25 +7,44 @@
<div class="container-fluid topMain"> <div class="container-fluid topMain">
<div class="row"> <div class="row">
<div class="col-lg-3"> <div class="col-lg-3">
<div class="logo" onClick="window.location='/'"></div> <a href="/"><div class="logo"></div></a>
</div> </div>
{% activeurl %}
{% if request.user.is_authenticated %} {% activeurl %}
<div class="col-lg-7"> {% if request.user.is_authenticated %}
<ul class="mainMenu"> <div class="col-lg-7">
<li class="icon_tm1"> <ul class="mainMenu">
<a href="{% url 'projects:project-filter' %}">Биржа проектов</a> <li class="icon_tm1">
<span></span> <a href="{% url 'projects:project-filter' %}">Биржа проектов</a>
</li> <span></span>
</li>
{% if request.user.is_contractor %}
<li class="officeList icon_tml"> {% if request.user.is_contractor %}
<a href="{% url 'users:contractor-office' pk=request.user.pk %}">Мой офис</a> <li class="officeList icon_tml">
<a href="{% url 'users:contractor-office' pk=request.user.pk %}">Мой офис</a>
<span></span>
</li>
{% endif %}
{% if request.user.is_customer %}
<li class="icon_tm2">
<a href="{% url 'users:contractor-filter' %}">Поиск исполнителей</a>
<span></span>
</li>
<li class="icon_tm3">
<a href="{% url 'work_sell:list' %}">Работы на продажу</a>
<span></span>
</li>
{% endif %}
</ul>
</div>
{% else %}
<div class="col-lg-7">
<ul class="mainMenu">
<li class="icon_tm1">
<a href="{% url 'projects:project-filter' %}">Биржа проектов</a>
<span></span> <span></span>
</li> </li>
{% endif %}
{% if request.user.is_customer %}
<li class="icon_tm2"> <li class="icon_tm2">
<a href="{% url 'users:contractor-filter' %}">Поиск исполнителей</a> <a href="{% url 'users:contractor-filter' %}">Поиск исполнителей</a>
<span></span> <span></span>
@ -34,28 +53,11 @@
<a href="{% url 'work_sell:list' %}">Работы на продажу</a> <a href="{% url 'work_sell:list' %}">Работы на продажу</a>
<span></span> <span></span>
</li> </li>
{% endif %} </ul>
</ul> </div>
</div> {% endif %}
{% else %} {% endactiveurl %}
<div class="col-lg-7">
<ul class="mainMenu">
<li class="icon_tm1">
<a href="{% url 'projects:project-filter' %}">Биржа проектов</a>
<span></span>
</li>
<li class="icon_tm2">
<a href="{% url 'users:contractor-filter' %}">Поиск исполнителей</a>
<span></span>
</li>
<li class="icon_tm3">
<a href="{% url 'work_sell:list' %}">Работы на продажу</a>
<span></span>
</li>
</ul>
</div>
{% endif %}
{% endactiveurl %}
{% if request.user.is_authenticated %} {% if request.user.is_authenticated %}
<div class="col-lg-2"> <div class="col-lg-2">
<div class="imgProfile"> <div class="imgProfile">

@ -174,12 +174,17 @@ class User(AbstractBaseUser, PermissionsMixin):
return self.avatar return self.avatar
def summary(self): def summary(self):
age = relativedelta(timezone.now(), util.to_local_datetime(self.date_of_birth)).years if self.date_of_birth:
years = relativedelta(timezone.now(), util.to_local_datetime(self.date_of_birth)).years
age = '%s %s' % (years, util.morph(years, ('год', 'года', 'лет')))
dob = formats.date_format(self.date_of_birth, 'DATE_FORMAT')
else:
age = dob = None
return _.join(_.filter(( return _.join(_.filter((
self.get_gender_display(), self.get_gender_display(),
'%s %s' % (age, util.morph(age, ('год', 'года', 'лет'))), age,
formats.date_format(self.date_of_birth, 'DATE_FORMAT'), dob,
), _.identity), ', ') ), _.identity), ', ')
USERNAME_FIELD = 'username' USERNAME_FIELD = 'username'

@ -4,7 +4,7 @@ from mptt.models import TreeForeignKey
from sorl.thumbnail import ImageField from sorl.thumbnail import ImageField
from users.models import User, Team from users.models import User, Team
from projects.models import BuildingClassfication, ConstructionType, TERMS, CURRENCIES from projects.models import BuildingClassfication, ConstructionType, TERM_TYPES, CURRENCIES
from specializations.models import Specialization from specializations.models import Specialization
@ -22,7 +22,7 @@ class WorkSell(models.Model):
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
specialization = TreeForeignKey(Specialization, related_name='worksells', null=True, blank=True) specialization = TreeForeignKey(Specialization, related_name='worksells', null=True, blank=True)
term = models.IntegerField(default=0, null=True, blank=True) term = models.IntegerField(default=0, null=True, blank=True)
term_type = models.CharField(max_length=20, choices=TERMS, default='hour', null=True, blank=True) term_type = models.CharField(max_length=20, choices=TERM_TYPES, default='hour', null=True, blank=True)
def __str__(self): def __str__(self):
return self.name return self.name

Loading…
Cancel
Save