optimizations

remotes/origin/PR-39
PekopT 9 years ago
parent da3793495d
commit 669d1d5db0
  1. 1
      api/test.py
  2. 1
      api/urls.py
  3. 72
      api/views.py
  4. 10
      archilance/management/commands/generate_build_classifs.py
  5. 10
      archilance/management/commands/generate_constr_types.py
  6. 17
      archilance/management/commands/generate_locations.py
  7. 11
      archilance/management/commands/generate_perm_groups.py
  8. 18
      archilance/management/commands/generate_portfolios.py
  9. 10
      archilance/management/commands/generate_projects.py
  10. 14
      archilance/management/commands/generate_realties.py
  11. 14
      archilance/management/commands/generate_reviews.py
  12. 16
      archilance/management/commands/generate_specializations.py
  13. 10
      archilance/management/commands/generate_superuser.py
  14. 15
      archilance/management/commands/generate_teams.py
  15. 19
      archilance/management/commands/generate_users.py
  16. 15
      archilance/management/commands/generate_work_sells.py
  17. 16
      archilance/middlewares.py
  18. 7
      archilance/mixins.py
  19. 8
      archilance/settings/base.py
  20. 80
      archilance/urls.py
  21. 34
      archilance/util.py
  22. 26
      archilance/views.py
  23. 6
      archilance/wsgi.py
  24. 21
      assets/css/main.css
  25. BIN
      assets/img/skype.png
  26. BIN
      assets/img/user-4.png
  27. BIN
      assets/img/user-5.png
  28. 8
      assets/index.js
  29. 5
      chat/admin.py
  30. 27
      chat/chat.py
  31. 5
      chat/filters.py
  32. 1
      chat/forms.py
  33. 2
      chat/models.py
  34. 1
      chat/response.py
  35. 10
      chat/serializers.py
  36. 3
      chat/settings.example.py
  37. 2
      chat/tests.py
  38. 1
      chat/utils.py
  39. 60
      chat/views.py
  40. 9
      common/admin.py
  41. 6
      common/forms.py
  42. 7
      common/middleware.py
  43. 2
      common/models.py
  44. 2
      common/tests.py
  45. 3
      common/urls.py
  46. 14
      common/views.py
  47. 4
      projects/admin.py
  48. 3
      projects/apps.py
  49. 1
      projects/filters.py
  50. 25
      projects/forms.py
  51. BIN
      projects/locale/ru_RU/LC_MESSAGES/django.mo
  52. 48
      projects/locale/ru_RU/LC_MESSAGES/django.po
  53. 38
      projects/migrations/0047_auto_20161014_2349.py
  54. 43
      projects/models.py
  55. 19
      projects/serializers.py
  56. 6
      projects/signals.py
  57. 498
      projects/templates/_trash/project_form.html
  58. 28
      projects/templates/_trash/testport.html
  59. 8
      projects/templates/chattest.html
  60. 296
      projects/templates/comparison.html
  61. 241
      projects/templates/contractor_portfolio_edit.html
  62. 700
      projects/templates/customer_project_create.html
  63. 703
      projects/templates/customer_project_edit.html
  64. 89
      projects/templates/partials/modals/project_work_type_suggestion.html
  65. 155
      projects/templates/portfolio_create.html
  66. 2213
      projects/templates/project_detail.html
  67. 381
      projects/templates/project_filter.html
  68. 16
      projects/templatetags/project_tags.py
  69. 2
      projects/tests.py
  70. 16
      projects/urls.py
  71. 37
      projects/views.py
  72. 1
      ratings/admin.py
  73. 6
      ratings/models.py
  74. 2
      ratings/tests.py
  75. 2
      ratings/views.py
  76. 1
      reviews/admin.py
  77. 2
      reviews/apps.py
  78. 3
      reviews/forms.py
  79. 2
      reviews/models.py
  80. 4
      reviews/serializers.py
  81. 2
      reviews/signals.py
  82. 2
      reviews/tests.py
  83. 6
      reviews/views.py
  84. 8
      specializations/admin.py
  85. 2
      specializations/filters.py
  86. 21
      specializations/migrations/0003_specialization_order.py
  87. 24
      specializations/migrations/0004_auto_20161014_2344.py
  88. 8
      specializations/models.py
  89. 2
      specializations/tests.py
  90. 1
      specializations/urls.py
  91. 13
      specializations/views.py
  92. 4
      users/admin.py
  93. 2
      users/apps.py
  94. 2
      users/backend.py
  95. 5
      users/filters.py
  96. 17
      users/forms.py
  97. 12
      users/helpers.py
  98. BIN
      users/locale/ru_RU/LC_MESSAGES/django.mo
  99. 42
      users/locale/ru_RU/LC_MESSAGES/django.po
  100. 1
      users/mixins.py
  101. Some files were not shown because too many files have changed in this diff Show More

@ -3,4 +3,3 @@ from rest_framework.test import APITestCase
class FileUploadTests(APITestCase): class FileUploadTests(APITestCase):
pass pass

@ -22,7 +22,6 @@ from .views import (
WorkSellViewSet, WorkSellViewSet,
) )
router = routers.DefaultRouter() router = routers.DefaultRouter()
router.register(r'answers', AnswerViewSet) router.register(r'answers', AnswerViewSet)

@ -4,41 +4,33 @@ from rest_framework import permissions
from rest_framework.pagination import PageNumberPagination from rest_framework.pagination import PageNumberPagination
from rest_framework.viewsets import ModelViewSet from rest_framework.viewsets import ModelViewSet
from projects.models import Project, Realty, Stage, Portfolio, PortfolioPhoto, Answer, AnswerFile, Order from chat.filters import MessageFilterSet, NoteFilterSet, DocumentFilterSet
from chat.models import Message, Notes, Documents, NewMessage
from projects.serializers import ( from chat.serializers import MessageSerializer, NoteSerializer, DocumentsSerializer
ProjectSerializer, RealtySerializer, StageSerializer, PortfolioSerializer, from common.filters import LocationFilterSet
PortfolioPhotoSerializer, AnswerSerializer, OrderSerializer, AnswerFileSerializer, from common.models import Location
) from common.serializers import LocationSerializer
from projects.filters import ( from projects.filters import (
ProjectFilterSet, RealtyFilterSet, StageFilterSet, PortfolioFilterSet, OrderFilterSet, ProjectFilterSet, RealtyFilterSet, StageFilterSet, PortfolioFilterSet, OrderFilterSet,
PortfolioPhotoFilterSet, AnswerFilterSet, PortfolioPhotoFilterSet, AnswerFilterSet,
) )
from projects.models import Project, Realty, Stage, Portfolio, PortfolioPhoto, Answer, Order
from projects.serializers import (
ProjectSerializer, RealtySerializer, StageSerializer, PortfolioSerializer,
PortfolioPhotoSerializer, AnswerSerializer, OrderSerializer, )
from reviews.filters import ReviewFilterSet
from reviews.models import Review
from reviews.serializers import ReviewSerializer
from specializations.filters import SpecializationFilterSet
from specializations.models import Specialization from specializations.models import Specialization
from specializations.serializers import SpecializationSerializer from specializations.serializers import SpecializationSerializer
from specializations.filters import SpecializationFilterSet from users.filters import UserFilterSet, TeamFilterSet
from users.models import User, ContractorResumeFiles, ContractorResume, Team from users.models import User, ContractorResumeFiles, ContractorResume, Team
from users.serializers import UserSerializer, ContractorResumeFilesSerializer, ContractorResumeSerializer, TeamSerializer from users.serializers import UserSerializer, ContractorResumeFilesSerializer, ContractorResumeSerializer, \
from users.filters import UserFilterSet, TeamFilterSet, ContractorResumeFilesFilterSet, ContractorResumeFilterSet TeamSerializer
from work_sell.filters import WorkSellFilterSet, WorkSellPhotoFilterSet
from common.models import Location
from common.serializers import LocationSerializer
from common.filters import LocationFilterSet
from chat.models import Message, Notes, Documents, NewMessage
from chat.serializers import MessageSerializer, NoteSerializer, DocumentsSerializer
from chat.filters import MessageFilterSet, NoteFilterSet, DocumentFilterSet
from reviews.models import Review
from reviews.serializers import ReviewSerializer
from reviews.filters import ReviewFilterSet
from work_sell.models import WorkSell, WorkSellPhoto from work_sell.models import WorkSell, WorkSellPhoto
from work_sell.serializers import WorkSellSerializer, WorkSellPhotoSerializer from work_sell.serializers import WorkSellSerializer, WorkSellPhotoSerializer
from work_sell.filters import WorkSellFilterSet, WorkSellPhotoFilterSet
class ContractorResumeFilesViewSet(ModelViewSet): class ContractorResumeFilesViewSet(ModelViewSet):
@ -83,7 +75,9 @@ class DocumentViewSet(ModelViewSet):
if search_param: if search_param:
# import code; code.interact(local=dict(globals(), **locals())) # import code; code.interact(local=dict(globals(), **locals()))
if search_param == 'in': if search_param == 'in':
queryset = queryset.filter(Q(sender__in=[sender_id, recipent_id]),Q(recipent__in=[sender_id, recipent_id])).filter(order__isnull=True).order_by('created') queryset = queryset.filter(Q(sender__in=[sender_id, recipent_id]),
Q(recipent__in=[sender_id, recipent_id])).filter(
order__isnull=True).order_by('created')
return queryset return queryset
@ -91,6 +85,7 @@ class ProjectViewSet(ModelViewSet):
queryset = Project.objects.all() queryset = Project.objects.all()
serializer_class = ProjectSerializer serializer_class = ProjectSerializer
filter_class = ProjectFilterSet filter_class = ProjectFilterSet
# permission_classes = (permissions.IsAuthenticatedOrReadOnly,) # permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
def get_queryset(self): def get_queryset(self):
@ -118,7 +113,8 @@ class NoteViewSet(ModelViewSet):
if search_param: if search_param:
# import code; code.interact(local=dict(globals(), **locals())) # import code; code.interact(local=dict(globals(), **locals()))
if search_param == 'in': if search_param == 'in':
queryset = queryset.filter(Q(sender__in=[sender_id,recipent_id]),Q(recipent__in=[sender_id,recipent_id])).order_by('created') queryset = queryset.filter(Q(sender__in=[sender_id, recipent_id]),
Q(recipent__in=[sender_id, recipent_id])).order_by('created')
return queryset return queryset
@ -135,11 +131,11 @@ class MessageViewSet(ModelViewSet):
if search_param: if search_param:
# import code; code.interact(local=dict(globals(), **locals())) # import code; code.interact(local=dict(globals(), **locals()))
if search_param == 'in': if search_param == 'in':
queryset = queryset.filter(Q(sender__in=[sender_id,recipent_id]),Q(recipent__in=[sender_id,recipent_id])).\ queryset = queryset.filter(Q(sender__in=[sender_id, recipent_id]),
filter(order__isnull=True).\ Q(recipent__in=[sender_id, recipent_id])). \
filter(order__isnull=True). \
filter(~Q(sender=F('recipent'))) filter(~Q(sender=F('recipent')))
queryset = queryset.order_by('created') queryset = queryset.order_by('created')
return queryset return queryset
@ -187,8 +183,8 @@ class LocationViewSet(ModelViewSet):
class PortfolioPagination(PageNumberPagination): class PortfolioPagination(PageNumberPagination):
page_size = settings.API_PAGE_SIZE # Default page size page_size = settings.API_PAGE_SIZE # Default page size
page_size_query_param = 'page_size' # Provide custom page size through a query param page_size_query_param = 'page_size' # Provide custom page size through a query param
max_page_size = 1000 max_page_size = 1000
@ -205,13 +201,12 @@ class PortfolioPhotoViewSet(ModelViewSet):
filter_class = PortfolioPhotoFilterSet filter_class = PortfolioPhotoFilterSet
class WorkSellPagination(PageNumberPagination): class WorkSellPagination(PageNumberPagination):
page_size = settings.API_PAGE_SIZE # Default page size page_size = settings.API_PAGE_SIZE # Default page size
page_size_query_param = 'page_size' # Provide custom page size through a query param page_size_query_param = 'page_size' # Provide custom page size through a query param
max_page_size = 1000 max_page_size = 1000
class WorkSellViewSet(ModelViewSet): class WorkSellViewSet(ModelViewSet):
queryset = WorkSell.objects.all() queryset = WorkSell.objects.all()
serializer_class = WorkSellSerializer serializer_class = WorkSellSerializer
@ -219,15 +214,12 @@ class WorkSellViewSet(ModelViewSet):
pagination_class = WorkSellPagination pagination_class = WorkSellPagination
class WorkSellPhotoViewSet(ModelViewSet): class WorkSellPhotoViewSet(ModelViewSet):
queryset = WorkSellPhoto.objects.all() queryset = WorkSellPhoto.objects.all()
serializer_class = WorkSellPhotoSerializer serializer_class = WorkSellPhotoSerializer
filter_class = WorkSellPhotoFilterSet filter_class = WorkSellPhotoFilterSet
class AnswerViewSet(ModelViewSet): class AnswerViewSet(ModelViewSet):
queryset = Answer.objects.all() queryset = Answer.objects.all()
serializer_class = AnswerSerializer serializer_class = AnswerSerializer

@ -1,11 +1,9 @@
from django.contrib.auth.models import Group, Permission import pydash as _;
from django.contrib.contenttypes.models import ContentType
from django.core.management import BaseCommand from django.core.management import BaseCommand
from django.utils import timezone
import pydash as _; _.map = _.map_; _.filter = _.filter_
import random
from archilance import util _.map = _.map_;
_.filter = _.filter_
from projects.models import BuildingClassfication from projects.models import BuildingClassfication

@ -1,11 +1,9 @@
from django.contrib.auth.models import Group, Permission import pydash as _;
from django.contrib.contenttypes.models import ContentType
from django.core.management import BaseCommand from django.core.management import BaseCommand
from django.utils import timezone
import pydash as _; _.map = _.map_; _.filter = _.filter_
import random
from archilance import util _.map = _.map_;
_.filter = _.filter_
from projects.models import ConstructionType from projects.models import ConstructionType

@ -1,11 +1,9 @@
from django.contrib.auth.models import Group, Permission import pydash as _;
from django.contrib.contenttypes.models import ContentType
from django.core.management import BaseCommand from django.core.management import BaseCommand
from django.utils import timezone
import pydash as _; _.map = _.map_; _.filter = _.filter_
import random
from archilance import util _.map = _.map_;
_.filter = _.filter_
from common.models import Location from common.models import Location
@ -15,14 +13,13 @@ class Command(BaseCommand):
print('Generating locations...') print('Generating locations...')
print('---------------------------------------') print('---------------------------------------')
_root = Location.objects.create(name='_root', type='_root') _root = Location.objects.create(name='_root', type='_root')
depths = ('A','B','C','D') depths = ('A', 'B', 'C', 'D')
for d1 in depths: for d1 in depths:
x = Location.objects.create(name='Страна %s' % d1, type='country', parent=_root) x = Location.objects.create(name='Страна %s' % d1, type='country', parent=_root)
for d2 in depths: for d2 in depths:
y = Location.objects.create(name='Регион %s-%s' % (d1,d2), type='region', parent=x) y = Location.objects.create(name='Регион %s-%s' % (d1, d2), type='region', parent=x)
for d3 in depths: for d3 in depths:
z = Location.objects.create(name='Город %s-%s-%s' % (d1,d2,d3), type='town', parent=y) z = Location.objects.create(name='Город %s-%s-%s' % (d1, d2, d3), type='town', parent=y)

@ -1,11 +1,9 @@
from django.contrib.auth.models import Group, Permission import pydash as _;
from django.contrib.contenttypes.models import ContentType from django.contrib.auth.models import Group
from django.core.management import BaseCommand from django.core.management import BaseCommand
from django.utils import timezone
import pydash as _; _.map = _.map_; _.filter = _.filter_
import random
from archilance import util _.map = _.map_;
_.filter = _.filter_
class Command(BaseCommand): class Command(BaseCommand):
@ -14,6 +12,5 @@ class Command(BaseCommand):
print('Generating permission groups...') print('Generating permission groups...')
print('---------------------------------------') print('---------------------------------------')
Group.objects.create(name='Исполнители') Group.objects.create(name='Исполнители')
Group.objects.create(name='Заказчики') Group.objects.create(name='Заказчики')

@ -1,15 +1,14 @@
from django.contrib.auth.models import Group, Permission import pydash as _;
from django.contrib.contenttypes.models import ContentType
from django.core.management import BaseCommand from django.core.management import BaseCommand
from django.utils import timezone
import pydash as _; _.map = _.map_; _.filter = _.filter_ _.map = _.map_;
import random _.filter = _.filter_
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, TERM_TYPES, BuildingClassfication , ConstructionType from projects.models import Portfolio, 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
class Command(BaseCommand): class Command(BaseCommand):
@ -18,7 +17,6 @@ class Command(BaseCommand):
print('Generating portfolios...') print('Generating portfolios...')
print('---------------------------------------') print('---------------------------------------')
# ('photos', 'Relation? True', 'Null? True', '(relation)', 'Hidden? False'), # ('photos', 'Relation? True', 'Null? True', '(relation)', 'Hidden? False'),
# ('budget', 'Relation? False', 'Null? True', 'Blank? True', 'Hidden? False'), # ('budget', 'Relation? False', 'Null? True', 'Blank? True', 'Hidden? False'),
# ('building_classification', 'Relation? True', 'Null? True', '(relation)', 'Hidden? False'), # ('building_classification', 'Relation? True', 'Null? True', '(relation)', 'Hidden? False'),
@ -56,7 +54,9 @@ class Command(BaseCommand):
portf.location = Location.objects.root_nodes()[0].get_descendants().order_by('?').first() portf.location = Location.objects.root_nodes()[0].get_descendants().order_by('?').first()
portf.specialization = Specialization.objects.root_nodes()[0].get_descendants().order_by('?').first() portf.specialization = Specialization.objects.root_nodes()[0].get_descendants().order_by('?').first()
pic_names = _.split('a.png b.png c.jpg d.png e.jpg f.png g.png h.jpg i.png j.png k.jpg l.png m.png n.png o.png p.png q.jpg', ' ') pic_names = _.split(
'a.png b.png c.jpg d.png e.jpg f.png g.png h.jpg i.png j.png k.jpg l.png m.png n.png o.png p.png q.jpg',
' ')
_.times( _.times(
lambda i_: portf.photos.create(img='_sample_files/%s' % util.take_one_random(pic_names)), lambda i_: portf.photos.create(img='_sample_files/%s' % util.take_one_random(pic_names)),

@ -1,9 +1,8 @@
from django.contrib.auth.models import Group, Permission import pydash as _;
from django.contrib.contenttypes.models import ContentType
from django.core.management import BaseCommand from django.core.management import BaseCommand
from django.utils import timezone
import pydash as _; _.map = _.map_; _.filter = _.filter_ _.map = _.map_;
import random _.filter = _.filter_
from archilance import util from archilance import util
from projects.models import Project, Order, CURRENCIES, TERM_TYPES, Specialization, Realty from projects.models import Project, Order, CURRENCIES, TERM_TYPES, Specialization, Realty
@ -16,7 +15,6 @@ class Command(BaseCommand):
print('Generating projects...') print('Generating projects...')
print('---------------------------------------') print('---------------------------------------')
# Fields: # Fields:

@ -1,11 +1,9 @@
from django.contrib.auth.models import Group, Permission import pydash as _;
from django.contrib.contenttypes.models import ContentType
from django.core.management import BaseCommand from django.core.management import BaseCommand
from django.utils import timezone
import pydash as _; _.map = _.map_; _.filter = _.filter_
import random
from archilance import util _.map = _.map_;
_.filter = _.filter_
from common.models import Location from common.models import Location
from projects.models import Realty, BuildingClassfication, ConstructionType from projects.models import Realty, BuildingClassfication, ConstructionType
from users.models import User from users.models import User
@ -17,7 +15,6 @@ class Command(BaseCommand):
print('Generating realties...') print('Generating realties...')
print('---------------------------------------') print('---------------------------------------')
# # Fields: # # Fields:
# #
# #
@ -39,7 +36,8 @@ class Command(BaseCommand):
realty.building_classification = BuildingClassfication.objects.order_by('?').first() realty.building_classification = BuildingClassfication.objects.order_by('?').first()
realty.construction_type = ConstructionType.objects.order_by('?').first() realty.construction_type = ConstructionType.objects.order_by('?').first()
realty.location = Location.objects.root_nodes()[0].get_descendants().order_by('?').first() realty.location = Location.objects.root_nodes()[0].get_descendants().order_by('?').first()
realty.user = User.objects.filter(groups__name='Заказчики', is_active=True, is_superuser=False).order_by('?').first() realty.user = User.objects.filter(groups__name='Заказчики', is_active=True, is_superuser=False).order_by(
'?').first()
realty.save() realty.save()
return realty return realty

@ -1,14 +1,12 @@
from django.contrib.auth.models import Group, Permission import pydash as _;
from django.contrib.contenttypes.models import ContentType
from django.core.management import BaseCommand from django.core.management import BaseCommand
from django.utils import timezone
import pydash as _; _.map = _.map_; _.filter = _.filter_ _.map = _.map_;
import random _.filter = _.filter_
from archilance import util from archilance import util
from projects.models import Project, Portfolio from projects.models import Project
from specializations.models import Specialization from users.models import User
from users.models import User, GENDERS, Team
from reviews.models import Review from reviews.models import Review

@ -1,8 +1,9 @@
import pydash as _;
from django.core.management import BaseCommand from django.core.management import BaseCommand
import pydash as _; _.map = _.map_; _.filter = _.filter_
import random
from archilance import util _.map = _.map_;
_.filter = _.filter_
from specializations.models import Specialization from specializations.models import Specialization
@ -12,16 +13,15 @@ class Command(BaseCommand):
print('Generating specializations...') print('Generating specializations...')
print('---------------------------------------') print('---------------------------------------')
_root = Specialization.objects.create(name='_root') _root = Specialization.objects.create(name='_root')
stages = ('A','B','C','D') stages = ('A', 'B', 'C', 'D')
for s1 in stages: for s1 in stages:
x = Specialization.objects.create(name='Специализация %s' % s1, parent=_root) x = Specialization.objects.create(name='Специализация %s' % s1, parent=_root)
for s2 in stages: for s2 in stages:
y = Specialization.objects.create(name='Специализация %s-%s' % (s1,s2), parent=x) y = Specialization.objects.create(name='Специализация %s-%s' % (s1, s2), parent=x)
for s3 in stages: for s3 in stages:
z = Specialization.objects.create(name='Специализация %s-%s-%s' % (s1,s2,s3), parent=y) z = Specialization.objects.create(name='Специализация %s-%s-%s' % (s1, s2, s3), parent=y)
for s4 in stages: for s4 in stages:
Specialization.objects.create(name='Специализация %s-%s-%s-%s' % (s1,s2,s3,s4), parent=z) Specialization.objects.create(name='Специализация %s-%s-%s-%s' % (s1, s2, s3, s4), parent=z)

@ -1,11 +1,9 @@
from django.contrib.auth.models import Group, Permission import pydash as _;
from django.contrib.contenttypes.models import ContentType
from django.core.management import BaseCommand from django.core.management import BaseCommand
from django.utils import timezone
import pydash as _; _.map = _.map_; _.filter = _.filter_
import random
from archilance import util _.map = _.map_;
_.filter = _.filter_
from users.models import User from users.models import User

@ -1,14 +1,13 @@
from django.contrib.auth.models import Group, Permission import pydash as _;
from django.contrib.contenttypes.models import ContentType
from django.core.management import BaseCommand from django.core.management import BaseCommand
from django.utils import timezone
import pydash as _; _.map = _.map_; _.filter = _.filter_ _.map = _.map_;
import random _.filter = _.filter_
from archilance import util from archilance import util
from projects.models import Portfolio from projects.models import Portfolio
from specializations.models import Specialization from specializations.models import Specialization
from users.models import User, GENDERS, Team from users.models import User, Team
class Command(BaseCommand): class Command(BaseCommand):
@ -17,7 +16,6 @@ class Command(BaseCommand):
print('Generating teams...') print('Generating teams...')
print('---------------------------------------') print('---------------------------------------')
# ('name', 'Relation? False', 'Null? False', 'Blank? False', 'Hidden? False'), # ('name', 'Relation? False', 'Null? False', 'Blank? False', 'Hidden? False'),
# ('portfolios', 'Relation? True', 'Null? True', '(relation)', 'Hidden? False'), # ('portfolios', 'Relation? True', 'Null? True', '(relation)', 'Hidden? False'),
@ -39,7 +37,8 @@ class Command(BaseCommand):
team.owner = owner team.owner = owner
team.contractors = _.sample(members, _.random(1, 5)) team.contractors = _.sample(members, _.random(1, 5))
team.specializations = Specialization.objects.root_nodes()[0].get_descendants().order_by('?')[:_.random(1, 5)] team.specializations = Specialization.objects.root_nodes()[0].get_descendants().order_by('?')[
:_.random(1, 5)]
team.portfolios = Portfolio.objects.order_by('?')[:_.random(1, 10)] team.portfolios = Portfolio.objects.order_by('?')[:_.random(1, 10)]
team.save() team.save()

@ -1,14 +1,13 @@
from django.contrib.auth.models import Group, Permission import pydash as _;
from django.contrib.contenttypes.models import ContentType from django.contrib.auth.models import Group
from django.core.management import BaseCommand from django.core.management import BaseCommand
from django.utils import timezone
import pydash as _; _.map = _.map_; _.filter = _.filter_
import random
from archilance import util _.map = _.map_;
_.filter = _.filter_
from common.models import Location from common.models import Location
from specializations.models import Specialization from specializations.models import Specialization
from users.models import User, GENDERS from users.models import User
class Command(BaseCommand): class Command(BaseCommand):
@ -17,8 +16,6 @@ class Command(BaseCommand):
print('Generating users...') print('Generating users...')
print('---------------------------------------') print('---------------------------------------')
# # Fields: # # Fields:
# #
# ('contractor_specializations', 'Relation? True', 'Null? False', '(relation)', 'Hidden? False'), # ('contractor_specializations', 'Relation? True', 'Null? False', '(relation)', 'Hidden? False'),
@ -91,14 +88,14 @@ class Command(BaseCommand):
users = _.times(create_user, 500) users = _.times(create_user, 500)
contractor_group = Group.objects.get(name='Исполнители') contractor_group = Group.objects.get(name='Исполнители')
customer_group = Group.objects.get(name='Заказчики') customer_group = Group.objects.get(name='Заказчики')
for user in users: for user in users:
user.set_password('123') user.set_password('123')
user.groups.add(customer_group if user.pk % 2 == 0 else contractor_group) user.groups.add(customer_group if user.pk % 2 == 0 else contractor_group)
user.contractor_specializations = Specialization.objects.root_nodes()[0].get_descendants().order_by('?')[:_.random(1, 5)] user.contractor_specializations = Specialization.objects.root_nodes()[0].get_descendants().order_by('?')[
:_.random(1, 5)]
user.location = Location.objects.root_nodes()[0].get_descendants().order_by('?').first() user.location = Location.objects.root_nodes()[0].get_descendants().order_by('?').first()
user.save() user.save()

@ -1,16 +1,15 @@
from django.contrib.auth.models import Group, Permission import pydash as _;
from django.contrib.contenttypes.models import ContentType
from django.core.management import BaseCommand from django.core.management import BaseCommand
from django.utils import timezone
import pydash as _; _.map = _.map_; _.filter = _.filter_ _.map = _.map_;
import random _.filter = _.filter_
from archilance import util from archilance import util
from common.models import Location from common.models import Location
from projects.models import TERM_TYPES, 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, Team from users.models import User, Team
from work_sell.models import WorkSell, WorkSellPhoto from work_sell.models import WorkSell
class Command(BaseCommand): class Command(BaseCommand):
@ -42,7 +41,9 @@ class Command(BaseCommand):
ws.location = Location.objects.root_nodes()[0].get_descendants().order_by('?').first() ws.location = Location.objects.root_nodes()[0].get_descendants().order_by('?').first()
ws.specialization = Specialization.objects.root_nodes()[0].get_descendants().order_by('?').first() ws.specialization = Specialization.objects.root_nodes()[0].get_descendants().order_by('?').first()
pic_names = _.split('a.png b.png c.jpg d.png e.jpg f.png g.png h.jpg i.png j.png k.jpg l.png m.png n.png o.png p.png q.jpg', ' ') pic_names = _.split(
'a.png b.png c.jpg d.png e.jpg f.png g.png h.jpg i.png j.png k.jpg l.png m.png n.png o.png p.png q.jpg',
' ')
_.times( _.times(
lambda i_: ws.photos.create(img='_sample_files/%s' % util.take_one_random(pic_names)), lambda i_: ws.photos.create(img='_sample_files/%s' % util.take_one_random(pic_names)),

@ -0,0 +1,16 @@
from django.utils import translation
class LocaleMiddleware(object):
"""
This is a very simple middleware that parses a request
and decides what translation object to install in the current
thread context. This allows pages to be dynamically
translated to the language the user desires (if the language
is available, of course).
"""
def process_request(self, request):
user_language = 'ru_RU'
translation.activate(user_language)
request.session[translation.LANGUAGE_SESSION_KEY] = user_language

@ -7,9 +7,9 @@ class BaseMixin(ContextMixin):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
c = super().get_context_data(**kwargs) c = super().get_context_data(**kwargs)
pk = self.kwargs.get('pk') # Current object's ID pk = self.kwargs.get('pk') # Current object's ID
next = self.kwargs.get('next') # Redirect next path next = self.kwargs.get('next') # Redirect next path
back = self.kwargs.get('back') # Redirect back path back = self.kwargs.get('back') # Redirect back path
if pk: c['pk'] = int(pk) if pk: c['pk'] = int(pk)
if next: c['next'] = next if next: c['next'] = next
@ -22,5 +22,4 @@ class BaseMixin(ContextMixin):
return c return c
# import code; code.interact(local=dict(globals(), **locals())) # import code; code.interact(local=dict(globals(), **locals()))

@ -83,6 +83,7 @@ INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS + WAGTAIL
MIDDLEWARE_CLASSES = [ MIDDLEWARE_CLASSES = [
'django.middleware.security.SecurityMiddleware', 'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',
'archilance.middlewares.LocaleMiddleware',
'django.middleware.common.CommonMiddleware', 'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware', 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware',
@ -102,7 +103,6 @@ TEMPLATES = [
'BACKEND': 'django.template.backends.django.DjangoTemplates', 'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(ROOT_DIR, 'templates')], 'DIRS': [os.path.join(ROOT_DIR, 'templates')],
'APP_DIRS': True, 'APP_DIRS': True,
'OPTIONS': { 'OPTIONS': {
'context_processors': [ 'context_processors': [
'django.template.context_processors.debug', 'django.template.context_processors.debug',
@ -237,7 +237,7 @@ FIELDS_STORED_IN_SESSION = ['user_type']
# Internationalization # Internationalization
# https://docs.djangoproject.com/en/1.9/topics/i18n/ # https://docs.djangoproject.com/en/1.9/topics/i18n/
LANGUAGE_CODE = 'ru-ru' LANGUAGE_CODE = 'ru_RU'
TIME_ZONE = 'Europe/Moscow' TIME_ZONE = 'Europe/Moscow'
@ -247,6 +247,10 @@ USE_L10N = True
USE_TZ = True USE_TZ = True
LANGUAGES = (
('ru_RU', 'Russian'),
)
# Static files (CSS, JavaScript, Images) # Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.9/howto/static-files/ # https://docs.djangoproject.com/en/1.9/howto/static-files/

@ -4,52 +4,50 @@ from django.conf.urls.static import static
from django.contrib import admin from django.contrib import admin
from django.contrib.staticfiles.urls import staticfiles_urlpatterns from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.views.generic import TemplateView from django.views.generic import TemplateView
from .views import HomeTemplateView, TestChatTemplateView, TestView
from common.views import CustomRegistrationView
from wallets.views import TmpCheckOrderView, TmpPaymentAvisoView
from wagtail.wagtailadmin import urls as wagtailadmin_urls from wagtail.wagtailadmin import urls as wagtailadmin_urls
from wagtail.wagtailcore import urls as wagtail_urls from wagtail.wagtailcore import urls as wagtail_urls
from common.views import CustomRegistrationView
from wallets.views import TmpCheckOrderView, TmpPaymentAvisoView
from .views import HomeTemplateView, TestChatTemplateView, TestView
urlpatterns = [ urlpatterns = [
url(r'^$', HomeTemplateView.as_view()), url(r'^$', HomeTemplateView.as_view()),
url('', include('social.apps.django_app.urls', namespace='social')), url('', include('social.apps.django_app.urls', namespace='social')),
url(r'^chattest/$', TestChatTemplateView.as_view()), url(r'^chattest/$', TestChatTemplateView.as_view()),
url(r'^work_sell/', include('work_sell.urls')), url(r'^work_sell/', include('work_sell.urls')),
url(r'^test/$', TestView.as_view(), name='test'), url(r'^test/$', TestView.as_view(), name='test'),
url(r'^projects/', include('projects.urls')), url(r'^projects/', include('projects.urls')),
url(r'^reviews/', include('reviews.urls')), url(r'^reviews/', include('reviews.urls')),
url(r'^wallets/', include('wallets.urls')), url(r'^wallets/', include('wallets.urls')),
url(r'^chat/', include('chat.urls')), url(r'^chat/', include('chat.urls')),
url(r'^specializations/', include('specializations.urls')), url(r'^specializations/', include('specializations.urls')),
url(r'^users/', include('users.urls')), url(r'^users/', include('users.urls')),
url(r'^common/', include('common.urls')), url(r'^common/', include('common.urls')),
url(r'^password/', include('password_reset.urls')), url(r'^password/', include('password_reset.urls')),
url(r'^users/register/$', CustomRegistrationView.as_view(), name='registration_register'), url(r'^users/register/$', CustomRegistrationView.as_view(), name='registration_register'),
url(r'^users/', include('registration.backends.default.urls')), url(r'^users/', include('registration.backends.default.urls')),
url(r'^admin/', admin.site.urls), url(r'^admin/', admin.site.urls),
url(r'^api/', include('api.urls')), url(r'^api/', include('api.urls')),
url(r'^cms/', include(wagtailadmin_urls)), url(r'^cms/', include(wagtailadmin_urls)),
url(r'^pages/', include(wagtail_urls)), url(r'^pages/', include(wagtail_urls)),
# TODO: Move URLs into the "wallets" app (Yandex Money settings modification needed): # TODO: Move URLs into the "wallets" app (Yandex Money settings modification needed):
url(r'^yandex/check$', TmpCheckOrderView.as_view(), name='tmp-check-order'), url(r'^yandex/check$', TmpCheckOrderView.as_view(), name='tmp-check-order'),
url(r'^yandex/aviso$', TmpPaymentAvisoView.as_view(), name='tmp-payment-aviso'), url(r'^yandex/aviso$', TmpPaymentAvisoView.as_view(), name='tmp-payment-aviso'),
url(r'^payment/success$', TemplateView.as_view(template_name='message.html'), { url(r'^payment/success$', TemplateView.as_view(template_name='message.html'), {
'message': 'Оплата прошла успешно', 'message': 'Оплата прошла успешно',
}, name='tmp-payment-success'), }, name='tmp-payment-success'),
url(r'^payment/fail$', TemplateView.as_view(template_name='message.html'), { url(r'^payment/fail$', TemplateView.as_view(template_name='message.html'), {
'message': 'Произошла ошибка при оплате', 'message': 'Произошла ошибка при оплате',
}, name='tmp-payment-fail'), }, name='tmp-payment-fail'),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
if settings.DEBUG: if settings.DEBUG:
urlpatterns += staticfiles_urlpatterns() urlpatterns += staticfiles_urlpatterns()

@ -1,12 +1,16 @@
import datetime
from pprint import pprint
import natsort
import pydash as _;
from django.core import validators from django.core import validators
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.core.files.storage import FileSystemStorage from django.core.files.storage import FileSystemStorage
from django.shortcuts import _get_queryset from django.shortcuts import _get_queryset
from django.utils import timezone from django.utils import timezone
from pprint import pprint, pformat
import datetime _.map = _.map_;
import natsort _.filter = _.filter_
import pydash as _; _.map = _.map_; _.filter = _.filter_
import random import random
import string import string
@ -33,7 +37,7 @@ def take_one_random(coll):
if len(coll) == 0: if len(coll) == 0:
return None return None
return coll.pop(_.random(0, len(coll)-1)) return coll.pop(_.random(0, len(coll) - 1))
def random_phone(): def random_phone():
@ -84,11 +88,11 @@ def model_fields(model, width=200):
fields = natsort.natsorted(model._meta.get_fields(), key=lambda f: f.name) fields = natsort.natsorted(model._meta.get_fields(), key=lambda f: f.name)
pprint([( pprint([(
f.name, f.name,
'Relation? %s' % f.is_relation, 'Relation? %s' % f.is_relation,
'Null? %s' % getattr(f, 'null', None), 'Null? %s' % getattr(f, 'null', None),
'Blank? %s' % getattr(f, 'blank', None), 'Blank? %s' % getattr(f, 'blank', None),
) for f in fields], width=width) ) for f in fields], width=width)
def lorem(words=None, sentences=5): def lorem(words=None, sentences=5):
@ -102,7 +106,8 @@ def lorem(words=None, sentences=5):
'vitae viverra volutpat vulputate' 'vitae viverra volutpat vulputate'
), ' ') ), ' ')
return _.join(_.times(lambda i_: _.capitalize(_.join(_.sample(vocab, words or _.random(5, 30)), ' ')), sentences), '. ') return _.join(_.times(lambda i_: _.capitalize(_.join(_.sample(vocab, words or _.random(5, 30)), ' ')), sentences),
'. ')
def decap(s): def decap(s):
@ -115,7 +120,7 @@ def decap(s):
def random_ident(length=8): def random_ident(length=8):
return ''.join( return ''.join(
[random.choice(string.ascii_lowercase)] + [random.choice(string.ascii_lowercase)] +
_.times(lambda x_: random.choice(string.ascii_letters + string.digits), length-1) _.times(lambda x_: random.choice(string.ascii_letters + string.digits), length - 1)
) )
@ -153,6 +158,7 @@ def morph(number, words):
return words[choice] return words[choice]
# # Example: # # Example:
# #
# words = ['яблоко', 'яблока', 'яблок'] # words = ['яблоко', 'яблока', 'яблок']
@ -164,8 +170,8 @@ def morph(number, words):
class ASCIIFileSystemStorage(FileSystemStorage): class ASCIIFileSystemStorage(FileSystemStorage):
def get_valid_name(self, name): def get_valid_name(self, name):
symbols = (u"абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ", symbols = (u"абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ",
u"abvgdeejzijklmnoprstufhzcss_y_euaABVGDEEJZIJKLMNOPRSTUFHZCSS_Y_EUA") u"abvgdeejzijklmnoprstufhzcss_y_euaABVGDEEJZIJKLMNOPRSTUFHZCSS_Y_EUA")
tr = {ord(a):ord(b) for a, b in zip(*symbols)} tr = {ord(a): ord(b) for a, b in zip(*symbols)}
name = name.translate(tr) name = name.translate(tr)
return super().get_valid_name(name) return super().get_valid_name(name)

@ -1,22 +1,15 @@
from django.conf import settings import pydash as _;
from django.contrib import messages
from django.core.exceptions import PermissionDenied
from django.core.files.base import ContentFile from django.core.files.base import ContentFile
from django.core.urlresolvers import reverse, reverse_lazy from django.shortcuts import render
from django.http import HttpResponseForbidden, JsonResponse, HttpResponseRedirect, HttpResponse, Http404 from django.views.generic import View
from django.shortcuts import render, get_object_or_404, redirect
from django.views.generic import TemplateView, View _.map = _.map_;
from pprint import pprint, pformat _.filter = _.filter_
import json
import logging
import pydash as _; _.map = _.map_; _.filter = _.filter_
from .mixins import BaseMixin from .mixins import BaseMixin
from archilance import util
from chat.models import Documents from chat.models import Documents
from common.models import MainPage, PrintDocuments from common.models import MainPage
from projects.models import Order from users.models import User
from users.models import User, ContractorResumeFiles
from work_sell.models import Picture from work_sell.models import Picture
@ -36,7 +29,7 @@ class TestChatTemplateView(View):
template_name = 'chat_test.html' template_name = 'chat_test.html'
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
test = [54,55,56] test = [54, 55, 56]
for pk in test: for pk in test:
picture = Picture.objects.get(pk=pk) picture = Picture.objects.get(pk=pk)
temp_file = ContentFile(picture.file.read()) temp_file = ContentFile(picture.file.read())
@ -61,5 +54,4 @@ class TestView(BaseMixin, View):
return render(request, self.template_name, context) return render(request, self.template_name, context)
# return redirect('projects:detail', pk=153) # return redirect('projects:detail', pk=153)
# import code; code.interact(local=dict(globals(), **locals())) # import code; code.interact(local=dict(globals(), **locals()))

@ -7,21 +7,23 @@ For more information on this file, see
https://docs.djangoproject.com/en/1.9/howto/deployment/wsgi/ https://docs.djangoproject.com/en/1.9/howto/deployment/wsgi/
""" """
import os
from django.core.wsgi import get_wsgi_application from django.core.wsgi import get_wsgi_application
from django.template.base import Variable from django.template.base import Variable
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "archilance.settings.local") os.environ.setdefault("DJANGO_SETTINGS_MODULE", "archilance.settings.local")
application = get_wsgi_application() application = get_wsgi_application()
# Patch template Variable to output empty string for None values: # Patch template Variable to output empty string for None values:
old_resolve_lookup = Variable._resolve_lookup old_resolve_lookup = Variable._resolve_lookup
def new_resolve_lookup(self, *args, **kwargs): def new_resolve_lookup(self, *args, **kwargs):
val = old_resolve_lookup(self, *args, **kwargs) val = old_resolve_lookup(self, *args, **kwargs)
return '' if val == None else val return '' if val == None else val
Variable._resolve_lookup = new_resolve_lookup Variable._resolve_lookup = new_resolve_lookup

@ -1073,7 +1073,7 @@ footer:after {
} }
.pagin nav ul li a { .pagin nav ul li a {
background-color: none; background-color: transparent;
color: black; color: black;
font-size: 20px; font-size: 20px;
line-height: 50px; line-height: 50px;
@ -1099,7 +1099,6 @@ footer:after {
.pagin nav ul li a:hover, .pagin nav ul li a:hover,
.pagin nav ul li a:active { .pagin nav ul li a:active {
color: black;
color: white; color: white;
background-color: #2c2c2c; background-color: #2c2c2c;
border-color: #2c2c2c; border-color: #2c2c2c;
@ -2560,7 +2559,7 @@ input[type="checkbox"]:checked + span {
text-align: center; text-align: center;
margin: 0 0 0 0; margin: 0 0 0 0;
position: relative; position: relative;
letter-spacing: 0px; letter-spacing: 0;
} }
.compareBlock p:before { .compareBlock p:before {
@ -2986,9 +2985,8 @@ input[type="checkbox"]:checked + span {
.compTable tr td:nth-child(6) ul li:nth-child(2):before { .compTable tr td:nth-child(6) ul li:nth-child(2):before {
height: 20px; height: 20px;
background: url('../img/listTable.png') no-repeat center;
background-size: cover; background-size: cover;
background-position: 0 -17px; background: url('../img/listTable.png') no-repeat 0 -17px;
} }
.compTable tr td:nth-child(7) { .compTable tr td:nth-child(7) {
@ -3005,7 +3003,6 @@ input[type="checkbox"]:checked + span {
font-weight: bold; font-weight: bold;
font-family: Arial, Verdana, Helvetica, sans-serif; font-family: Arial, Verdana, Helvetica, sans-serif;
position: relative; position: relative;
position: relative;
width: 100%; width: 100%;
float: left; float: left;
} }
@ -3839,7 +3836,7 @@ input[type="checkbox"]:checked + span {
border-top: 1px solid black; border-top: 1px solid black;
border-bottom: 1px solid black; border-bottom: 1px solid black;
-webkit-transform: scale(1.03); -webkit-transform: scale(1.03);
-moz- transform: scale(1.03); -moz-transform: scale(1.03);
transform: scale(1.03); transform: scale(1.03);
box-shadow: 0 0 10px rgba(0,0,0,0.7); box-shadow: 0 0 10px rgba(0,0,0,0.7);
z-index: 999; z-index: 999;
@ -3916,7 +3913,7 @@ input[type="checkbox"]:checked + span {
border-top: 1px solid black; border-top: 1px solid black;
border-bottom: 1px solid black; border-bottom: 1px solid black;
-webkit-transform: scale(1.03); -webkit-transform: scale(1.03);
-moz- transform: scale(1.03); -moz-transform: scale(1.03);
transform: scale(1.03); transform: scale(1.03);
box-shadow: 0 0 10px rgba(0,0,0,0.7); box-shadow: 0 0 10px rgba(0,0,0,0.7);
z-index: 999; z-index: 999;
@ -4286,7 +4283,6 @@ input[type="checkbox"]:checked + span {
#modal_form1 { #modal_form1 {
width: 600px; width: 600px;
height: 400px; height: 400px;
display: table;
position: fixed; position: fixed;
top: 50%; top: 50%;
left: 50%; left: 50%;
@ -4344,7 +4340,6 @@ input[type="checkbox"]:checked + span {
width: 300px; width: 300px;
height: 160px; height: 160px;
min-height: 160px; min-height: 160px;
display: table;
position: fixed; position: fixed;
right: 0; right: 0;
top: 50%; top: 50%;
@ -5438,7 +5433,7 @@ input[type="radio"]:checked + span {
font-family: Arial, Verdana, Helvetica, sans-serif; font-family: Arial, Verdana, Helvetica, sans-serif;
font-size: 16px; font-size: 16px;
font-weight: bold; font-weight: bold;
margin: 0px 0 -15 0; margin: 0px 0 -15px 0;
} }
.inp-edit { .inp-edit {
@ -5536,7 +5531,7 @@ input[type="radio"]:checked + span {
.caret:after { .caret:after {
content: "\e253"; content: "\e253";
position: absolute; position: absolute;
font-family: 'Glyphicons Halflings'; font-family: 'Glyphicons Halflings', serif;
right: -6.5px; right: -6.5px;
top: -19px; top: -19px;
font-size: 12px; font-size: 12px;
@ -6080,7 +6075,7 @@ input[type="radio"]{
.welcomeMain{ .welcomeMain{
line-height: 48px; line-height: 48px;
font-family: 'pfdintextcomppro-regular', sans-serif; font-family: 'pfdintextcomppro-regular', sans-serif;
font-size: 43.5px; font-size: 43px;
} }
.menuUser > div{ .menuUser > div{
padding: 10px 0; padding: 10px 0;

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 612 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 B

@ -180,10 +180,10 @@ $('[data-tooltip]').tooltip({
specSelects[2].select2(_.merge(specSelectOptions, {ajax: {url: specs.urlLevel3}})) specSelects[2].select2(_.merge(specSelectOptions, {ajax: {url: specs.urlLevel3}}))
specSelects[3].select2(_.merge(specSelectOptions, {ajax: {url: specs.urlLevel4}})) specSelects[3].select2(_.merge(specSelectOptions, {ajax: {url: specs.urlLevel4}}))
var specLevel1 = specs.specLevel1 var specLevel1 = specs.specLevel1;
var specLevel2 = specs.specLevel2 var specLevel2 = specs.specLevel2;
var specLevel3 = specs.specLevel3 var specLevel3 = specs.specLevel3;
var specLevel4 = specs.specLevel4 var specLevel4 = specs.specLevel4;
specSelects[0].select2('data', specLevel1 ? {id: specLevel1.id, text: specLevel1.name, origItem: specLevel1} : null) specSelects[0].select2('data', specLevel1 ? {id: specLevel1.id, text: specLevel1.name, origItem: specLevel1} : null)
specSelects[1].select2('data', specLevel2 ? {id: specLevel2.id, text: specLevel2.name, origItem: specLevel2} : null) specSelects[1].select2('data', specLevel2 ? {id: specLevel2.id, text: specLevel2.name, origItem: specLevel2} : null)

@ -1,4 +1,5 @@
from django.contrib import admin from django.contrib import admin
from .models import Message, Notes, Documents, NewMessage from .models import Message, Notes, Documents, NewMessage
@ -11,11 +12,11 @@ class NotesAdmin(admin.ModelAdmin):
class DocumentsAdmin(admin.ModelAdmin): class DocumentsAdmin(admin.ModelAdmin):
list_display = ('sender', 'recipent', 'order','team') list_display = ('sender', 'recipent', 'order', 'team')
class NewMessageAdmin(admin.ModelAdmin): class NewMessageAdmin(admin.ModelAdmin):
list_display = ('user', 'message_pk','message_recipent', 'message_order','message_team') list_display = ('user', 'message_pk', 'message_recipent', 'message_order', 'message_team')
def message_pk(self, obj): def message_pk(self, obj):
return obj.message.pk return obj.message.pk

@ -1,13 +1,11 @@
import html import html
from tornado import gen, web, websocket, escape, options
from tornado.ioloop import IOLoop
from tornado.httpserver import HTTPServer
from tornado.options import parse_command_line
from settings import settings, PORT, DATABASE_DSN
import psycopg2
import momoko import momoko
import json from settings import settings, PORT, DATABASE_DSN
from tornado import gen, web, websocket, escape
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from tornado.options import parse_command_line
class BaseHandler(web.RequestHandler): class BaseHandler(web.RequestHandler):
@ -91,8 +89,8 @@ class ChatHandler(websocket.WebSocketHandler):
insert_sql = "INSERT INTO chat_message (id,text,created, sender_id,recipent_id," \ insert_sql = "INSERT INTO chat_message (id,text,created, sender_id,recipent_id," \
" private_type,team_id, order_id,is_delete,is_new) " \ " private_type,team_id, order_id,is_delete,is_new) " \
"VALUES (DEFAULT,'{0}',NOW(),{1},{2},{3},{4},{5},{6},{7}) RETURNING id".\ "VALUES (DEFAULT,'{0}',NOW(),{1},{2},{3},{4},{5},{6},{7}) RETURNING id". \
format(message, sender_id, recipent_id, private_type, team_value,order_value, is_delete, is_new) format(message, sender_id, recipent_id, private_type, team_value, order_value, is_delete, is_new)
cursor_list = yield dict(cursor=self.db.execute(insert_sql)) cursor_list = yield dict(cursor=self.db.execute(insert_sql))
cursor = cursor_list.get('cursor') cursor = cursor_list.get('cursor')
@ -102,19 +100,20 @@ class ChatHandler(websocket.WebSocketHandler):
team_ids = [t for t in team_ids_raw.rstrip(';').split(';')] team_ids = [t for t in team_ids_raw.rstrip(';').split(';')]
values_str = ''; values_str = '';
for t in team_ids: for t in team_ids:
values_str +='(DEFAULT,{0},{1}),'.format(message_id,t) values_str += '(DEFAULT,{0},{1}),'.format(message_id, t)
values_str = values_str.rstrip(',') values_str = values_str.rstrip(',')
insert_new_messages = "INSERT INTO chat_newmessage (id,message_id, user_id) VALUES{0}".\ insert_new_messages = "INSERT INTO chat_newmessage (id,message_id, user_id) VALUES{0}". \
format(values_str) format(values_str)
else: else:
insert_new_messages = "INSERT INTO chat_newmessage (id,message_id, user_id) VALUES(DEFAULT,{0},{1})".\ insert_new_messages = "INSERT INTO chat_newmessage (id,message_id, user_id) VALUES(DEFAULT,{0},{1})". \
format(message_id, recipent_id) format(message_id, recipent_id)
yield self.db.execute(insert_new_messages) yield self.db.execute(insert_new_messages)
if docs_send_links: if docs_send_links:
is_send = 'true' is_send = 'true'
docs_send_ids = docs_send_links.rstrip(';').replace(';', ',') docs_send_ids = docs_send_links.rstrip(';').replace(';', ',')
update_sql_documents = "UPDATE chat_documents SET message_id={0},is_send={1} WHERE id IN({2})".format(message_id, is_send, docs_send_ids) update_sql_documents = "UPDATE chat_documents SET message_id={0},is_send={1} WHERE id IN({2})".format(
message_id, is_send, docs_send_ids)
yield self.db.execute(update_sql_documents) yield self.db.execute(update_sql_documents)
select_last_sql = "SELECT chat_message.id, chat_message.text, chat_message.created, chat_message.sender_id," \ select_last_sql = "SELECT chat_message.id, chat_message.text, chat_message.created, chat_message.sender_id," \
@ -143,7 +142,7 @@ class ChatHandler(websocket.WebSocketHandler):
'sender_name': sender_name, 'sender_name': sender_name,
'answer_type': answer_type, 'answer_type': answer_type,
'docs_attach': docs_attach, 'docs_attach': docs_attach,
}) })
def check_origin(self, origin): def check_origin(self, origin):
return True return True

@ -2,6 +2,7 @@ from rest_framework_filters import FilterSet, RelatedFilter, AllLookupsFilter
from .models import Message, Notes, Documents from .models import Message, Notes, Documents
# #
# class DocumentsFilterSet(FilterSet): # class DocumentsFilterSet(FilterSet):
# file = AllLookupsFilter() # file = AllLookupsFilter()
@ -30,17 +31,15 @@ class MessageFilterSet(FilterSet):
model = Message model = Message
class DocumentFilterSet(FilterSet): class DocumentFilterSet(FilterSet):
id = AllLookupsFilter() id = AllLookupsFilter()
# order = RelatedFilter('projects.filters.OrderFilterSet') # order = RelatedFilter('projects.filters.OrderFilterSet')
class Meta: class Meta:
model = Documents model = Documents
class NoteFilterSet(FilterSet): class NoteFilterSet(FilterSet):
created = AllLookupsFilter() created = AllLookupsFilter()
id = AllLookupsFilter() id = AllLookupsFilter()

@ -4,4 +4,3 @@ from django import forms
class ArticleForm(forms.Form): class ArticleForm(forms.Form):
title = forms.CharField() title = forms.CharField()
pub_date = forms.DateField() pub_date = forms.DateField()

@ -8,7 +8,7 @@ from users.models import User, Team
class Message(models.Model): class Message(models.Model):
text = models.TextField() text = models.TextField()
created = models.DateTimeField(default=timezone.now) created = models.DateTimeField(default=timezone.now)
order = models.ForeignKey(Order, related_name='messages',null=True, blank=True) order = models.ForeignKey(Order, related_name='messages', null=True, blank=True)
sender = models.ForeignKey(User, related_name='sender_messages') sender = models.ForeignKey(User, related_name='sender_messages')
recipent = models.ForeignKey(User, related_name='recipent_messages') recipent = models.ForeignKey(User, related_name='recipent_messages')
private_type = models.BooleanField(default=False) private_type = models.BooleanField(default=False)

@ -1,4 +1,5 @@
import json import json
from django.http import HttpResponse from django.http import HttpResponse
MIMEANY = '*/*' MIMEANY = '*/*'

@ -1,8 +1,8 @@
from rest_framework import serializers from rest_framework import serializers
from rest_framework.serializers import ModelSerializer from rest_framework.serializers import ModelSerializer
from .models import Message, Notes, Documents
from users.serializers import UserSerializer from users.serializers import UserSerializer
from .models import Message, Notes, Documents
class DocumentsSerializer(ModelSerializer): class DocumentsSerializer(ModelSerializer):
@ -44,7 +44,6 @@ class MessageSerializer(ModelSerializer):
documents = DocumentsSerializer(read_only=True, many=True) documents = DocumentsSerializer(read_only=True, many=True)
text = serializers.SerializerMethodField() text = serializers.SerializerMethodField()
class Meta: class Meta:
model = Message model = Message
@ -62,14 +61,15 @@ class MessageSerializer(ModelSerializer):
def get_text(self, obj): def get_text(self, obj):
out = obj.text out = obj.text
documents = obj.documents.all() documents = obj.documents.all()
if len(documents)>0: if len(documents) > 0:
documents_str = '<br>'.join(['Приложенный файл. скачать: <br><a target="_blank" href="/chat/download/' + doc.file.name + '">' + doc.file.name + '</a>' for doc in documents]) documents_str = '<br>'.join([
'Приложенный файл. скачать: <br><a target="_blank" href="/chat/download/' + doc.file.name + '">' + doc.file.name + '</a>'
for doc in documents])
out += '<br><br>' + documents_str out += '<br><br>' + documents_str
return out return out
class NoteSerializer(ModelSerializer): class NoteSerializer(ModelSerializer):
class Meta: class Meta:
model = Notes model = Notes

@ -13,7 +13,4 @@ settings = {
'server_traceback': True, 'server_traceback': True,
} }
DATABASE_DSN = 'dbname=archilance user=postgres password=postgres host=localhost' DATABASE_DSN = 'dbname=archilance user=postgres password=postgres host=localhost'

@ -1,3 +1 @@
from django.test import TestCase
# Create your tests here. # Create your tests here.

@ -1,5 +1,4 @@
import mimetypes import mimetypes
from django.core.urlresolvers import reverse
def serialize(instance, file_attr='file'): def serialize(instance, file_attr='file'):

@ -1,18 +1,19 @@
import json import json
from django.shortcuts import render from wsgiref.util import FileWrapper
from django.conf import settings from django.conf import settings
from django.views.generic import View,CreateView
from django.http import HttpResponse, Http404
from django.db.models import Q
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from wsgiref.util import FileWrapper from django.db.models import Q
from django.http import HttpResponse, Http404
from django.shortcuts import render
from django.views.generic import View, CreateView
from .response import JSONResponse, response_mimetype
from .utils import serialize
from .models import Message, Documents, NewMessage
from projects.models import Order, Project from projects.models import Order, Project
from wallets.models import Transaction
from users.models import User, Team from users.models import User, Team
from wallets.models import Transaction
from .models import Message, Documents
from .response import JSONResponse, response_mimetype
from .utils import serialize
class DocumentCreateView(CreateView): class DocumentCreateView(CreateView):
@ -37,11 +38,11 @@ class ChatUserView(LoginRequiredMixin, View):
template_name = '' template_name = ''
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
user_id = request.GET.get('user_id',None) user_id = request.GET.get('user_id', None)
if request.user.is_customer(): if request.user.is_customer():
customer_contacts = Message.objects.values_list('sender_id', 'recipent_id'). \ customer_contacts = Message.objects.values_list('sender_id', 'recipent_id'). \
filter(Q(recipent_id=request.user.pk) | Q(sender_id=request.user.pk)).\ filter(Q(recipent_id=request.user.pk) | Q(sender_id=request.user.pk)). \
filter(Q(team_id=None)).\ filter(Q(team_id=None)). \
filter(is_delete=False).distinct() filter(is_delete=False).distinct()
users_ids = [] users_ids = []
@ -57,16 +58,18 @@ class ChatUserView(LoginRequiredMixin, View):
contacts_users = User.objects.filter(pk__in=users_ids) contacts_users = User.objects.filter(pk__in=users_ids)
archive_projects = request.user.customer_projects.select_related('order').exclude(state='active') archive_projects = request.user.customer_projects.select_related('order').exclude(state='active')
chat_messages = Message.objects.filter(Q(sender=request.user.pk) | Q(recipent=request.user.pk)) chat_messages = Message.objects.filter(Q(sender=request.user.pk) | Q(recipent=request.user.pk))
orders = request.user.customer_projects.select_related('order').filter(state='active').exclude(order__contractor__isnull=True, order__team__isnull=True) orders = request.user.customer_projects.select_related('order').filter(state='active').exclude(
order__contractor__isnull=True, order__team__isnull=True)
order_ids = [order.order.pk for order in orders] order_ids = [order.order.pk for order in orders]
transaction = Transaction.objects.get_or_create(customer=request.user, type='reservation', complete=False) transaction = Transaction.objects.get_or_create(customer=request.user, type='reservation', complete=False)
contacts_users_count = request.user.new_messages.filter(message__sender__in=users_ids, contacts_users_count = request.user.new_messages.filter(message__sender__in=users_ids,
message__order__isnull=True, message__order__isnull=True,
message__team__isnull=True message__team__isnull=True
).count() ).count()
orders_ms_count = request.user.new_messages.filter(message__order__in=order_ids, message__team__isnull=True).count() orders_ms_count = request.user.new_messages.filter(message__order__in=order_ids,
message__team__isnull=True).count()
self.template_name = 'chat_customer.html' self.template_name = 'chat_customer.html'
return render(request, self.template_name, {'contacts_users': contacts_users, return render(request, self.template_name, {'contacts_users': contacts_users,
'chat_messages': chat_messages, 'chat_messages': chat_messages,
@ -81,17 +84,19 @@ class ChatUserView(LoginRequiredMixin, View):
team_ids = [] team_ids = []
if request.user.is_owner_team(): if request.user.is_owner_team():
team_ids.append(request.user.team.pk) team_ids.append(request.user.team.pk)
# team_orders = request.user.team.orders.all() # team_orders = request.user.team.orders.all()
# # teams = Team.objects.filter(contractors__id=request.user.pk).all() # # teams = Team.objects.filter(contractors__id=request.user.pk).all()
# else: # else:
teams = Team.objects.filter(Q(contractors__id=request.user.pk) | Q(owner=request.user.pk)).all() teams = Team.objects.filter(Q(contractors__id=request.user.pk) | Q(owner=request.user.pk)).all()
team_orders = Order.objects.filter(team_id__in=[team.pk for team in teams]).all() team_orders = Order.objects.filter(team_id__in=[team.pk for team in teams]).all()
orders = Order.objects.filter(Q(contractor=request.user) | Q(team_id__in=team_ids)).filter(project__state='active') orders = Order.objects.filter(Q(contractor=request.user) | Q(team_id__in=team_ids)).filter(
archive_orders = Order.objects.filter(Q(contractor=request.user) | Q(team_id__in=team_ids)).exclude(project__state='active') project__state='active')
archive_orders = Order.objects.filter(Q(contractor=request.user) | Q(team_id__in=team_ids)).exclude(
project__state='active')
contractor_contacts = Message.objects.values_list('sender_id', 'recipent_id').filter( contractor_contacts = Message.objects.values_list('sender_id', 'recipent_id').filter(
Q(recipent_id=request.user.pk) | Q(sender_id=request.user.pk)).filter(Q(team_id=None)).\ Q(recipent_id=request.user.pk) | Q(sender_id=request.user.pk)).filter(Q(team_id=None)). \
filter(is_delete=False).distinct() filter(is_delete=False).distinct()
users_ids = [] users_ids = []
for msg in contractor_contacts: for msg in contractor_contacts:
@ -105,15 +110,16 @@ class ChatUserView(LoginRequiredMixin, View):
contacts_users = User.objects.filter(pk__in=users_ids) contacts_users = User.objects.filter(pk__in=users_ids)
contacts_users_count = request.user.new_messages.filter(message__sender__in=users_ids, contacts_users_count = request.user.new_messages.filter(message__sender__in=users_ids,
message__order__isnull=True, message__order__isnull=True,
message__team__isnull=True message__team__isnull=True
).count() ).count()
chat_messages = Message.objects.filter(Q(sender=request.user.pk) | Q(recipent=request.user.pk)).order_by( chat_messages = Message.objects.filter(Q(sender=request.user.pk) | Q(recipent=request.user.pk)).order_by(
'created') 'created')
your_teams = Team.objects.filter(Q(contractors__id=request.user.pk) | Q(owner=request.user)) your_teams = Team.objects.filter(Q(contractors__id=request.user.pk) | Q(owner=request.user))
orders_ms_count = request.user.new_messages.filter(message__order__in=orders, message__team__isnull=True).count() orders_ms_count = request.user.new_messages.filter(message__order__in=orders,
message__team__isnull=True).count()
teams_ms_count = request.user.new_messages.filter(message__team__in=your_teams).count() teams_ms_count = request.user.new_messages.filter(message__team__in=your_teams).count()
self.template_name = 'chat_contractor.html' self.template_name = 'chat_contractor.html'
@ -146,7 +152,7 @@ def project_delete(request):
if request.is_ajax(): if request.is_ajax():
project_id = request.POST.get('project_id') project_id = request.POST.get('project_id')
try: try:
project = Project.objects.get(pk=project_id,customer=request.user) project = Project.objects.get(pk=project_id, customer=request.user)
except Documents.DoesNotExist: except Documents.DoesNotExist:
project = None project = None
if project: if project:
@ -160,7 +166,7 @@ def project_delete(request):
raise Http404 raise Http404
def download_file(request,file_name): def download_file(request, file_name):
try: try:
document = Documents.objects.get(file=file_name) document = Documents.objects.get(file=file_name)
except Documents.DoesNotExist: except Documents.DoesNotExist:

@ -1,7 +1,10 @@
import pydash as _;
from django import forms from django import forms
from django.contrib import admin from django.contrib import admin
from mptt.admin import MPTTModelAdmin from mptt.admin import MPTTModelAdmin
import pydash as _; _.map = _.map_; _.filter = _.filter_
_.map = _.map_;
_.filter = _.filter_
from .models import ( from .models import (
LiveImageUpload, LiveImageUpload,
@ -29,7 +32,7 @@ class MainPageAdminForm(forms.ModelForm):
'lib/ckeditor/adapters/jquery.js', 'lib/ckeditor/adapters/jquery.js',
) )
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
for field_name in ('contractor_text', 'customer_text'): for field_name in ('contractor_text', 'customer_text'):
@ -53,7 +56,7 @@ class TooltipAdminForm(forms.ModelForm):
'lib/ckeditor/adapters/jquery.js', 'lib/ckeditor/adapters/jquery.js',
) )
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
for field_name in ('text', 'example'): for field_name in ('text', 'example'):

@ -1,10 +1,14 @@
import pydash as _;
from django import forms from django import forms
from registration.forms import RegistrationFormTermsOfService from registration.forms import RegistrationFormTermsOfService
import pydash as _; _.map = _.map_; _.filter = _.filter_
_.map = _.map_;
_.filter = _.filter_
from .models import PrintOrder, PrintDocuments from .models import PrintOrder, PrintDocuments
from captcha.fields import ReCaptchaField from captcha.fields import ReCaptchaField
class PrintOrderForm(forms.ModelForm): class PrintOrderForm(forms.ModelForm):
files = forms.ModelMultipleChoiceField( files = forms.ModelMultipleChoiceField(
queryset=PrintDocuments.objects.none(), queryset=PrintDocuments.objects.none(),

@ -1,11 +1,12 @@
import datetime import datetime
from django.utils.timezone import now from django.utils.timezone import now
from users.models import User
from ratings.models import HistoryRating from ratings.models import HistoryRating
from users.models import User
class SetLastVisitMiddleware(object): class SetLastVisitMiddleware(object):
def process_response(self, request, response): def process_response(self, request, response):
if hasattr(request, 'user'): if hasattr(request, 'user'):
if request.user.is_authenticated(): if request.user.is_authenticated():
@ -14,7 +15,6 @@ class SetLastVisitMiddleware(object):
class SetRatingToUserEveryDay(object): class SetRatingToUserEveryDay(object):
def process_response(self, request, response): def process_response(self, request, response):
if hasattr(request, 'user'): if hasattr(request, 'user'):
today_date = datetime.datetime.now().date() today_date = datetime.datetime.now().date()
@ -27,4 +27,3 @@ class SetRatingToUserEveryDay(object):
hs_new.description = 'Балл за вход на сайт' hs_new.description = 'Балл за вход на сайт'
hs_new.save() hs_new.save()
return response return response

@ -44,7 +44,7 @@ class Settings(models.Model):
document_send_time_remove = models.IntegerField(default=14) document_send_time_remove = models.IntegerField(default=14)
recalculation_spec_time = models.TimeField() recalculation_spec_time = models.TimeField()
recalculation_rating_time = models.TimeField() recalculation_rating_time = models.TimeField()
noreply_email = models.CharField(max_length=50,default='noreply@proekton.com') noreply_email = models.CharField(max_length=50, default='noreply@proekton.com')
def __str__(self): def __str__(self):
return 'Настройки сайта' return 'Настройки сайта'

@ -1,3 +1 @@
from django.test import TestCase
# Create your tests here. # Create your tests here.

@ -14,5 +14,6 @@ urlpatterns = [
urls.url(r'^printorder/(?P<pk>\d+)/$', PrintOrderDetailView.as_view(), name='print-order-detail'), urls.url(r'^printorder/(?P<pk>\d+)/$', PrintOrderDetailView.as_view(), name='print-order-detail'),
urls.url(r'^live-image-upload/create/$', LiveImageUploadCreateView.as_view(), name='live-image-upload-create'), urls.url(r'^live-image-upload/create/$', LiveImageUploadCreateView.as_view(), name='live-image-upload-create'),
urls.url(r'^live-image-upload/(?P<pk>\d+)/delete/$', LiveImageUploadDeleteView.as_view(), name='live-image-upload-delete'), urls.url(r'^live-image-upload/(?P<pk>\d+)/delete/$', LiveImageUploadDeleteView.as_view(),
name='live-image-upload-delete'),
] ]

@ -1,8 +1,7 @@
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.models import Group from django.contrib.auth.models import Group
from django.core.exceptions import PermissionDenied from django.core.mail import EmailMultiAlternatives
from django.core.mail import send_mail, EmailMultiAlternatives
from django.core.urlresolvers import reverse, reverse_lazy from django.core.urlresolvers import reverse, reverse_lazy
from django.http import JsonResponse from django.http import JsonResponse
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
@ -10,15 +9,13 @@ from django.template.loader import get_template, render_to_string
from django.views.generic import View, DetailView from django.views.generic import View, DetailView
from registration.backends.default.views import RegistrationView from registration.backends.default.views import RegistrationView
from sorl.thumbnail import get_thumbnail from sorl.thumbnail import get_thumbnail
import json
import jsonschema
from .forms import PrintOrderForm, CustomRegistrationForm
from .models import PrintDocuments, PrintOrder, Settings, LiveImageUpload
from archilance import util from archilance import util
from archilance.mixins import BaseMixin from archilance.mixins import BaseMixin
from common.mixins import NoCsrfMixin from common.mixins import NoCsrfMixin
from users.models import ContractorResume from users.models import ContractorResume
from .forms import PrintOrderForm, CustomRegistrationForm
from .models import PrintDocuments, PrintOrder, Settings, LiveImageUpload
class PrintOrderDetailView(DetailView): class PrintOrderDetailView(DetailView):
@ -62,7 +59,6 @@ class PrintDocumentCreate(BaseMixin, View):
'files': link_files, 'files': link_files,
} }
settings = Settings.objects.all().first() settings = Settings.objects.all().first()
subject, from_email, to = 'Заявка на распечатку', settings.noreply_email, settings.document_send_email subject, from_email, to = 'Заявка на распечатку', settings.noreply_email, settings.document_send_email
text_content = render_to_string('document_email.txt', ctx_dict) text_content = render_to_string('document_email.txt', ctx_dict)
@ -74,7 +70,7 @@ class PrintDocumentCreate(BaseMixin, View):
msg.send() msg.send()
messages.info(request, 'Заявка на распечатку принята') messages.info(request, 'Заявка на распечатку принята')
return redirect('common:print-order-detail',pk=print_order.pk) return redirect('common:print-order-detail', pk=print_order.pk)
# import code; code.interact(local=dict(globals(), **locals())) # import code; code.interact(local=dict(globals(), **locals()))
else: else:
context = self.get_context_data(**kwargs) context = self.get_context_data(**kwargs)
@ -82,7 +78,6 @@ class PrintDocumentCreate(BaseMixin, View):
return render(request, self.template_name, context) return render(request, self.template_name, context)
class LiveImageUploadCreateView(NoCsrfMixin, LoginRequiredMixin, View): class LiveImageUploadCreateView(NoCsrfMixin, LoginRequiredMixin, View):
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
image = request.FILES.get('image') image = request.FILES.get('image')
@ -153,5 +148,4 @@ class CustomRegistrationView(RegistrationView):
return user return user
# import code; code.interact(local=dict(globals(), **locals())) # import code; code.interact(local=dict(globals(), **locals()))

@ -35,7 +35,7 @@ class ProjectAdminForm(forms.ModelForm):
class ProjectAdmin(admin.ModelAdmin): class ProjectAdmin(admin.ModelAdmin):
readonly_fields = ('pk',) readonly_fields = ('pk',)
list_display = ('name','pk','customer','state') list_display = ('name', 'pk', 'customer', 'state')
form = ProjectAdminForm form = ProjectAdminForm
@ -44,7 +44,7 @@ class OrderAdmin(admin.ModelAdmin):
class StageAdmin(admin.ModelAdmin): class StageAdmin(admin.ModelAdmin):
list_display = ('name','status','pos','order','is_paid',) list_display = ('name', 'status', 'pos', 'order', 'is_paid',)
admin.site.register(Answer) admin.site.register(Answer)

@ -6,5 +6,4 @@ class ProjectsConfig(AppConfig):
name = 'projects' name = 'projects'
def ready(self): def ready(self):
import projects.signals pass

@ -129,6 +129,7 @@ class PortfolioPhotoFilterSet(FilterSet):
id = AllLookupsFilter() id = AllLookupsFilter()
portfolio = RelatedFilter('projects.filters.PortfolioFilterSet') portfolio = RelatedFilter('projects.filters.PortfolioFilterSet')
# img = ??? # img = ???
class Meta: class Meta:

@ -1,10 +1,13 @@
import itertools
import pydash as _;
from django import forms from django import forms
from django.db.models import Q from django.db.models import Q
from django.forms.models import inlineformset_factory from django.forms.models import inlineformset_factory
from mptt.forms import TreeNodeChoiceField from mptt.forms import TreeNodeChoiceField
from pprint import pprint, pformat
import itertools _.map = _.map_;
import pydash as _; _.map = _.map_; _.filter = _.filter_ _.filter = _.filter_
from .models import ( from .models import (
Project, ProjectFile, Portfolio, Answer, Project, ProjectFile, Portfolio, Answer,
@ -14,11 +17,11 @@ from .models import (
from archilance import util from archilance import util
from common.models import Location, LiveImageUpload from common.models import Location, LiveImageUpload
from specializations.models import Specialization from specializations.models import Specialization
from users.models import User, Team from users.models import Team
class ProjectFilterForm(forms.ModelForm): class ProjectFilterForm(forms.ModelForm):
PROJECT_ORDER_CHOICES = ( # "Упорядочить по"... PROJECT_ORDER_CHOICES = ( # "Упорядочить по"...
('name', 'названию'), ('name', 'названию'),
('budget', 'цене'), ('budget', 'цене'),
('created', 'дате размещения'), ('created', 'дате размещения'),
@ -49,7 +52,7 @@ class ProjectFilterForm(forms.ModelForm):
self.request = kwargs.pop('request') self.request = kwargs.pop('request')
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.fields['work_type'].choices = tuple(itertools.chain((('',''),), self.fields['work_type'].choices)) self.fields['work_type'].choices = tuple(itertools.chain((('', ''),), self.fields['work_type'].choices))
self.fields['work_type'].required = False self.fields['work_type'].required = False
self.fields['work_type'].initial = '' self.fields['work_type'].initial = ''
@ -85,7 +88,8 @@ class ProjectFilterRealtyForm(forms.ModelForm):
self.fields['construction_type'].required = False self.fields['construction_type'].required = False
self.fields['location'].queryset = Location.objects.root_nodes()[0].get_descendants() self.fields['location'].queryset = Location.objects.root_nodes()[0].get_descendants()
self.fields['building_classification'].queryset = BuildingClassfication.objects.root_nodes()[0].get_descendants() self.fields['building_classification'].queryset = BuildingClassfication.objects.root_nodes()[
0].get_descendants()
# self.fields['location'].queryset = Location.objects # Migrate with this enabled # self.fields['location'].queryset = Location.objects # Migrate with this enabled
@ -184,7 +188,8 @@ class RealtyForm(forms.ModelForm):
self.fields['name'].required = False self.fields['name'].required = False
self.fields['location'].queryset = Location.objects.root_nodes()[0].get_descendants() self.fields['location'].queryset = Location.objects.root_nodes()[0].get_descendants()
self.fields['building_classification'].queryset = BuildingClassfication.objects.root_nodes()[0].get_descendants() self.fields['building_classification'].queryset = BuildingClassfication.objects.root_nodes()[
0].get_descendants()
# self.fields['location'].queryset = Location.objects # Migrate with this enabled # self.fields['location'].queryset = Location.objects # Migrate with this enabled
@ -300,7 +305,8 @@ class ProjectAnswerForm(forms.ModelForm):
# for c in members: # for c in members:
# portfolios.extend(c.portfolios.all()) # portfolios.extend(c.portfolios.all())
portfolios = Portfolio.objects.filter(user__pk__in=tuple(m.pk for m in itertools.chain((contractor,), members))) portfolios = Portfolio.objects.filter(
user__pk__in=tuple(m.pk for m in itertools.chain((contractor,), members)))
self.fields['portfolios'].queryset = portfolios self.fields['portfolios'].queryset = portfolios
else: else:
@ -416,5 +422,4 @@ class ProjectWorkTypeSuggestionForm(forms.ModelForm):
self['username'].field.initial = self.request.user.username self['username'].field.initial = self.request.user.username
self['email'].field.initial = self.request.user.email self['email'].field.initial = self.request.user.email
# import code; code.interact(local=dict(globals(), **locals())) # import code; code.interact(local=dict(globals(), **locals()))

@ -0,0 +1,48 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-10-14 22:49+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: templates/_trash/project_form.html:46
#: templates/contractor_portfolio_edit.html:46
#: templates/customer_project_create.html:62
#: templates/customer_project_edit.html:72 templates/project_filter.html:21
msgid "project_stage0"
msgstr "Тип работы"
#: templates/contractor_portfolio_edit.html:59
#: templates/customer_project_create.html:89
#: templates/customer_project_edit.html:99 templates/project_filter.html:35
msgid "project_stage1"
msgstr "Стадия проекта"
#: templates/contractor_portfolio_edit.html:64
#: templates/customer_project_create.html:94
#: templates/customer_project_edit.html:104 templates/project_filter.html:39
msgid "project_stage2"
msgstr "Раздел"
#: templates/contractor_portfolio_edit.html:69
#: templates/customer_project_create.html:99
#: templates/customer_project_edit.html:109 templates/project_filter.html:43
msgid "project_stage3"
msgstr "Подраздел"
#: templates/contractor_portfolio_edit.html:74
#: templates/customer_project_create.html:104
#: templates/customer_project_edit.html:114 templates/project_filter.html:47
msgid "project_stage4"
msgstr "Подраздел ( доп. )"

@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-10-14 20:49
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('projects', '0046_merge'),
]
operations = [
migrations.AlterModelOptions(
name='buildingclassfication',
options={'ordering': ['order'], 'verbose_name': 'Тип здания', 'verbose_name_plural': 'Типы зданий'},
),
migrations.AlterModelOptions(
name='constructiontype',
options={'ordering': ['order'], 'verbose_name': 'Вид строительства', 'verbose_name_plural': 'Виды строительства'},
),
migrations.AlterModelManagers(
name='buildingclassfication',
managers=[
],
),
migrations.AddField(
model_name='buildingclassfication',
name='order',
field=models.PositiveSmallIntegerField(default=0, null=True),
),
migrations.AddField(
model_name='constructiontype',
name='order',
field=models.PositiveSmallIntegerField(default=0, null=True),
),
]

@ -1,17 +1,19 @@
import pydash as _;
from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType 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.db.models import Q
from django.core.exceptions import ValidationError
from django.utils import timezone from django.utils import timezone
from hitcount.models import HitCountMixin from hitcount.models import HitCountMixin
from mptt.managers import TreeManager
from mptt.models import TreeForeignKey, MPTTModel from mptt.models import TreeForeignKey, MPTTModel
import pydash as _; _.map = _.map_; _.filter = _.filter_
_.map = _.map_;
_.filter = _.filter_
from users.models import User, Team from users.models import User, Team
from specializations.models import Specialization from specializations.models import Specialization
CURRENCIES = ( CURRENCIES = (
('rur', 'RUR'), ('rur', 'RUR'),
('usd', 'USD'), ('usd', 'USD'),
@ -36,22 +38,31 @@ TERM_TYPE_MORPHS = {
class BuildingClassfication(MPTTModel): class BuildingClassfication(MPTTModel):
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
parent = TreeForeignKey('self', blank=True, null=True, related_name='children', db_index=True) parent = TreeForeignKey('self', blank=True, null=True, related_name='children', db_index=True)
order = models.PositiveSmallIntegerField(default=0, null=True)
objects = TreeManager()
def __str__(self): def __str__(self):
return self.name return self.name
class MPTTMeta:
order_insertion_by = ['order']
class Meta: class Meta:
ordering = ['order']
verbose_name = 'Тип здания' verbose_name = 'Тип здания'
verbose_name_plural = 'Типы зданий' verbose_name_plural = 'Типы зданий'
class ConstructionType(models.Model): class ConstructionType(models.Model):
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
order = models.PositiveSmallIntegerField(default=0, null=True)
def __str__(self): def __str__(self):
return self.name return self.name
class Meta: class Meta:
ordering = ['order']
verbose_name = 'Вид строительства' verbose_name = 'Вид строительства'
verbose_name_plural = 'Виды строительства' verbose_name_plural = 'Виды строительства'
@ -61,7 +72,7 @@ class Realty(models.Model):
construction_type = models.ForeignKey(ConstructionType, related_name='realties') construction_type = models.ForeignKey(ConstructionType, related_name='realties')
location = TreeForeignKey('common.Location', related_name='realties', null=True, blank=True) location = TreeForeignKey('common.Location', related_name='realties', null=True, blank=True)
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
user = models.ForeignKey(User, related_name='realties') # Do we actually need this field? user = models.ForeignKey(User, related_name='realties') # Do we actually need this field?
def __str__(self): def __str__(self):
return self.name return self.name
@ -79,8 +90,8 @@ class Project(models.Model, HitCountMixin):
) )
DEAL_TYPES = ( DEAL_TYPES = (
('secure_deal', 'Безопасная сделка'), # "Безопасная сделка (с резервированием бюджета)" ('secure_deal', 'Безопасная сделка'), # "Безопасная сделка (с резервированием бюджета)"
('direct_payment', 'Прямая оплата'), # "Прямая оплата Исполнителю на его кошелек/счет" ('direct_payment', 'Прямая оплата'), # "Прямая оплата Исполнителю на его кошелек/счет"
) )
STATES = ( STATES = (
@ -137,7 +148,7 @@ class Answer(models.Model):
budget = models.DecimalField(max_digits=10, decimal_places=0, blank=True, null=True) budget = models.DecimalField(max_digits=10, decimal_places=0, blank=True, null=True)
created = models.DateTimeField(default=timezone.now) created = models.DateTimeField(default=timezone.now)
currency = models.CharField(max_length=5, choices=CURRENCIES, blank=True, null=True) currency = models.CharField(max_length=5, choices=CURRENCIES, blank=True, null=True)
portfolios = models.ManyToManyField('Portfolio', related_name ='answers', blank=True) 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) secure_deal_only = models.BooleanField(default=False)
term = models.IntegerField(blank=True, null=True) term = models.IntegerField(blank=True, null=True)
@ -145,7 +156,9 @@ class Answer(models.Model):
is_archive = models.BooleanField(default=False) is_archive = models.BooleanField(default=False)
rejected = models.BooleanField(default=False) rejected = models.BooleanField(default=False)
content_type = models.ForeignKey(ContentType, limit_choices_to=Q(app_label='users', model='user') | Q(app_label='users', model='team')) content_type = models.ForeignKey(ContentType,
limit_choices_to=Q(app_label='users', model='user') | Q(app_label='users',
model='team'))
object_id = models.IntegerField() object_id = models.IntegerField()
author = GenericForeignKey('content_type', 'object_id') author = GenericForeignKey('content_type', 'object_id')
@ -216,7 +229,8 @@ class Order(models.Model):
('completed', 'Завершен'), ('completed', 'Завершен'),
) )
contractor = models.ForeignKey(User, null=True, blank=True, related_name='orders') # Related name should've been "contractor_orders" contractor = models.ForeignKey(User, null=True, blank=True,
related_name='orders') # Related name should've been "contractor_orders"
created = models.DateTimeField(default=timezone.now) created = models.DateTimeField(default=timezone.now)
project = models.OneToOneField(Project, related_name='order') project = models.OneToOneField(Project, related_name='order')
secure = models.BooleanField(default=False) secure = models.BooleanField(default=False)
@ -238,6 +252,7 @@ class Order(models.Model):
else: else:
return None return None
class Arbitration(models.Model): class Arbitration(models.Model):
user = models.ForeignKey(User) user = models.ForeignKey(User)
text = models.TextField() text = models.TextField()
@ -252,7 +267,7 @@ class Arbitration(models.Model):
verbose_name_plural = 'Арбитраж' verbose_name_plural = 'Арбитраж'
unique_together = ( unique_together = (
('user', 'order'), ('user', 'order'),
) )
@ -264,7 +279,6 @@ STATUSES = (
('completed', 'Завершен'), ('completed', 'Завершен'),
) )
from .validators import validate_term
class Stage(models.Model): class Stage(models.Model):
cost = models.DecimalField(max_digits=10, decimal_places=0) cost = models.DecimalField(max_digits=10, decimal_places=0)
@ -304,8 +318,9 @@ class Stage(models.Model):
class Candidate(models.Model): class Candidate(models.Model):
answer = models.ForeignKey(Answer, related_name='candidates') # TODO: Swap to "OneToOneField" answer = models.ForeignKey(Answer, related_name='candidates') # TODO: Swap to "OneToOneField"
project = models.ForeignKey(Project, related_name='candidates') # TODO: Remove this redundant field at all (we've got "candidate.answer.project") project = models.ForeignKey(Project,
related_name='candidates') # TODO: Remove this redundant field at all (we've got "candidate.answer.project")
status = models.BooleanField(default=False) status = models.BooleanField(default=False)
position = models.PositiveIntegerField(default=0) position = models.PositiveIntegerField(default=0)
@ -356,7 +371,7 @@ class Portfolio(models.Model):
def get_cover(self): def get_cover(self):
photo = self.photos.first() photo = self.photos.first()
return photo and photo.img # WTF? We could at leat return a URL, not an object return photo and photo.img # WTF? We could at leat return a URL, not an object
class PortfolioPhoto(models.Model): class PortfolioPhoto(models.Model):

@ -1,12 +1,13 @@
from rest_framework import serializers
from generic_relations.relations import GenericRelatedField from generic_relations.relations import GenericRelatedField
from rest_framework.serializers import ModelSerializer, ImageField, FileField, SerializerMethodField, PrimaryKeyRelatedField, ReadOnlyField from rest_framework import serializers
from rest_framework.serializers import ModelSerializer, ImageField, FileField, PrimaryKeyRelatedField
from .models import Project, Realty, BuildingClassfication, ConstructionType, Order, Stage, Portfolio, PortfolioPhoto, Answer, AnswerFile
from common.serializers import LocationSerializer, ContentTypeSerializer from common.serializers import LocationSerializer, ContentTypeSerializer
from specializations.serializers import SpecializationSerializer from specializations.serializers import SpecializationSerializer
from users.models import User, Team from users.models import User, Team
from users.serializers import UserSerializer, TeamSerializer from users.serializers import UserSerializer, TeamSerializer
from .models import Project, Realty, BuildingClassfication, ConstructionType, Order, Stage, Portfolio, PortfolioPhoto, \
Answer, AnswerFile
class AnswerFileSerializer(ModelSerializer): class AnswerFileSerializer(ModelSerializer):
@ -78,16 +79,16 @@ class RealtySerializer(ModelSerializer):
class StageSerializer(ModelSerializer): class StageSerializer(ModelSerializer):
term = serializers.DateField(format="%d.%m.%Y", input_formats=['%d.%m.%Y',]) term = serializers.DateField(format="%d.%m.%Y", input_formats=['%d.%m.%Y', ])
def validate(self, data): def validate(self, data):
if 'pos' in data and data['pos'] > 1: if 'pos' in data and data['pos'] > 1:
pos = data['pos'] -1 pos = data['pos'] - 1
stage_last = Stage.objects.filter(order=data['order'], pos=pos) stage_last = Stage.objects.filter(order=data['order'], pos=pos)
if stage_last: if stage_last:
stage_last = stage_last[0] stage_last = stage_last[0]
if stage_last.term > data['term']: if stage_last.term > data['term']:
raise serializers.ValidationError({'term':'Дата не должна быть меньше даты предыдущео этапа'}) raise serializers.ValidationError({'term': 'Дата не должна быть меньше даты предыдущео этапа'})
return data return data
class Meta: class Meta:
@ -162,7 +163,7 @@ class AnswerSerializer_(ModelSerializer):
'term', 'term',
'term_type', 'term_type',
'author', # Generic related field 'author', # Generic related field
'content_type', 'content_type',
'files', 'files',
) )
@ -171,7 +172,7 @@ class AnswerSerializer_(ModelSerializer):
class ProjectSerializer(ModelSerializer): class ProjectSerializer(ModelSerializer):
answers = AnswerSerializer_(many=True) answers = AnswerSerializer_(many=True)
customer = UserSerializer() customer = UserSerializer()
order = OrderSerializer_() # TODO: Can't serialize a reverse/reciprocal relation order = OrderSerializer_() # TODO: Can't serialize a reverse/reciprocal relation
realty = RealtySerializer() realty = RealtySerializer()
specialization = SpecializationSerializer() specialization = SpecializationSerializer()
@ -303,7 +304,7 @@ class AnswerSerializer(ModelSerializer):
'term', 'term',
'term_type', 'term_type',
'author', # Generic related field 'author', # Generic related field
'content_type', 'content_type',
'files', 'files',
'portfolios', 'portfolios',

@ -1,8 +1,8 @@
from django.core.signals import request_finished
from django.db.models.signals import post_save from django.db.models.signals import post_save
from django.utils import timezone
from django.dispatch import receiver from django.dispatch import receiver
from .models import Stage from django.utils import timezone
from .models import Stage
@receiver(post_save, sender=Stage) @receiver(post_save, sender=Stage)

@ -1,279 +1,279 @@
{% extends 'partials/base.html' %} {% extends 'partials/base.html' %}
{% block content %} {% block content %}
<div class="col-lg-12 allProjects"> <div class="col-lg-12 allProjects">
<p class="titleScore">Новый заказ</p> <p class="titleScore">Новый заказ</p>
</div> </div>
<form method="post"> <form method="post">
{% csrf_token %} {% csrf_token %}
{{ form_project.errors }} {{ form_project.errors }}
{{ form_realty.errors }} {{ form_realty.errors }}
<div class="chatBlock new-rass new-rass2 disTab"> <div class="chatBlock new-rass new-rass2 disTab">
{{ project_form.errors }} {{ project_form.errors }}
<div class="col-lg-9"> <div class="col-lg-9">
<p class="new-pp new-pp3">Формирование заказа</p> <p class="new-pp new-pp3">Формирование заказа</p>
<div class="textAreaBlock2 text-nn box-sizing disTab"> <div class="textAreaBlock2 text-nn box-sizing disTab">
<p>Название заказа</p> <p>Название заказа</p>
<input type="text" class="box-sizing" name="{{ project_form.name.name }}"/> <input type="text" class="box-sizing" name="{{ project_form.name.name }}"/>
{{ project_form.name.errors }} {{ project_form.name.errors }}
</div> </div>
<div class="textAreaBlock2 text-nn box-sizing disTab"> <div class="textAreaBlock2 text-nn box-sizing disTab">
<p>Подробно опишите задание</p> <p>Подробно опишите задание</p>
<textarea name="{{ project_form.text.name }}" id="text-new"></textarea> <textarea name="{{ project_form.text.name }}" id="text-new"></textarea>
</div> </div>
</div> </div>
<div class="col-lg-3 wrChat1"> <div class="col-lg-3 wrChat1">
<div class="messageBlock box-sizing disTab"> <div class="messageBlock box-sizing disTab">
<p>Дополнительно</p> <p>Дополнительно</p>
</div> </div>
<div class="col-lg-12 documentsChat"> <div class="col-lg-12 documentsChat">
{# <form action="" method="post">#} {# <form action="" method="post">#}
{# <div class="upload">#} {# <div class="upload">#}
{# <input type="file" name="upload"/>#} {# <input type="file" name="upload"/>#}
{# <p>+ добавить файл (до 100 файлов)</p>#} {# <p>+ добавить файл (до 100 файлов)</p>#}
{# </div>#} {# </div>#}
{# <input type="submit" value="Submit" />#} {# <input type="submit" value="Submit" />#}
{# </form>#} {# </form>#}
<ul class="list-new-new"> {# <ul class="list-new-new">#}
<li> {# <li>#}
Архитерурное 2.jpg {# Архитерурное 2.jpg#}
<span>7мб</span> {# <span>7мб</span>#}
<div></div> {# <div></div>#}
</li> {# </li>#}
</ul> {# </ul>#}
</div> </div>
<p class="type-work">Тип работы:</p> <p class="type-work">{% trans 'project_stage0' %}:</p>
<div class="mail-block type-work-inset"> <div class="mail-block type-work-inset">
<div class="inset-mb"> <div class="inset-mb">
<label><input type="radio" value="1" name="{{ project_form.type_work.name }}"><span></span></label> <label><input type="radio" value="1" name="{{ project_form.type_work.name }}"><span></span></label>
<p>Проектирование</p> <p>Проектирование</p>
</div> </div>
<div class="inset-mb"> <div class="inset-mb">
<label><input type="radio" value="2" name="{{ project_form.type_work.name }}"><span></span></label> <label><input type="radio" value="2" name="{{ project_form.type_work.name }}"><span></span></label>
<p>Техническое сопровождение</p> <p>Техническое сопровождение</p>
</div> </div>
</div> </div>
<div class="textAreaBlock2 box-sizing disTab"> <div class="textAreaBlock2 box-sizing disTab">
<a href="javascriptt:void(0)" class="new-link new-lw">+ Добавить раздел</a> <a href="javascriptt:void(0)" class="new-link new-lw">+ Добавить раздел</a>
</div> </div>
</div> </div>
</div>
<div class="col-lg-12 new-filter">
<div class="filter clearfix">
<div class="titleF1 disTab">
<div class="col-lg-3">Специализация проекта:</div>
<div class="col-lg-3"></div>
<div class="col-lg-3"></div>
<div class="col-lg-3"></div>
</div> </div>
<div class="col-lg-12 new-filter">
<div class="filter clearfix">
<div class="titleF1 disTab">
<div class="col-lg-3">Специализация проекта:</div>
<div class="col-lg-3"></div>
<div class="col-lg-3"></div>
<div class="col-lg-3"></div>
</div>
<div class="polsF1 disTab"> <div class="polsF1 disTab">
<div class="col-lg-3"> <div class="col-lg-3">
<select id="specialization1" name="{{ project_form.specialization.name }}"> <select id="specialization1" name="{{ project_form.specialization.name }}">
</select> </select>
{# {{ project_form.specialization }}#} {# {{ project_form.specialization }}#}
</div> </div>
<div class="col-lg-3"> <div class="col-lg-3">
<select class="selectpicker"> <select class="selectpicker">
<option>Mustard</option> <option>Mustard</option>
<option>Ketchup</option> <option>Ketchup</option>
<option>Relish</option> <option>Relish</option>
</select> </select>
</div> </div>
<div class="col-lg-3"> <div class="col-lg-3">
{# <select class="selectpicker">#} {# <select class="selectpicker">#}
{# <option>Mustard</option>#} {# <option>Mustard</option>#}
{# <option>Ketchup</option>#} {# <option>Ketchup</option>#}
{# <option>Relish</option>#} {# <option>Relish</option>#}
{# </select>#} {# </select>#}
</div> </div>
<div class="col-lg-3"> <div class="col-lg-3">
{# <select class="selectpicker">#} {# <select class="selectpicker">#}
{# <option>Mustard</option>#} {# <option>Mustard</option>#}
{# <option>Ketchup</option>#} {# <option>Ketchup</option>#}
{# <option>Relish</option>#} {# <option>Relish</option>#}
{# </select>#} {# </select>#}
</div> </div>
</div> </div>
<div class="titleF1 titleF2 disTab"> <div class="titleF1 titleF2 disTab">
<div class="col-lg-4">Бюджет</div> <div class="col-lg-4">Бюджет</div>
<div class="col-lg-8"></div> <div class="col-lg-8"></div>
</div> </div>
<div class="searchF1 polsF1 polsFF"> <div class="searchF1 polsF1 polsFF">
<div class="col-lg-4"> <div class="col-lg-4">
<input type="text" name="{{ project_form.price.name }}" class="box-sizing surr"> <input type="text" name="{{ project_form.price.name }}" class="box-sizing surr">
<select class="selectpicker2 valul"> <select class="selectpicker2 valul">
<option>&#36;</option> <option>&#36;</option>
<option>&#36;</option> <option>&#36;</option>
<option>&#36;</option> <option>&#36;</option>
</select> </select>
</div> </div>
<div class="col-lg-3"> <div class="col-lg-3">
<select class="selectpicker"> <select class="selectpicker">
<option>За проект</option> <option>За проект</option>
<option>Ketchup</option> <option>Ketchup</option>
<option>Relish</option> <option>Relish</option>
</select> </select>
</div> </div>
<div class="col-lg-5 dog-new"> <div class="col-lg-5 dog-new">
<label><input type="checkbox" name="dogovor"><span></span></label> <label><input type="checkbox" name="dogovor"><span></span></label>
<p>или по договоренности</p> <p>или по договоренности</p>
</div> </div>
</div> </div>
<div class="searchF1 polsF1 polsFF make-new"> <div class="searchF1 polsF1 polsFF make-new">
<label><input type="checkbox" name="dogovor"><span></span></label> <label><input type="checkbox" name="dogovor"><span></span></label>
<p>Сделать для исполнителей обязательным для заполнения поля цена и срок</p> <p>Сделать для исполнителей обязательным для заполнения поля цена и срок</p>
</div> </div>
<div class="titleF1 titleF2 disTab"> <div class="titleF1 titleF2 disTab">
<div class="col-lg-12">Способ оплаты</div> <div class="col-lg-12">Способ оплаты</div>
</div> </div>
<div class="searchF1 polsF1 polsFF radio-afer"> <div class="searchF1 polsF1 polsFF radio-afer">
<div class="col-lg-6"> <div class="col-lg-6">
<label><input type="radio" name="afer"><span></span></label> <label><input type="radio" name="afer"><span></span></label>
<p class="text-afer"> <p class="text-afer">
Безопасная сделка (с резервированием бюджета) Безопасная сделка (с резервированием бюджета)
</p> </p>
<p class="des-afer"> <p class="des-afer">
Текст Текст
</p> </p>
</div> </div>
<div class="col-lg-6"> <div class="col-lg-6">
<label><input type="radio" name="afer"><span></span></label> <label><input type="radio" name="afer"><span></span></label>
<p class="text-afer"> <p class="text-afer">
Прямая оплата Исполнителю на его кошелек/счет Прямая оплата Исполнителю на его кошелек/счет
</p> </p>
<p class="des-afer"> <p class="des-afer">
Текст Текст
</p> </p>
</div> </div>
</div> </div>
<div class="resSearchF1"> <div class="resSearchF1">
<div class="col-lg-3"> <div class="col-lg-3">
<p class="titleResF1">Расширенный поиск</p> <p class="titleResF1">Расширенный поиск</p>
<button class="resButtonF1"> <button class="resButtonF1">
<span class="glyphicon glyphicon-arrow-up" aria-hidden="true"></span> <span class="glyphicon glyphicon-arrow-up" aria-hidden="true"></span>
</button> </button>
</div> </div>
<div class="col-lg-9"> <div class="col-lg-9">
<div class="borderS1"></div> <div class="borderS1"></div>
</div> </div>
</div> </div>
<div class="slideRes disTab activeSlide"> <div class="slideRes disTab activeSlide">
<div class="titleF1 disTab"> <div class="titleF1 disTab">
<div class="col-lg-3">Выбор объекта:</div> <div class="col-lg-3">Выбор объекта:</div>
<div class="col-lg-3">Наименование:</div> <div class="col-lg-3">Наименование:</div>
<div class="col-lg-3">Классификация здания:</div> <div class="col-lg-3">Классификация здания:</div>
<div class="col-lg-3">Вид строительства:</div> <div class="col-lg-3">Вид строительства:</div>
</div> </div>
<div class="polsF1 polsF2 disTab"> <div class="polsF1 polsF2 disTab">
<div class="col-lg-3"> <div class="col-lg-3">
<select class="selectpicker" > <select class="selectpicker">
<option>Mustard</option> <option>Mustard</option>
<option>Ketchup</option> <option>Ketchup</option>
<option>Relish</option> <option>Relish</option>
</select> </select>
</div> </div>
<div class="col-lg-3"> <div class="col-lg-3">
<input type="text" class="box-sizing surr surr2" name="{{ realty_form.name.name }}"> <input type="text" class="box-sizing surr surr2" name="{{ realty_form.name.name }}">
</div> </div>
<div class="col-lg-3"> <div class="col-lg-3">
<select class="selectpicker" name="{{ realty_form.building_classification.name }}"> <select class="selectpicker" name="{{ realty_form.building_classification.name }}">
<option>Mustard</option> <option>Mustard</option>
<option>Ketchup</option> <option>Ketchup</option>
<option>Relish</option> <option>Relish</option>
</select> </select>
</div> </div>
<div class="col-lg-3"> <div class="col-lg-3">
<select class="selectpicker" name="{{ realty_form.type_construction.name }}"> <select class="selectpicker" name="{{ realty_form.type_construction.name }}">
<option>Mustard</option> <option>Mustard</option>
<option>Ketchup</option> <option>Ketchup</option>
<option>Relish</option> <option>Relish</option>
</select> </select>
</div> </div>
</div> </div>
<div class="titleF1 disTab"> <div class="titleF1 disTab">
<div class="col-lg-12">Местоположение:</div> <div class="col-lg-12">Местоположение:</div>
</div> </div>
<div class="polsF1 polsF2 disTab"> <div class="polsF1 polsF2 disTab">
<div class="col-lg-3"> <div class="col-lg-3">
<select class="selectpicker" name="{{ realty_form.country.name }}"> <select class="selectpicker" name="{{ realty_form.country.name }}">
<option>Страна</option> <option>Страна</option>
<option>Ketchup</option> <option>Ketchup</option>
<option>Relish</option> <option>Relish</option>
</select> </select>
</div> </div>
<div class="col-lg-3"> <div class="col-lg-3">
<select class="selectpicker" {{ realty_form.city.name }}> <select class="selectpicker" {{ realty_form.city.name }}>
<option>Город</option> <option>Город</option>
<option>Ketchup</option> <option>Ketchup</option>
<option>Relish</option> <option>Relish</option>
</select> </select>
</div> </div>
<div class="col-lg-6 make-new"> <div class="col-lg-6 make-new">
<label><input type="checkbox" name="dogovor"><span></span></label> <label><input type="checkbox" name="dogovor"><span></span></label>
<p>Требуется допуск СРО</p> <p>Требуется допуск СРО</p>
</div> </div>
</div> </div>
<div class="searchF1 polsF1 polsFF links-filter"> <div class="searchF1 polsF1 polsFF links-filter">
<input style="border-radius: 40px; <input style="border-radius: 40px;
font-family: 'pfdintextcomppro-regular', sans-serif;color: black;font-size: 16px;padding: 17px 33px 17px 33px; font-family: 'pfdintextcomppro-regular', sans-serif;color: black;font-size: 16px;padding: 17px 33px 17px 33px;
float: left;margin: 0 15px 48px 15px;border: 1px solid #DFDFDF;text-transform: uppercase; float: left;margin: 0 15px 48px 15px;border: 1px solid #DFDFDF;text-transform: uppercase;
letter-spacing: 2px;color: #42B476;border: 1px solid #42B476" type="submit" value="Разместить проект" /> letter-spacing: 2px;color: #42B476;border: 1px solid #42B476" type="submit" value="Разместить проект"/>
<a href="javascript:void(0)">Сохранить</a> <a href="javascript:void(0)">Сохранить</a>
</div> </div>
</div>
</div>
</div> </div>
</div>
</div>
</form> </form>
{% endblock %} {% endblock %}
{% block js_block %} {% block js_block %}
<script type="text/javascript"> <script type="text/javascript">
$(function () { $(function () {
function updateSelectData() {
function updateSelectData(){
}
} $.ajax({
$.ajax({ url: '/api/specializations?parent=1',
url: '/api/specializations?parent=1', type: 'GET',
type: 'GET', dataType: 'json',
dataType: 'json', success: function (json) {
success: function (json) {
console.log(json.results); console.log(json.results);
var out = '' var out = ''
$.each(json.results, function (i, v) { $.each(json.results, function (i, v) {
$('#specialization1') $('#specialization1')
.append($("<option></option>") .append($("<option></option>")
.attr("value", v.name) .attr("value", v.name)
.text(v.name)); .text(v.name));
}); });
$("#specialization1").addClass("selectpicker"); $("#specialization1").addClass("selectpicker");
$('.selectpicker').selectpicker({ $('.selectpicker').selectpicker({
style: 'btn-info', style: 'btn-info',
size: 4, size: 4,
width: '237px' width: '237px'
}); });
} }
}); });
$("#specialization1").on("change",function(){ $("#specialization1").on("change", function () {
}); });
}); });
</script> </script>
{% endblock %} {% endblock %}

@ -1,18 +1,18 @@
<form method="post" action="">{% csrf_token %} <form method="post" action="">{% csrf_token %}
{{ form.as_p }} {{ form.as_p }}
<fieldset> <fieldset>
<legend>Photos</legend> <legend>Photos</legend>
{{ portfolio_photo_form.management_form }} {{ portfolio_photo_form.management_form }}
{{ portfolio_photo_form.non_form_errors }} {{ portfolio_photo_form.non_form_errors }}
{% for form in portfolio_photo_form %} {% for form in portfolio_photo_form %}
{{ form.id }} {{ form.id }}
<div class="inline {{ portfolio_photo_form.prefix }}"> <div class="inline {{ portfolio_photo_form.prefix }}">
{{ form.img.errors }} {{ form.img.errors }}
{{ form.img.label_tag }} {{ form.img.label_tag }}
{{ form.img }} {{ form.img }}
</div> </div>
{% endfor %} {% endfor %}
</fieldset> </fieldset>
<input type="submit" value="Add portfolio" class="submit" /> <input type="submit" value="Add portfolio" class="submit"/>
</form> </form>

@ -3,7 +3,7 @@
<h2>Мои проекты</h2> <h2>Мои проекты</h2>
{% for proj in request.user.customer_projects.all %} {% for proj in request.user.customer_projects.all %}
<h3>{{ proj }}</h3> <h3>{{ proj }}</h3>
<h5>{{ proj.order }}</h5> <h5>{{ proj.order }}</h5>
{% endfor %} {% endfor %}

@ -4,155 +4,159 @@
{% load i18n %} {% load i18n %}
{% block content %} {% block content %}
{% include 'partials/header.html' %} {% include 'partials/header.html' %}
<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">Сравнение кандидатов по проекту</p> <p class="titleScore">Сравнение кандидатов по проекту</p>
</div> </div>
<div class="titleBlockComparison disTab"> <div class="titleBlockComparison disTab">
<div class="triangle1"></div> <div class="triangle1"></div>
<p>{{ object }}</p> <p>{{ object }}</p>
<table class="compTable" id="compTable"> <table class="compTable" id="compTable">
<thead> <thead>
<tr> <tr>
<th></th> <th></th>
<th>Кандидат</th> <th>Кандидат</th>
<th>Цена</th> <th>Цена</th>
<th>Срок</th> <th>Срок</th>
<th>Описание</th> <th>Описание</th>
<th>Рейтинги/отзывы</th> <th>Рейтинги/отзывы</th>
<th>Безопасные сделки</th> <th>Безопасные сделки</th>
<th>Решение</th> <th>Решение</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for cand in object.candidates.all %} {% for cand in object.candidates.all %}
<tr style="cursor:move;" class="items[]_{{ cand.pk }}" data-class="items[]_{{ cand.pk }}"> <tr style="cursor:move;" class="items[]_{{ cand.pk }}" data-class="items[]_{{ cand.pk }}">
<td>{{ cand.position }}</td> <td>{{ cand.position }}</td>
<td> <td>
{% if cand.answer.author|class_name == 'User' %} {% if cand.answer.author|class_name == 'User' %}
{% firstof cand.answer.author.get_full_name.strip cand.answer.author.username %} {% firstof cand.answer.author.get_full_name.strip cand.answer.author.username %}
{% elif cand.answer.author|class_name == 'Team' %} {% elif cand.answer.author|class_name == 'Team' %}
{% firstof cand.answer.author.name.strip cand.answer.author.username %} {% firstof cand.answer.author.name.strip cand.answer.author.username %}
{% endif %} {% endif %}
</td> </td>
<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>
{% if cand.answer.term_type == 'project' %} {% if cand.answer.term_type == 'project' %}
За проект За проект
{% elif cand.answer.term and cand.answer.term_type %} {% elif cand.answer.term and cand.answer.term_type %}
{% morph cand.answer.term TERM_TYPE_MORPHS|get:cand.answer.term_type %} {% morph cand.answer.term TERM_TYPE_MORPHS|get:cand.answer.term_type %}
{% endif %} {% endif %}
</td> </td>
<td> <td>
<span class="glyphicon glyphicon-info-sign" aria-hidden="true" data-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"
</td> title="{{ cand.answer.get_first_message }}"></span>
</td>
<td>
<ul> <td>
<ul>
<li><span>{{ cand.answer.author.rating }}</span></li>
<li><span>{{ cand.answer.author.rating }}</span></li>
<li>
<span>+0</span> 0 <small> - 0</small> <li>
</li> <span>+0</span> 0
<small> - 0</small>
{% if cand.answer.author.cro %} </li>
<li>
СРО {% if cand.answer.author.cro %}
</li> <li>
{% endif %} СРО
</ul> </li>
</td> {% endif %}
</ul>
<td> </td>
<span>0</span><br>
{% if cand.answer.secure_deal_only %} <td>
Готов работать по безопасной сделке <span>0</span><br>
{% endif %} {% if cand.answer.secure_deal_only %}
</td> Готов работать по безопасной сделке
{% endif %}
<td> </td>
<div class="tableButtons disTab">
<form action="{% url 'projects:customer-offer-order' answer_id=cand.answer.pk project_id=cand.project.pk %}" method="POST" novalidate> <td>
{% csrf_token %} <div class="tableButtons disTab">
<form
<a href="#" onclick="$(this).closest('form').submit(); return false"> action="{% url 'projects:customer-offer-order' answer_id=cand.answer.pk project_id=cand.project.pk %}"
<div class="btnTab btnTab1" title="Предложить проект"></div> method="POST" novalidate>
</a> {% csrf_token %}
</form>
<a href="#" onclick="$(this).closest('form').submit(); return false">
<a href="{% url 'chat:chat-user' %}?user_id={{ cand.answer.author.pk }}"> <div class="btnTab btnTab1" title="Предложить проект"></div>
<div class="btnTab btnTab2" title="Перейти в чат"></div> </a>
</a> </form>
<form method="POST" action="{% url 'projects:delete-candidate' cand.pk %}"> <a href="{% url 'chat:chat-user' %}?user_id={{ cand.answer.author.pk }}">
{% csrf_token %} <div class="btnTab btnTab2" title="Перейти в чат"></div>
<input class="btnTab btnTab3" type="submit" value="" title="Удалить из сравнения"> </a>
</form>
<form method="POST" action="{% url 'projects:delete-candidate' cand.pk %}">
<a href="{% url 'users:contractor-profile' cand.answer.author.pk %}#open-contact"> {% csrf_token %}
<div class="btnTab btnTab4" title="Показать контакты"></div> <input class="btnTab btnTab3" type="submit" value="" title="Удалить из сравнения">
</a> </form>
</div>
</td> <a href="{% url 'users:contractor-profile' cand.answer.author.pk %}#open-contact">
</tr> <div class="btnTab btnTab4" title="Показать контакты"></div>
{% endfor %} </a>
</tbody> </div>
</table> </td>
</div> </tr>
{% endfor %}
{% include 'partials/footer.html' %} </tbody>
</div> </table>
</div>
{% include 'partials/footer.html' %}
</div> </div>
</div>
{% endblock %} {% endblock %}
{% block js_block %} {% block js_block %}
<script> <script>
$(function () { $(function () {
var fixHelper = function (e, ui) { var fixHelper = function (e, ui) {
ui.children().each(function () { ui.children().each(function () {
$(this).width($(this).width()); $(this).width($(this).width());
});
return ui;
};
$("#compTable tbody").sortable({
forcePlaceholderSize: true,
forceHelperSize: true,
items: 'tr',
update: function () {
var serial = $('#compTable tbody').sortable('serialize', {key: 'items[]', attribute: 'data-class'});
console.log(serial);
$.ajax({
url: '/projects/candidate/comparison/sort/',
method: 'POST',
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
},
data: serial,
dataType: 'json',
success: function (json) {
console.log(json);
},
error: function (jqXHR, e) {
console.log(jqXHR);
console.log(e);
}
});
},
helper: fixHelper,
}).disableSelection();
;
}); });
</script> return ui;
};
$("#compTable tbody").sortable({
forcePlaceholderSize: true,
forceHelperSize: true,
items: 'tr',
update: function () {
var serial = $('#compTable tbody').sortable('serialize', {key: 'items[]', attribute: 'data-class'});
console.log(serial);
$.ajax({
url: '/projects/candidate/comparison/sort/',
method: 'POST',
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
},
data: serial,
dataType: 'json',
success: function (json) {
console.log(json);
},
error: function (jqXHR, e) {
console.log(jqXHR);
console.log(e);
}
});
},
helper: fixHelper,
}).disableSelection();
;
});
</script>
{% endblock %} {% endblock %}

@ -1,177 +1,184 @@
{% extends 'partials/base.html' %} {% extends 'partials/base.html' %}
{% load thumbnail %} {% load thumbnail %}
{% load i18n %}
{% block head_css %} {% block head_css %}
<style> <style>
.-live-image-upload-container .-position-relative-parent {position: relative} .-live-image-upload-container .-position-relative-parent {
position: relative
.-live-image-upload-container .-image-delete, }
.-live-image-upload-container .-live-image-delete {
position: absolute; .-live-image-upload-container .-image-delete,
top: 0; .-live-image-upload-container .-live-image-delete {
right: 0; position: absolute;
background-color: white; top: 0;
} right: 0;
</style> background-color: white;
}
</style>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
{% include 'partials/header.html' %} {% include 'partials/header.html' %}
<div class="container mainScore"> <div class="container mainScore">
<div class="row"> <div class="row">
<div class="col-lg-12 allProjects"> <div class="col-lg-12 allProjects">
<p class="titleScore">Изменение портфолио</p> <p class="titleScore">Изменение портфолио</p>
</div> </div>
<form method="post" enctype="multipart/form-data" id="worksell-add-form" class="-spec-work-type-combo-container"> <form method="post" enctype="multipart/form-data" id="worksell-add-form" class="-spec-work-type-combo-container">
{% csrf_token %} {% csrf_token %}
{{ form.errors }} {{ form.errors }}
<div class="textAreaBlock2 text-nn box-sizing disTab"> <div class="textAreaBlock2 text-nn box-sizing disTab">
<p>Название <span style="color: red">{{ form.name.errors.as_text }}</span></p> <p>Название <span style="color: red">{{ form.name.errors.as_text }}</span></p>
<input type="text" class="box-sizing" name="{{ form.name.html_name }}" value="{{ form.name.value }}"> <input type="text" class="box-sizing" name="{{ form.name.html_name }}" value="{{ form.name.value }}">
<input type="hidden" name="{{ form.contractor.html_name }}" value="{{ form.contractor.value }}" /> <input type="hidden" name="{{ form.contractor.html_name }}" value="{{ form.contractor.value }}"/>
</div> </div>
<div class="textAreaBlock2 text-nn box-sizing disTab"> <div class="textAreaBlock2 text-nn box-sizing disTab">
<p>Описание<span style="color: red">{{ form.description.errors.as_text }}</span></p> <p>Описание<span style="color: red">{{ form.description.errors.as_text }}</span></p>
<textarea name="{{ form.description.html_name }}" id="text-new">{{ form.description.value }}</textarea> <textarea name="{{ form.description.html_name }}" id="text-new">{{ form.description.value }}</textarea>
</div> </div>
<div class="textAreaBlock2 text-nn box-sizing disTab"> <div class="textAreaBlock2 text-nn box-sizing disTab">
<p>Тип работы <span style="color: red">{{ form.work_type.errors.as_text }}</span></p> <p>{% trans 'project_stage0' %} <span style="color: red">{{ form.work_type.errors.as_text }}</span></p>
</div> </div>
<div class="col-lg-3"> <div class="col-lg-3">
<div class="polsF1 disTab" style="padding:0;"> <div class="polsF1 disTab" style="padding:0;">
{{ form.work_type }} {{ form.work_type }}
</div> </div>
</div> </div>
<div class="textAreaBlock2 text-nn box-sizing disTab"> <div class="textAreaBlock2 text-nn box-sizing disTab">
</div> </div>
<div class="col-lg-3 -single-spec-select"> <div class="col-lg-3 -single-spec-select">
<div class="-bold">Стадия проекта <span style="color: red">{{ form.specialization.errors.as_text }}</span></div> <div class="-bold">{% trans 'project_stage1' %} <span
<input type='hidden' class="-spec-select -spec-select-level-1" style="width: 100%"> style="color: red">{{ form.specialization.errors.as_text }}</span></div>
</div> <input type='hidden' class="-spec-select -spec-select-level-1" style="width: 100%">
</div>
<div class="col-lg-3 -single-spec-select"> <div class="col-lg-3 -single-spec-select">
<div class="-bold"><span class="-dynamic-label">Стадия проекта</span></div> <div class="-bold"><span class="-dynamic-label">{% trans 'project_stage2' %}</span></div>
<input type='hidden' class="-spec-select -spec-select-level-2" style="width: 100%"> <input type='hidden' class="-spec-select -spec-select-level-2" style="width: 100%">
</div> </div>
<div class="col-lg-3 -single-spec-select"> <div class="col-lg-3 -single-spec-select">
<div class="-bold">Раздел</div> <div class="-bold">{% trans 'project_stage3' %}</div>
<input type='hidden' class="-spec-select -spec-select-level-3" style="width: 100%"> <input type='hidden' class="-spec-select -spec-select-level-3" style="width: 100%">
</div> </div>
<div class="col-lg-3 -single-spec-select"> <div class="col-lg-3 -single-spec-select">
<div class="-bold">Подраздел</div> <div class="-bold">{% trans 'project_stage4' %}</div>
<input type='hidden' class="-spec-select -spec-select-level-4" style="width: 100%"> <input type='hidden' class="-spec-select -spec-select-level-4" style="width: 100%">
</div> </div>
<input type="hidden" class="-chosen-spec-id" name="{{ form.specialization.html_name }}" <input type="hidden" class="-chosen-spec-id" name="{{ form.specialization.html_name }}"
value="{{ form.specialization.value }}"> value="{{ form.specialization.value }}">
<div class="textAreaBlock2 text-nn box-sizing disTab"> <div class="textAreaBlock2 text-nn box-sizing disTab">
<p>Бюджет{{ form.budget.errors.as_text }}</p> <p>Бюджет{{ form.budget.errors.as_text }}</p>
<div class="row"> <div class="row">
<div class="col-lg-8"> <div class="col-lg-8">
<input type="text" class="box-sizing" name="{{ form.budget.html_name }}" value="{{ form.budget.value }}"> <input type="text" class="box-sizing" name="{{ form.budget.html_name }}" value="{{ form.budget.value }}">
</div>
<div class="col-lg-4">
{{ form.currency}}
</div>
</div> </div>
</div> <div class="col-lg-4">
{{ form.currency }}
</div>
</div>
</div>
<div class="textAreaBlock2 text-nn box-sizing disTab"> <div class="textAreaBlock2 text-nn box-sizing disTab">
<p>Срок выполнения{{ form.budget.errors.as_text }}</p> <p>Срок выполнения{{ form.budget.errors.as_text }}</p>
<div class="row"> <div class="row">
<div class="col-lg-8"> <div class="col-lg-8">
<input type="text" class="box-sizing" name="{{ form.term.html_name }}" value="{{ form.term.value }}"> <input type="text" class="box-sizing" name="{{ form.term.html_name }}" value="{{ form.term.value }}">
</div>
<div class="col-lg-4">
{{ form.term_type }}
</div>
</div> </div>
</div> <div class="col-lg-4">
{{ form.term_type }}
</div>
</div>
</div>
<div class="textAreaBlock2 text-nn box-sizing disTab"> <div class="textAreaBlock2 text-nn box-sizing disTab">
</div> </div>
<div class="polsF1 polsF2 disTab"> <div class="polsF1 polsF2 disTab">
<p>Вид строительства</p> <p>Вид строительства</p>
{{ form.construction_type}} {{ form.construction_type }}
</div> </div>
<div class="polsF1 polsF2 disTab"> <div class="polsF1 polsF2 disTab">
<p>Классификация здания</p> <p>Классификация здания</p>
{{ form.building_classification}} {{ form.building_classification }}
</div> </div>
<div class="textAreaBlock2 text-nn box-sizing disTab -live-image-upload-container"> <div class="textAreaBlock2 text-nn box-sizing disTab -live-image-upload-container">
<p>Фотографии</p> <p>Фотографии</p>
{% for photo in form.photos.field.queryset.all %} {% for photo in form.photos.field.queryset.all %}
<div class="col-lg-3 -image-widget"> <div class="col-lg-3 -image-widget">
<div class="-position-relative-parent" style="display: inline-block"> <div class="-position-relative-parent" style="display: inline-block">
<a href="#" onclick="return false" class="btn close -image-delete">&times;</a> <a href="#" onclick="return false" class="btn close -image-delete">&times;</a>
{% thumbnail photo.img "200x200" crop="center" as img %} {% thumbnail photo.img "200x200" crop="center" as img %}
<img src="{{ img.url }}"> <img src="{{ img.url }}">
{% endthumbnail %} {% endthumbnail %}
</div> </div>
<input type="checkbox" name="{{ form.photos.html_name }}" value="{{ photo.pk }}" checked style='display: none'> <input type="checkbox" name="{{ form.photos.html_name }}" value="{{ photo.pk }}" checked
</div> style='display: none'>
{% endfor %}
<script type="text/x-template" class="-templ">
<% images.forEach(function(image) { %>
<div class="col-lg-3">
<div class="-position-relative-parent" style="display: inline-block">
<a href="#" onclick="return false" data-image-id="<%- image.id %>" class="btn close -live-image-delete">&times;</a>
<img src="<%- image.smallThumbnailUrl %>">
</div>
<input type="checkbox" name="{{ form.live_images.html_name }}" value="<%- image.id %>" checked style='display: none'>
</div>
<% }) %>
</script>
<div class="-res"></div>
<div class="col-xs-12">
<input type="file" name="image" multiple class="-live-image-upload-field" style="display: none">
<a href="#" onclick="$(this).closest('.-live-image-upload-container').find('.-live-image-upload-field').first().click(); return false" class="btn btn-default add_file_to_port">
Выберите файлы
</a>
</div> </div>
</div> {% endfor %}
<script type="text/x-template" class="-templ">
<% images.forEach(function(image) { %>
<div class="col-lg-3">
<div class="-position-relative-parent" style="display: inline-block">
<a href="#" onclick="return false" data-image-id="<%- image.id %>"
class="btn close -live-image-delete">&times;</a>
<img src="<%- image.smallThumbnailUrl %>">
</div>
<input type="checkbox" name="{{ form.live_images.html_name }}" value="<%- image.id %>" checked
style='display: none'>
</div>
<% }) %>
</script>
<div class="-res"></div>
<div class="col-xs-12">
<input type="file" name="image" multiple class="-live-image-upload-field" style="display: none">
<a href="#"
onclick="$(this).closest('.-live-image-upload-container').find('.-live-image-upload-field').first().click(); return false"
class="btn btn-default add_file_to_port">
Выберите файлы
</a>
</div>
</div>
<div class="textAreaBlock2 text-nn box-sizing disTab"> <div class="textAreaBlock2 text-nn box-sizing disTab">
</div> </div>
<div class="searchF1 polsF1 polsFF links-filter"> <div class="searchF1 polsF1 polsFF links-filter">
<input type="submit" value="Сохранить" class="btn-submit-link add_file_to_port"> <input type="submit" value="Сохранить" class="btn-submit-link add_file_to_port">
<a href="{% url 'users:contractor-profile' request.user.pk %}" class="btn-submit-link add_file_to_port">Отмена</a> <a href="{% url 'users:contractor-profile' request.user.pk %}"
class="btn-submit-link add_file_to_port">Отмена</a>
</div>
</form>
{% include 'partials/footer.html' %}
</div> </div>
</form>
{% include 'partials/footer.html' %}
</div> </div>
</div>
{% endblock %} {% endblock %}

@ -1,346 +1,410 @@
{% extends 'partials/base.html' %} {% extends 'partials/base.html' %}
{% load i18n %}
{% block head_css %} {% block head_css %}
<style> <style>
.-error, .errorlist {color: red} .-error, .errorlist {
</style> color: red
}
</style>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
{% include 'partials/modals/project_work_type_suggestion.html' %} {% include 'partials/modals/project_work_type_suggestion.html' %}
{% include 'partials/header.html' %} {% include 'partials/header.html' %}
<div class="container mainScore">
<div class="row">
<div class="col-lg-12 allProjects">
<p class="titleScore">Новый заказ</p>
</div>
<form action="{% url 'projects:customer-project-create' %}" method="POST" enctype="multipart/form-data" novalidate
class="-spec-work-type-combo-container">
{% csrf_token %}
<input type="hidden" id="extraFields" name="extra_fields" value="">
<div class="chatBlock new-rass new-rass2 disTab">
<div class="col-lg-9">
<p class="new-pp new-pp3">Формирование заказа</p>
{% if form.non_field_errors %}
<div class="new-pp3" style="color: red; margin-top: 70px">{{ form.non_field_errors }}</div>
{% endif %}
<div class="textAreaBlock2 text-nn box-sizing disTab">
<p class="titleResF1">Название заказа <span data-tooltip data-placement="{% tooltip_placement pk=4 %}"
title="{% tooltip pk=4 %}"
class="-green-glyphicon glyphicon glyphicon-question-sign"></span>
<span id="{% random_ident %}" class="-validation-error"
style="color: red">{{ form.name.errors.as_text }}</span></p>
<input type="text" class="box-sizing" name="{{ form.name.html_name }}" value="{{ form.name.value }}">
</div>
<div class="container mainScore"> <div class="textAreaBlock2 text-nn box-sizing disTab">
<div class="row"> <p class="titleResF1">Подробно опишите задание <span data-tooltip
<div class="col-lg-12 allProjects"> data-placement="{% tooltip_placement pk=5 %}"
<p class="titleScore">Новый заказ</p> title="{% tooltip pk=5 %}"
class="-green-glyphicon glyphicon glyphicon-question-sign"></span>
<span id="{% random_ident %}" class="-validation-error"
style="color: red">{{ form.text.errors.as_text }}</span></p>
<textarea name="{{ form.text.html_name }}" id="text-new"
style="margin-top:0;">{{ form.text.value }}</textarea>
</div>
</div>
<div class="col-lg-3 wrChat1">
<div class="messageBlock box-sizing disTab">
<p>Дополнительно</p>
</div>
<div id="fileUploadContainer" class="col-lg-12 documentsChat">
<div class="upload">
<p id="fileUploadAddBtn" style="margin: 0">+ добавить файл (до 100 файлов)</p>
</div>
<ul class="list-new-new">
<li class="file-upload-widget" style="display: none">
<input type="file" name="new_files" class="file-upload-input"
style="position: absolute; top: -1000px; left: -1000px">
<p class="file-upload-label"></p>
<div class="file-upload-remove-btn"></div>
</li>
</ul>
</div> </div>
<form action="{% url 'projects:customer-project-create' %}" method="POST" enctype="multipart/form-data" novalidate class="-spec-work-type-combo-container"> <p class="type-work">{% trans 'project_stage0' %} <span data-tooltip
{% csrf_token %} data-placement="{% tooltip_placement pk=6 %}"
title="{% tooltip pk=6 %}"
<input type="hidden" id="extraFields" name="extra_fields" value=""> class="-green-glyphicon glyphicon glyphicon-question-sign"></span>
<span id="{% random_ident %}" class="-validation-error"
<div class="chatBlock new-rass new-rass2 disTab"> style="color: red">{{ form.work_type.errors.as_text }}</span></p>
<div class="col-lg-9"> <div class="mail-block type-work-inset -project-work-type-radios-container">
<p class="new-pp new-pp3">Формирование заказа</p> {% for id, text in form.work_type.field.choices %}
<div class="inset-mb">
{% if form.non_field_errors %} <label>
<div class="new-pp3" style="color: red; margin-top: 70px">{{ form.non_field_errors }}</div> <input
{% endif %} type="radio"
value="{{ id }}"
<div class="textAreaBlock2 text-nn box-sizing disTab"> {% if form.work_type.value|int == id %}checked{% endif %}
<p class="titleResF1">Название заказа <span data-tooltip data-placement="{% tooltip_placement pk=4 %}" title="{% tooltip pk=4 %}" class="-green-glyphicon glyphicon glyphicon-question-sign"></span> <span id="{% random_ident %}" class="-validation-error" style="color: red">{{ form.name.errors.as_text }}</span></p> name="{{ form.work_type.html_name }}">
<input type="text" class="box-sizing" name="{{ form.name.html_name }}" value="{{ form.name.value }}">
</div> <span></span>
</label>
<div class="textAreaBlock2 text-nn box-sizing disTab">
<p class="titleResF1">Подробно опишите задание <span data-tooltip data-placement="{% tooltip_placement pk=5 %}" title="{% tooltip pk=5 %}" class="-green-glyphicon glyphicon glyphicon-question-sign"></span> <span id="{% random_ident %}" class="-validation-error" style="color: red">{{ form.text.errors.as_text }}</span></p> <p>{{ text }}</p>
<textarea name="{{ form.text.html_name }}" id="text-new" style="margin-top:0;">{{ form.text.value }}</textarea>
</div>
</div>
<div class="col-lg-3 wrChat1">
<div class="messageBlock box-sizing disTab">
<p>Дополнительно</p>
</div>
<div id="fileUploadContainer" class="col-lg-12 documentsChat">
<div class="upload">
<p id="fileUploadAddBtn" style="margin: 0">+ добавить файл (до 100 файлов)</p>
</div>
<ul class="list-new-new">
<li class="file-upload-widget" style="display: none">
<input type="file" name="new_files" class="file-upload-input" style="position: absolute; top: -1000px; left: -1000px">
<p class="file-upload-label"></p>
<div class="file-upload-remove-btn"></div>
</li>
</ul>
</div>
<p class="type-work">Тип работы <span data-tooltip data-placement="{% tooltip_placement pk=6 %}" title="{% tooltip pk=6 %}" class="-green-glyphicon glyphicon glyphicon-question-sign"></span> <span id="{% random_ident %}" class="-validation-error" style="color: red">{{ form.work_type.errors.as_text }}</span></p>
<div class="mail-block type-work-inset -project-work-type-radios-container">
{% for id, text in form.work_type.field.choices %}
<div class="inset-mb">
<label>
<input
type="radio"
value="{{ id }}"
{% if form.work_type.value|int == id %}checked{% endif %}
name="{{ form.work_type.html_name }}">
<span></span>
</label>
<p>{{ text }}</p>
</div>
{% endfor %}
</div>
<div class="textAreaBlock2 box-sizing disTab">
<a href="#" onclick="return false" data-toggle="modal" data-target="#projectWorkTypeSuggestionModal" class="new-link new-lw">+ Добавить раздел</a>
</div>
</div>
</div> </div>
<div class="col-lg-12 new-filter"> {% endfor %}
<div class="filter clearfix"> </div>
<div class="polsF1 disTab"> <div class="textAreaBlock2 box-sizing disTab">
<div class="col-lg-3 -single-spec-select"> <a href="#" onclick="return false" data-toggle="modal" data-target="#projectWorkTypeSuggestionModal"
<div class="-bold">Стадия проекта <span data-tooltip data-placement="{% tooltip_placement pk=7 %}" title="{% tooltip pk=7 %}" class="-green-glyphicon glyphicon glyphicon-question-sign"></span> <span id="{% random_ident %}" class="-validation-error" style="color: red">{{ form.specialization.errors.as_text }}</span></div> class="new-link new-lw">+ Добавить раздел</a>
<input type="hidden" class="-spec-select -spec-select-level-1" style="width: 100%"> </div>
</div> </div>
</div>
<div class="col-lg-3 -single-spec-select"> <div class="col-lg-12 new-filter">
<div class="-bold"><span class="-dynamic-label">Стадия проекта</span></div> <div class="filter clearfix">
<input type="hidden" class="-spec-select -spec-select-level-2" style="width: 100%"> <div class="polsF1 disTab">
</div> <div class="col-lg-3 -single-spec-select">
<div class="-bold">{% trans 'project_stage1' %} <span data-tooltip
<div class="col-lg-3 -single-spec-select"> data-placement="{% tooltip_placement pk=7 %}"
<div class="-bold">Раздел</div> title="{% tooltip pk=7 %}"
<input type="hidden" class="-spec-select -spec-select-level-3" style="width: 100%"> class="-green-glyphicon glyphicon glyphicon-question-sign"></span>
</div> <span id="{% random_ident %}" class="-validation-error"
style="color: red">{{ form.specialization.errors.as_text }}</span></div>
<div class="col-lg-3 -single-spec-select"> <input type="hidden" class="-spec-select -spec-select-level-1" style="width: 100%">
<div class="-bold">Подраздел</div> </div>
<input type="hidden" class="-spec-select -spec-select-level-4" style="width: 100%">
</div> <div class="col-lg-3 -single-spec-select">
<div class="-bold"><span class="-dynamic-label">{% trans 'project_stage2' %}</span></div>
<input type="hidden" name="{{ form.specialization.html_name }}" value="{{ form.specialization.value }}" class="-chosen-spec-id"> <input type="hidden" class="-spec-select -spec-select-level-2" style="width: 100%">
</div> </div>
<div class="titleF1 titleF2 disTab">
<div class="col-lg-12">Бюджет <span data-tooltip data-placement="{% tooltip_placement pk=8 %}" title="{% tooltip pk=8 %}" class="-green-glyphicon glyphicon glyphicon-question-sign"></span> <span id="{% random_ident %}" class="-validation-error" style="color: red">{{ form.budget.errors.as_text }}</span></div> <div class="col-lg-3 -single-spec-select">
<!--<div class="col-lg-8"></div>--> <div class="-bold">{% trans 'project_stage3' %}</div>
</div> <input type="hidden" class="-spec-select -spec-select-level-3" style="width: 100%">
<div class="searchF1 polsF1 polsFF"> </div>
<div class="col-lg-4">
<input type="text" class="box-sizing surr" name="{{ form.budget.html_name }}" value="{{ form.budget.value }}"> <div class="col-lg-3 -single-spec-select">
{{ form.currency }} <div class="-bold">{% trans 'project_stage4' %}</div>
</div> <input type="hidden" class="-spec-select -spec-select-level-4" style="width: 100%">
<div class="col-lg-3"> </div>
{{ form.term_type }}
</div> <input type="hidden" name="{{ form.specialization.html_name }}" value="{{ form.specialization.value }}"
<div class="col-lg-5 dog-new"> class="-chosen-spec-id">
<label> </div>
<input <div class="titleF1 titleF2 disTab">
type="checkbox" <div class="col-lg-12">Бюджет <span data-tooltip data-placement="{% tooltip_placement pk=8 %}"
{% if form.budget_by_agreement.value %}checked{% endif %} title="{% tooltip pk=8 %}"
name="{{ form.budget_by_agreement.html_name }}"> class="-green-glyphicon glyphicon glyphicon-question-sign"></span>
<span id="{% random_ident %}" class="-validation-error"
<span></span> style="color: red">{{ form.budget.errors.as_text }}</span></div>
</label> <!--<div class="col-lg-8"></div>-->
</div>
<p>или по договоренности <span data-tooltip data-placement="{% tooltip_placement pk=9 %}" title="{% tooltip pk=9 %}" class="-green-glyphicon glyphicon glyphicon-question-sign"></span></p> <div class="searchF1 polsF1 polsFF">
</div> <div class="col-lg-4">
</div> <input type="text" class="box-sizing surr" name="{{ form.budget.html_name }}"
<div class="searchF1 polsF1 polsFF make-new"> value="{{ form.budget.value }}">
<label> {{ form.currency }}
<input </div>
type="checkbox" <div class="col-lg-3">
{% if form.price_and_term_required.value %}checked{% endif %} {{ form.term_type }}
name="{{ form.price_and_term_required.html_name }}"> </div>
<div class="col-lg-5 dog-new">
<span></span> <label>
</label> <input
type="checkbox"
<p>Сделать для исполнителей обязательным для заполнения поля цена и срок</p> {% if form.budget_by_agreement.value %}checked{% endif %}
</div> name="{{ form.budget_by_agreement.html_name }}">
<div class="titleF1 titleF2 disTab">
<div class="col-lg-12">Способ оплаты <span id="{% random_ident %}" class="-validation-error" style="color: red">{{ form.deal_type.errors.as_text }}</span></div> <span></span>
</div> </label>
<div class="searchF1 polsF1 polsFF radio-afer">
<div class="col-lg-6"> <p>или по договоренности <span data-tooltip data-placement="{% tooltip_placement pk=9 %}"
<label> title="{% tooltip pk=9 %}"
<input class="-green-glyphicon glyphicon glyphicon-question-sign"></span></p>
type="radio" </div>
name="{{ form.deal_type.html_name }}" </div>
{% if form.deal_type.value == 'secure_deal' %}checked{% endif %} <div class="searchF1 polsF1 polsFF make-new">
value="secure_deal"> <label>
<input
<span></span> type="checkbox"
</label> {% if form.price_and_term_required.value %}checked{% endif %}
name="{{ form.price_and_term_required.html_name }}">
<p class="text-afer">
Безопасная сделка (с резервированием бюджета) <span></span>
</p> </label>
<p class="des-afer"> <p>Сделать для исполнителей обязательным для заполнения поля цена и срок</p>
{% tooltip pk=10 as tooltip10 %}{{ tooltip10|linebreaksbr }} </div>
</p> <div class="titleF1 titleF2 disTab">
</div> <div class="col-lg-12">Способ оплаты <span id="{% random_ident %}" class="-validation-error"
style="color: red">{{ form.deal_type.errors.as_text }}</span>
<div class="col-lg-6"> </div>
<label> </div>
<input <div class="searchF1 polsF1 polsFF radio-afer">
type="radio" <div class="col-lg-6">
name="{{ form.deal_type.html_name }}" <label>
{% if form.deal_type.value == 'direct_payment' %}checked{% endif %} <input
value="direct_payment"> type="radio"
name="{{ form.deal_type.html_name }}"
<span></span> {% if form.deal_type.value == 'secure_deal' %}checked{% endif %}
</label> value="secure_deal">
<p class="text-afer"> <span></span>
Прямая оплата Исполнителю на его кошелек/счет </label>
</p>
<p class="text-afer">
<p class="des-afer"> Безопасная сделка (с резервированием бюджета)
{% tooltip pk=11 as tooltip11 %}{{ tooltip11|linebreaksbr }} </p>
</p>
</div> <p class="des-afer">
</div> {% tooltip pk=10 as tooltip10 %}{{ tooltip10|linebreaksbr }}
</p>
</div>
<div class="col-lg-6">
<label>
<input
<div class="resSearchF1"> type="radio"
<div class="col-lg-3"> name="{{ form.deal_type.html_name }}"
<p class="titleResF1">Расширенный поиск</p> {% if form.deal_type.value == 'direct_payment' %}checked{% endif %}
<button data-tooltip data-placement="{% tooltip_placement pk=12 %}" title="{% tooltip pk=12 %}" class="resButtonF1"> value="direct_payment">
<span class="glyphicon glyphicon-arrow-up" aria-hidden="true"></span>
</button> <span></span>
</div> </label>
<div class="col-lg-9">
<div class="borderS1"></div> <p class="text-afer">
</div> Прямая оплата Исполнителю на его кошелек/счет
</div> </p>
<div class="slideRes disTab activeSlide"> <p class="des-afer">
<div class="titleF1 disTab"> {% tooltip pk=11 as tooltip11 %}{{ tooltip11|linebreaksbr }}
<div class="col-lg-3">Выбор объекта <span data-tooltip data-placement="{% tooltip_placement pk=13 %}" title="{% tooltip pk=13 %}" class="-green-glyphicon glyphicon glyphicon-question-sign"></span><br><span id="{% random_ident %}" class="-validation-error" style="color: red">{{ form.realty.errors.as_text }}</span></div> </p>
<div class="col-lg-3">Наименование <span data-tooltip data-placement="{% tooltip_placement pk=14 %}" title="{% tooltip pk=14 %}" class="-green-glyphicon glyphicon glyphicon-question-sign"></span><br><span id="{% random_ident %}" class="-validation-error" style="color: red">{{ realty_form.name.errors.as_text }}</span></div> </div>
<div class="col-lg-3">Классификация здания <span data-tooltip data-placement="{% tooltip_placement pk=15 %}" title="{% tooltip pk=15 %}" class="-green-glyphicon glyphicon glyphicon-question-sign"></span><br><span id="{% random_ident %}" class="-validation-error" style="color: red">{{ realty_form.building_classification.errors.as_text }}</span></div> </div>
<div class="col-lg-3">Вид строительства <span data-tooltip data-placement="{% tooltip_placement pk=16 %}" title="{% tooltip pk=16 %}" class="-green-glyphicon glyphicon glyphicon-question-sign"></span><br><span id="{% random_ident %}" class="-validation-error" style="color: red">{{ realty_form.construction_type.errors.as_text }}</span></div>
</div>
<div class="resSearchF1">
<div class="polsF1 polsF2 disTab"> <div class="col-lg-3">
<div class="col-lg-3"> <p class="titleResF1">Расширенный поиск</p>
<select <button data-tooltip data-placement="{% tooltip_placement pk=12 %}" title="{% tooltip pk=12 %}"
class="selectpicker" class="resButtonF1">
id="realtyId" <span class="glyphicon glyphicon-arrow-up" aria-hidden="true"></span>
name="{{ form.realty.html_name }}"> </button>
<option value="" {% if not form.realty.value %}selected="selected"{% endif %}>Создать новый</option> </div>
<div class="col-lg-9">
{% for r in form.realty.field.queryset %} <div class="borderS1"></div>
<option value="{{ r.pk }}" {% if form.realty.value|int == r.pk %}selected="selected"{% endif %}>{{ r.name }}</option> </div>
{% endfor %} </div>
</select>
</div> <div class="slideRes disTab activeSlide">
<div class="col-lg-3"> <div class="titleF1 disTab">
<input <div class="col-lg-3">Выбор объекта <span data-tooltip data-placement="{% tooltip_placement pk=13 %}"
type="text" title="{% tooltip pk=13 %}"
id="realtyName" class="-green-glyphicon glyphicon glyphicon-question-sign"></span><br><span
name="{{ realty_form.name.html_name }}" id="{% random_ident %}" class="-validation-error"
class="box-sizing surr surr2" style="color: red">{{ form.realty.errors.as_text }}</span></div>
value="{{ realty_form.name.value }}"> <div class="col-lg-3">Наименование <span data-tooltip data-placement="{% tooltip_placement pk=14 %}"
</div> title="{% tooltip pk=14 %}"
<div class="col-lg-3"> class="-green-glyphicon glyphicon glyphicon-question-sign"></span><br><span
{{ realty_form.building_classification }} id="{% random_ident %}" class="-validation-error"
{# <select#} style="color: red">{{ realty_form.name.errors.as_text }}</span></div>
{# id="realtyBuildingClassificationId"#} <div class="col-lg-3">Классификация здания <span data-tooltip
{# #} data-placement="{% tooltip_placement pk=15 %}"
{# name="{{ realty_form.building_classification.html_name }}">#} title="{% tooltip pk=15 %}"
{# {% for c in realty_form.building_classification.field.queryset %}#} class="-green-glyphicon glyphicon glyphicon-question-sign"></span><br><span
{# <option value="{{ c.pk }}" {% if realty_form.building_classification.value|int == c.pk %}selected="selected"{% endif %}>{{ c.name }}</option>#} id="{% random_ident %}" class="-validation-error"
{# {% endfor %}#} style="color: red">{{ realty_form.building_classification.errors.as_text }}</span></div>
{# </select>#} <div class="col-lg-3">Вид строительства <span data-tooltip
</div> data-placement="{% tooltip_placement pk=16 %}"
<div class="col-lg-3"> title="{% tooltip pk=16 %}"
<select class="-green-glyphicon glyphicon glyphicon-question-sign"></span><br><span
id="realtyConstructionTypeId" id="{% random_ident %}" class="-validation-error"
class="selectpicker" style="color: red">{{ realty_form.construction_type.errors.as_text }}</span></div>
name="{{ realty_form.construction_type.html_name }}"> </div>
{% for t in realty_form.construction_type.field.queryset %}
<option value="{{ t.pk }}" {% if realty_form.construction_type.value|int == t.pk %}selected="selected"{% endif %}>{{ t.name }}</option> <div class="polsF1 polsF2 disTab">
{% endfor %} <div class="col-lg-3">
</select> <select
</div> class="selectpicker"
</div> id="realtyId"
<div class="titleF1 disTab"> name="{{ form.realty.html_name }}">
<div class="col-lg-12">Местоположение <span data-tooltip data-placement="{% tooltip_placement pk=18 %}" title="{% tooltip pk=18 %}" class="-green-glyphicon glyphicon glyphicon-question-sign"></span> <span id="{% random_ident %}" class="-validation-error" style="color: red">{{ realty_form.location.errors.as_text }}</span></div> <option value="" {% if not form.realty.value %}selected="selected"{% endif %}>Создать новый</option>
</div>
<div class="polsF1 polsF2 disTab"> {% for r in form.realty.field.queryset %}
<div> <option value="{{ r.pk }}"
<div class="col-lg-3"> {% if form.realty.value|int == r.pk %}selected="selected"{% endif %}>{{ r.name }}</option>
<input type="hidden" class="-location-select -location-select-country" style="width: 100%"> {% endfor %}
</div> </select>
</div>
<div class="col-lg-3"> <div class="col-lg-3">
<input type="hidden" class="-location-select -location-select-region" style="width: 100%"> <input
</div> type="text"
id="realtyName"
<div class="col-lg-3"> name="{{ realty_form.name.html_name }}"
<input type="hidden" class="-location-select -location-select-city" style="width: 100%"> class="box-sizing surr surr2"
</div> value="{{ realty_form.name.value }}">
</div> </div>
<div class="col-lg-3">
<input type="hidden" id="chosenLocationId" name="{{ realty_form.location.html_name }}" value="{{ realty_form.location.value }}"> {{ realty_form.building_classification }}
{# <select#}
<div class="col-lg-3 make-new"> {# id="realtyBuildingClassificationId"#}
<label>{{ form.cro }}<span></span></label> {# #}
<p>Требуется допуск (СРО) <span data-tooltip data-placement="{% tooltip_placement pk=17 %}" title="{% tooltip pk=17 %}" class="-green-glyphicon glyphicon glyphicon-question-sign"></span></p> {# name="{{ realty_form.building_classification.html_name }}">#}
</div> {# {% for c in realty_form.building_classification.field.queryset %}#}
</div> {# <option value="{{ c.pk }}" {% if realty_form.building_classification.value|int == c.pk %}selected="selected"{% endif %}>{{ c.name }}</option>#}
</div> {# {% endfor %}#}
{# </select>#}
</div>
<div class="searchF1 polsF1 polsFF links-filter"> <div class="col-lg-3">
<input class="btn-submit-link" type="submit" value="Разместить проект"> <select
</div> id="realtyConstructionTypeId"
</div> class="selectpicker"
name="{{ realty_form.construction_type.html_name }}">
{% for t in realty_form.construction_type.field.queryset %}
<option value="{{ t.pk }}"
{% if realty_form.construction_type.value|int == t.pk %}selected="selected"{% endif %}>{{ t.name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="titleF1 disTab">
<div class="col-lg-12">Местоположение <span data-tooltip data-placement="{% tooltip_placement pk=18 %}"
title="{% tooltip pk=18 %}"
class="-green-glyphicon glyphicon glyphicon-question-sign"></span>
<span id="{% random_ident %}" class="-validation-error"
style="color: red">{{ realty_form.location.errors.as_text }}</span></div>
</div>
<div class="polsF1 polsF2 disTab">
<div>
<div class="col-lg-3">
<input type="hidden" class="-location-select -location-select-country" style="width: 100%">
</div>
<div class="col-lg-3">
<input type="hidden" class="-location-select -location-select-region" style="width: 100%">
</div>
<div class="col-lg-3">
<input type="hidden" class="-location-select -location-select-city" style="width: 100%">
</div>
</div> </div>
</form>
{% include 'partials/footer.html' %} <input type="hidden" id="chosenLocationId" name="{{ realty_form.location.html_name }}"
value="{{ realty_form.location.value }}">
<div class="col-lg-3 make-new">
<label>{{ form.cro }}<span></span></label>
<p>Требуется допуск (СРО) <span data-tooltip data-placement="{% tooltip_placement pk=17 %}"
title="{% tooltip pk=17 %}"
class="-green-glyphicon glyphicon glyphicon-question-sign"></span></p>
</div>
</div>
</div>
<div class="searchF1 polsF1 polsFF links-filter">
<input class="btn-submit-link" type="submit" value="Разместить проект">
</div>
</div>
</div> </div>
</form>
{% include 'partials/footer.html' %}
</div> </div>
</div>
{% endblock %} {% endblock %}
{% block js_block %} {% block js_block %}
<script> <script>
// Project work type suggestion modal --------------------------------- // Project work type suggestion modal ---------------------------------
;(function() { ;
var $modal = $('#projectWorkTypeSuggestionModal') (function () {
var $form = $modal.find('.-project-work-type-suggestion-form').first() var $modal = $('#projectWorkTypeSuggestionModal')
var workTypeSuggestionUrl = '/projects/suggest-work-type/' var $form = $modal.find('.-project-work-type-suggestion-form').first()
var workTypeSuggestionUrl = '/projects/suggest-work-type/'
$modal.find('.-action-button').first().on('click', function($evt) {
$.post(workTypeSuggestionUrl, $form.serialize()) $modal.find('.-action-button').first().on('click', function ($evt) {
.then(function(res) { $.post(workTypeSuggestionUrl, $form.serialize())
if (res.status === 'success') { .then(function (res) {
$form.trigger('reset') if (res.status === 'success') {
$('.-error').text('') $form.trigger('reset')
$modal.modal('hide') $('.-error').text('')
$.jGrowl('Предложение успешно отправлено') $modal.modal('hide')
} else if (res.status === 'error') { $.jGrowl('Предложение успешно отправлено')
_.flow( } else if (res.status === 'error') {
_.toPairs, _.flow(
_.toPairs,
_.each(function(pair) {
var cssSelector = pair[0] _.each(function (pair) {
var errors = pair[1] var cssSelector = pair[0]
var errors = pair[1]
$(cssSelector).first().text(_.join(' ', errors))
}) $(cssSelector).first().text(_.join(' ', errors))
)(res.form_errors)
}
}) })
)(res.form_errors)
}
}) })
}()) })
}())
// Scroll to first form validation error --------------------------- // Scroll to first form validation error ---------------------------
;(function() { ;
var hash = $('.-validation-error').filter(function(i, el) {return $(el).text()}).first().attr('id') (function () {
var hash = $('.-validation-error').filter(function (i, el) {
return $(el).text()
}).first().attr('id')
if (hash) if (hash)
window.location.hash = hash window.location.hash = hash
}()) }())
</script> </script>
{% endblock %} {% endblock %}

@ -1,362 +1,397 @@
{% extends 'partials/base.html' %} {% extends 'partials/base.html' %}
{% load i18n %}
{% block head_css %} {% block head_css %}
<style> <style>
.-error, .errorlist {color: red} .-error, .errorlist {
</style> color: red
}
</style>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
{% include 'partials/modals/project_work_type_suggestion.html' %} {% include 'partials/modals/project_work_type_suggestion.html' %}
{% include 'partials/header.html' %} {% include 'partials/header.html' %}
<div class="container mainScore">
<div class="row">
<div class="col-lg-12 allProjects">
<p class="titleScore">Изменение проекта</p>
</div>
<form action="{% url 'projects:customer-project-edit' pk=pk %}" method="POST" enctype="multipart/form-data"
novalidate class="-spec-work-type-combo-container">
{% csrf_token %}
<input type="hidden" name="next" value="{% url 'projects:detail' pk=pk %}">
<input type="hidden" id="extraFields" name="extra_fields" value="">
<div class="chatBlock new-rass new-rass2 disTab">
<div class="col-lg-9">
<p class="new-pp new-pp3">Формирование заказа</p>
{% if form.non_field_errors %}
<div class="new-pp3" style="color: red; margin-top: 70px">{{ form.non_field_errors }}</div>
{% endif %}
<div class="textAreaBlock2 text-nn box-sizing disTab">
<p>Название заказа <span id="{% random_ident %}" class="-validation-error"
style="color: red">{{ form.name.errors.as_text }}</span></p>
<input type="text" class="box-sizing" name="{{ form.name.html_name }}" value="{{ form.name.value }}">
</div>
<div class="textAreaBlock2 text-nn box-sizing disTab">
<p>Подробно опишите задание <span id="{% random_ident %}" class="-validation-error"
style="color: red">{{ form.text.errors.as_text }}</span></p>
<textarea name="{{ form.text.html_name }}" id="text-new">{{ form.text.value }}</textarea>
</div>
</div>
<div class="col-lg-3 wrChat1">
<div class="messageBlock box-sizing disTab">
<p>Дополнительно</p>
</div>
<div id="fileUploadContainer" class="col-lg-12 documentsChat">
<div class="upload">
<p id="fileUploadAddBtn" style="margin: 0">+ добавить файл (до 100 файлов)</p>
</div>
<ul class="list-new-new">
{% for file in form.files.field.queryset.all %}
<li class="existing-file-widget">
<input type="checkbox" name="{{ form.files.html_name }}" value="{{ file.pk }}" checked
style='display: none'>
<p class="file-upload-label">{{ file.file.name|basename }} {{ file.file.size|filesizeformat }}</p>
<div class="existing-file-remove-btn"></div>
</li>
{% endfor %}
<li class="file-upload-widget" style="display: none">
<input type="file" name="new_files" class="file-upload-input"
style="position: absolute; top: -1000px; left: -1000px">
<p class="file-upload-label"></p>
<div class="file-upload-remove-btn"></div>
</li>
</ul>
</div>
<p class="type-work">{% trans 'project_stage0' %} <span id="{% random_ident %}" class="-validation-error"
style="color: red">{{ form.work_type.errors.as_text }}</span>
</p>
<div class="mail-block type-work-inset -project-work-type-radios-container">
{% for id, text in form.work_type.field.choices %}
<div class="inset-mb">
<label>
<input
type="radio"
value="{{ id }}"
{% if form.work_type.value|int == id %}checked{% endif %}
name="{{ form.work_type.html_name }}">
<span></span>
</label>
<p>{{ text }}</p>
</div>
{% endfor %}
</div>
<div class="textAreaBlock2 box-sizing disTab">
<a href="#" onclick="return false" data-toggle="modal" data-target="#projectWorkTypeSuggestionModal"
class="new-link new-lw">+ Добавить раздел</a>
</div>
</div>
</div>
<div class="col-lg-12 new-filter">
<div class="filter clearfix">
<div class="polsF1 disTab">
<div class="col-lg-3 -single-spec-select">
<div class="-bold">{% trans 'project_stage1' %} <span data-tooltip
data-placement="{% tooltip_placement pk=7 %}"
title="{% tooltip pk=7 %}"
class="-green-glyphicon glyphicon glyphicon-question-sign"></span>
<span id="{% random_ident %}" class="-validation-error"
style="color: red">{{ form.specialization.errors.as_text }}</span></div>
<input type="hidden" class="-spec-select -spec-select-level-1" style="width: 100%">
</div>
<div class="col-lg-3 -single-spec-select">
<div class="-bold"><span class="-dynamic-label">{% trans 'project_stage2' %}</span></div>
<input type="hidden" class="-spec-select -spec-select-level-2" style="width: 100%">
</div>
<div class="col-lg-3 -single-spec-select">
<div class="-bold">{% trans 'project_stage3' %}</div>
<input type="hidden" class="-spec-select -spec-select-level-3" style="width: 100%">
</div>
<div class="col-lg-3 -single-spec-select">
<div class="-bold">{% trans 'project_stage4' %}</div>
<input type="hidden" class="-spec-select -spec-select-level-4" style="width: 100%">
</div>
<input type="hidden" name="{{ form.specialization.html_name }}" value="{{ form.specialization.value }}"
class="-chosen-spec-id">
</div>
<div class="titleF1 titleF2 disTab">
<div class="col-lg-12">Бюджет <span id="{% random_ident %}" class="-validation-error"
style="color: red">{{ form.budget.errors.as_text }}</span></div>
<!--<div class="col-lg-8"></div>-->
</div>
<div class="searchF1 polsF1 polsFF">
<div class="col-lg-4">
<input type="text" class="box-sizing surr" name="{{ form.budget.html_name }}"
value="{{ form.budget.value }}">
{{ form.currency }}
</div>
<div class="col-lg-3">
{{ form.term_type }}
</div>
<div class="col-lg-5 dog-new">
<label>
<input
type="checkbox"
{% if form.budget_by_agreement.value %}checked{% endif %}
name="{{ form.budget_by_agreement.html_name }}">
<span></span>
</label>
<p>или по договоренности</p>
</div>
</div>
<div class="searchF1 polsF1 polsFF make-new">
<label>
<input
type="checkbox"
{% if form.price_and_term_required.value %}checked{% endif %}
name="{{ form.price_and_term_required.html_name }}">
<span></span>
</label>
<div class="container mainScore"> <p>Сделать для исполнителей обязательным для заполнения поля цена и срок</p>
<div class="row">
<div class="col-lg-12 allProjects">
<p class="titleScore">Изменение проекта</p>
</div> </div>
<div class="titleF1 titleF2 disTab">
<div class="col-lg-12">Способ оплаты <span id="{% random_ident %}" class="-validation-error"
style="color: red">{{ form.deal_type.errors.as_text }}</span>
</div>
</div>
<div class="searchF1 polsF1 polsFF radio-afer">
<div class="col-lg-6">
<label>
<input
type="radio"
name="{{ form.deal_type.html_name }}"
{% if form.deal_type.value == 'secure_deal' %}checked{% endif %}
value="secure_deal">
<span></span>
</label>
<p class="text-afer">
Безопасная сделка (с резервированием бюджета)
</p>
<p class="des-afer">
{% tooltip pk=10 as tooltip10 %}{{ tooltip10|linebreaksbr }}
</p>
</div>
<div class="col-lg-6">
<label>
<input
type="radio"
name="{{ form.deal_type.html_name }}"
{% if form.deal_type.value == 'direct_payment' %}checked{% endif %}
value="direct_payment">
<span></span>
</label>
<p class="text-afer">
Прямая оплата Исполнителю на его кошелек/счет
</p>
<p class="des-afer">
{% tooltip pk=11 as tooltip11 %}{{ tooltip11|linebreaksbr }}
</p>
</div>
</div>
<form action="{% url 'projects:customer-project-edit' pk=pk %}" method="POST" enctype="multipart/form-data" novalidate class="-spec-work-type-combo-container"> <div class="resSearchF1">
{% csrf_token %} <div class="col-lg-3">
<p class="titleResF1">Расширенный поиск</p>
<input type="hidden" name="next" value="{% url 'projects:detail' pk=pk %}"> <button class="resButtonF1">
<input type="hidden" id="extraFields" name="extra_fields" value=""> <span class="glyphicon glyphicon-arrow-up" aria-hidden="true"></span>
</button>
<div class="chatBlock new-rass new-rass2 disTab"> </div>
<div class="col-lg-9"> <div class="col-lg-9">
<p class="new-pp new-pp3">Формирование заказа</p> <div class="borderS1"></div>
</div>
{% if form.non_field_errors %} </div>
<div class="new-pp3" style="color: red; margin-top: 70px">{{ form.non_field_errors }}</div> <div class="slideRes disTab activeSlide">
{% endif %} <div class="titleF1 disTab">
<div class="col-lg-3">Выбор объекта<br><span id="{% random_ident %}" class="-validation-error"
<div class="textAreaBlock2 text-nn box-sizing disTab"> style="color: red">{{ form.realty.errors.as_text }}</span>
<p>Название заказа <span id="{% random_ident %}" class="-validation-error" style="color: red">{{ form.name.errors.as_text }}</span></p> </div>
<input type="text" class="box-sizing" name="{{ form.name.html_name }}" value="{{ form.name.value }}"> <div class="col-lg-3">Наименование<br><span id="{% random_ident %}" class="-validation-error"
</div> style="color: red">{{ realty_form.name.errors.as_text }}</span>
<div class="textAreaBlock2 text-nn box-sizing disTab">
<p>Подробно опишите задание <span id="{% random_ident %}" class="-validation-error" style="color: red">{{ form.text.errors.as_text }}</span></p>
<textarea name="{{ form.text.html_name }}" id="text-new">{{ form.text.value }}</textarea>
</div>
</div>
<div class="col-lg-3 wrChat1">
<div class="messageBlock box-sizing disTab">
<p>Дополнительно</p>
</div>
<div id="fileUploadContainer" class="col-lg-12 documentsChat">
<div class="upload">
<p id="fileUploadAddBtn" style="margin: 0">+ добавить файл (до 100 файлов)</p>
</div>
<ul class="list-new-new">
{% for file in form.files.field.queryset.all %}
<li class="existing-file-widget">
<input type="checkbox" name="{{ form.files.html_name }}" value="{{ file.pk }}" checked style='display: none'>
<p class="file-upload-label">{{ file.file.name|basename }} {{ file.file.size|filesizeformat }}</p>
<div class="existing-file-remove-btn"></div>
</li>
{% endfor %}
<li class="file-upload-widget" style="display: none">
<input type="file" name="new_files" class="file-upload-input" style="position: absolute; top: -1000px; left: -1000px">
<p class="file-upload-label"></p>
<div class="file-upload-remove-btn"></div>
</li>
</ul>
</div>
<p class="type-work">Тип работы <span id="{% random_ident %}" class="-validation-error" style="color: red">{{ form.work_type.errors.as_text }}</span></p>
<div class="mail-block type-work-inset -project-work-type-radios-container">
{% for id, text in form.work_type.field.choices %}
<div class="inset-mb">
<label>
<input
type="radio"
value="{{ id }}"
{% if form.work_type.value|int == id %}checked{% endif %}
name="{{ form.work_type.html_name }}">
<span></span>
</label>
<p>{{ text }}</p>
</div>
{% endfor %}
</div>
<div class="textAreaBlock2 box-sizing disTab">
<a href="#" onclick="return false" data-toggle="modal" data-target="#projectWorkTypeSuggestionModal" class="new-link new-lw">+ Добавить раздел</a>
</div>
</div>
</div> </div>
<div class="col-lg-12 new-filter"> <div class="col-lg-3">Классификация здания<br><span id="{% random_ident %}" class="-validation-error"
<div class="filter clearfix"> style="color: red">{{ realty_form.building_classification.errors.as_text }}</span>
<div class="polsF1 disTab"> </div>
<div class="col-lg-3 -single-spec-select"> <div class="col-lg-3">Вид строительства<br><span id="{% random_ident %}" class="-validation-error"
<div class="-bold">Стадия проекта <span data-tooltip data-placement="{% tooltip_placement pk=7 %}" title="{% tooltip pk=7 %}" class="-green-glyphicon glyphicon glyphicon-question-sign"></span> <span id="{% random_ident %}" class="-validation-error" style="color: red">{{ form.specialization.errors.as_text }}</span></div> style="color: red">{{ realty_form.construction_type.errors.as_text }}</span>
<input type="hidden" class="-spec-select -spec-select-level-1" style="width: 100%"> </div>
</div> </div>
<div class="col-lg-3 -single-spec-select"> <div class="polsF1 polsF2 disTab">
<div class="-bold"><span class="-dynamic-label">Стадия проекта</span></div> <div class="col-lg-3">
<input type="hidden" class="-spec-select -spec-select-level-2" style="width: 100%"> <select
</div> class="selectpicker"
id="realtyId"
<div class="col-lg-3 -single-spec-select"> name="{{ form.realty.html_name }}">
<div class="-bold">Раздел</div> <option value="" {% if not form.realty.value %}selected="selected"{% endif %}>Создать новый</option>
<input type="hidden" class="-spec-select -spec-select-level-3" style="width: 100%">
</div> {% for r in form.realty.field.queryset %}
<option value="{{ r.pk }}"
<div class="col-lg-3 -single-spec-select"> {% if form.realty.value|int == r.pk %}selected="selected"{% endif %}>{{ r.name }}</option>
<div class="-bold">Подраздел</div> {% endfor %}
<input type="hidden" class="-spec-select -spec-select-level-4" style="width: 100%"> </select>
</div> </div>
<div class="col-lg-3">
<input type="hidden" name="{{ form.specialization.html_name }}" value="{{ form.specialization.value }}" class="-chosen-spec-id"> <input
</div> type="text"
<div class="titleF1 titleF2 disTab"> id="realtyName"
<div class="col-lg-12">Бюджет <span id="{% random_ident %}" class="-validation-error" style="color: red">{{ form.budget.errors.as_text }}</span></div> name="{{ realty_form.name.html_name }}"
<!--<div class="col-lg-8"></div>--> class="box-sizing surr surr2"
</div> value="{{ realty_form.name.value }}">
<div class="searchF1 polsF1 polsFF"> </div>
<div class="col-lg-4"> <div class="col-lg-3">
<input type="text" class="box-sizing surr" name="{{ form.budget.html_name }}" value="{{ form.budget.value }}"> <select
{{ form.currency }} id="realtyBuildingClassificationId"
</div> class="selectpicker"
<div class="col-lg-3"> name="{{ realty_form.building_classification.html_name }}">
{{ form.term_type }} {% for c in realty_form.building_classification.field.queryset %}
</div> <option value="{{ c.pk }}"
<div class="col-lg-5 dog-new"> {% if realty_form.building_classification.value|int == c.pk %}selected="selected"{% endif %}>{{ c.name }}</option>
<label> {% endfor %}
<input </select>
type="checkbox" </div>
{% if form.budget_by_agreement.value %}checked{% endif %} <div class="col-lg-3">
name="{{ form.budget_by_agreement.html_name }}"> <select
id="realtyConstructionTypeId"
<span></span> class="selectpicker"
</label> name="{{ realty_form.construction_type.html_name }}">
{% for t in realty_form.construction_type.field.queryset %}
<p>или по договоренности</p> <option value="{{ t.pk }}"
</div> {% if realty_form.construction_type.value|int == t.pk %}selected="selected"{% endif %}>{{ t.name }}</option>
</div> {% endfor %}
<div class="searchF1 polsF1 polsFF make-new"> </select>
<label> </div>
<input </div>
type="checkbox" <div class="titleF1 disTab">
{% if form.price_and_term_required.value %}checked{% endif %} <div class="col-lg-12">Местоположение <span id="{% random_ident %}" class="-validation-error"
name="{{ form.price_and_term_required.html_name }}"> style="color: red">{{ realty_form.location.errors.as_text }}</span>
</div>
<span></span> </div>
</label> <div class="polsF1 polsF2 disTab">
<div class="col-lg-3">
<p>Сделать для исполнителей обязательным для заполнения поля цена и срок</p> <input type="hidden" class="-location-select -location-select-country" style="width: 100%">
</div>
<div class="titleF1 titleF2 disTab">
<div class="col-lg-12">Способ оплаты <span id="{% random_ident %}" class="-validation-error" style="color: red">{{ form.deal_type.errors.as_text }}</span></div>
</div>
<div class="searchF1 polsF1 polsFF radio-afer">
<div class="col-lg-6">
<label>
<input
type="radio"
name="{{ form.deal_type.html_name }}"
{% if form.deal_type.value == 'secure_deal' %}checked{% endif %}
value="secure_deal">
<span></span>
</label>
<p class="text-afer">
Безопасная сделка (с резервированием бюджета)
</p>
<p class="des-afer">
{% tooltip pk=10 as tooltip10 %}{{ tooltip10|linebreaksbr }}
</p>
</div>
<div class="col-lg-6">
<label>
<input
type="radio"
name="{{ form.deal_type.html_name }}"
{% if form.deal_type.value == 'direct_payment' %}checked{% endif %}
value="direct_payment">
<span></span>
</label>
<p class="text-afer">
Прямая оплата Исполнителю на его кошелек/счет
</p>
<p class="des-afer">
{% tooltip pk=11 as tooltip11 %}{{ tooltip11|linebreaksbr }}
</p>
</div>
</div>
<div class="resSearchF1">
<div class="col-lg-3">
<p class="titleResF1">Расширенный поиск</p>
<button class="resButtonF1">
<span class="glyphicon glyphicon-arrow-up" aria-hidden="true"></span>
</button>
</div>
<div class="col-lg-9">
<div class="borderS1"></div>
</div>
</div>
<div class="slideRes disTab activeSlide">
<div class="titleF1 disTab">
<div class="col-lg-3">Выбор объекта<br><span id="{% random_ident %}" class="-validation-error" style="color: red">{{ form.realty.errors.as_text }}</span></div>
<div class="col-lg-3">Наименование<br><span id="{% random_ident %}" class="-validation-error" style="color: red">{{ realty_form.name.errors.as_text }}</span></div>
<div class="col-lg-3">Классификация здания<br><span id="{% random_ident %}" class="-validation-error" style="color: red">{{ realty_form.building_classification.errors.as_text }}</span></div>
<div class="col-lg-3">Вид строительства<br><span id="{% random_ident %}" class="-validation-error" style="color: red">{{ realty_form.construction_type.errors.as_text }}</span></div>
</div>
<div class="polsF1 polsF2 disTab">
<div class="col-lg-3">
<select
class="selectpicker"
id="realtyId"
name="{{ form.realty.html_name }}">
<option value="" {% if not form.realty.value %}selected="selected"{% endif %}>Создать новый</option>
{% for r in form.realty.field.queryset %}
<option value="{{ r.pk }}" {% if form.realty.value|int == r.pk %}selected="selected"{% endif %}>{{ r.name }}</option>
{% endfor %}
</select>
</div>
<div class="col-lg-3">
<input
type="text"
id="realtyName"
name="{{ realty_form.name.html_name }}"
class="box-sizing surr surr2"
value="{{ realty_form.name.value }}">
</div>
<div class="col-lg-3">
<select
id="realtyBuildingClassificationId"
class="selectpicker"
name="{{ realty_form.building_classification.html_name }}">
{% for c in realty_form.building_classification.field.queryset %}
<option value="{{ c.pk }}" {% if realty_form.building_classification.value|int == c.pk %}selected="selected"{% endif %}>{{ c.name }}</option>
{% endfor %}
</select>
</div>
<div class="col-lg-3">
<select
id="realtyConstructionTypeId"
class="selectpicker"
name="{{ realty_form.construction_type.html_name }}">
{% for t in realty_form.construction_type.field.queryset %}
<option value="{{ t.pk }}" {% if realty_form.construction_type.value|int == t.pk %}selected="selected"{% endif %}>{{ t.name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="titleF1 disTab">
<div class="col-lg-12">Местоположение <span id="{% random_ident %}" class="-validation-error" style="color: red">{{ realty_form.location.errors.as_text }}</span></div>
</div>
<div class="polsF1 polsF2 disTab">
<div class="col-lg-3">
<input type="hidden" class="-location-select -location-select-country" style="width: 100%">
</div>
<div class="col-lg-3">
<input type="hidden" class="-location-select -location-select-region" style="width: 100%">
</div>
<div class="col-lg-3">
<input type="hidden" class="-location-select -location-select-city" style="width: 100%">
</div>
<input type="hidden" id="chosenLocationId" name="{{ realty_form.location.html_name }}" value="{{ realty_form.location.value }}">
<div class="col-lg-3 make-new">
<label>
<input
type="checkbox"
{% if form.cro.value %}checked{% endif %}
name="{{ form.cro.html_name }}">
<span></span>
</label>
<p>Требуется допуск СРО</p>
</div>
</div>
</div>
<div class="searchF1 polsF1 polsFF links-filter">
<input class="btn-submit-link" type="submit" value="Сохранить">
</div>
</div>
</div> </div>
</form>
{% include 'partials/footer.html' %} <div class="col-lg-3">
<input type="hidden" class="-location-select -location-select-region" style="width: 100%">
</div>
<div class="col-lg-3">
<input type="hidden" class="-location-select -location-select-city" style="width: 100%">
</div>
<input type="hidden" id="chosenLocationId" name="{{ realty_form.location.html_name }}"
value="{{ realty_form.location.value }}">
<div class="col-lg-3 make-new">
<label>
<input
type="checkbox"
{% if form.cro.value %}checked{% endif %}
name="{{ form.cro.html_name }}">
<span></span>
</label>
<p>Требуется допуск СРО</p>
</div>
</div>
</div>
<div class="searchF1 polsF1 polsFF links-filter">
<input class="btn-submit-link" type="submit" value="Сохранить">
</div>
</div>
</div> </div>
</form>
{% include 'partials/footer.html' %}
</div> </div>
</div>
{% endblock %} {% endblock %}
{% block js_block %} {% block js_block %}
<script> <script>
// Project work type suggestion modal --------------------------------- // Project work type suggestion modal ---------------------------------
;(function() { ;
var $modal = $('#projectWorkTypeSuggestionModal') (function () {
var $form = $modal.find('.-project-work-type-suggestion-form').first() var $modal = $('#projectWorkTypeSuggestionModal')
var workTypeSuggestionUrl = '/projects/suggest-work-type/' var $form = $modal.find('.-project-work-type-suggestion-form').first()
var workTypeSuggestionUrl = '/projects/suggest-work-type/'
$modal.find('.-action-button').first().on('click', function($evt) {
$.post(workTypeSuggestionUrl, $form.serialize()) $modal.find('.-action-button').first().on('click', function ($evt) {
.then(function(res) { $.post(workTypeSuggestionUrl, $form.serialize())
if (res.status === 'success') { .then(function (res) {
console.log('Success') if (res.status === 'success') {
$form.trigger('reset') console.log('Success')
$('.-error').text('') $form.trigger('reset')
$modal.modal('hide') $('.-error').text('')
$.jGrowl('Предложение успешно отправлено') $modal.modal('hide')
} else if (res.status === 'error') { $.jGrowl('Предложение успешно отправлено')
console.log('Error') } else if (res.status === 'error') {
console.log('Error')
_.flow(
_.toPairs, _.flow(
_.toPairs,
_.each(function(pair) {
var cssSelector = pair[0] _.each(function (pair) {
var errors = pair[1] var cssSelector = pair[0]
var errors = pair[1]
$(cssSelector).first().text(_.join(' ', errors))
}) $(cssSelector).first().text(_.join(' ', errors))
)(res.form_errors)
}
}) })
)(res.form_errors)
}
}) })
}()) })
}())
// Scroll to first form validation error ------------------------------ // Scroll to first form validation error ------------------------------
;(function() { ;
var hash = $('.-validation-error').filter(function(i, el) {return $(el).text()}).first().attr('id') (function () {
var hash = $('.-validation-error').filter(function (i, el) {
return $(el).text()
}).first().attr('id')
if (hash) if (hash)
window.location.hash = hash window.location.hash = hash
}()) }())
</script> </script>
{% endblock %} {% endblock %}

@ -1,55 +1,56 @@
<div class="modal fade" id="projectWorkTypeSuggestionModal" tabindex="-1"> <div class="modal fade" id="projectWorkTypeSuggestionModal" tabindex="-1">
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span>&times;</span></button> <button type="button" class="close" data-dismiss="modal"><span>&times;</span></button>
<h4 class="modal-title">Предложение нового типа работы</h4> <h4 class="modal-title">Предложение нового типа работы</h4>
</div> </div>
<div class="modal-body">
<form action="{% url 'projects:suggest-work-type' %}" method="POST" novalidate class="-project-work-type-suggestion-form">
{% csrf_token %}
<div>{{ work_type_suggestion_form.non_field_errors }}</div> <div class="modal-body">
<form action="{% url 'projects:suggest-work-type' %}" method="POST" novalidate
class="-project-work-type-suggestion-form">
{% csrf_token %}
<div class="row"> <div>{{ work_type_suggestion_form.non_field_errors }}</div>
<div class="col-xs-12 projectsBlock">
<div>{{ work_type_suggestion_form.name.label }}</div>
<div>{{ work_type_suggestion_form.name }}</div>
<div class="-error -error-{{ work_type_suggestion_form.name.html_name }}"></div>
</div>
</div>
<div class="row"> <div class="row">
<div class="col-xs-12 projectsBlock"> <div class="col-xs-12 projectsBlock">
<div>{{ work_type_suggestion_form.commentary.label }}</div> <div>{{ work_type_suggestion_form.name.label }}</div>
<div>{{ work_type_suggestion_form.commentary }}</div> <div>{{ work_type_suggestion_form.name }}</div>
<div class="-error -error-{{ work_type_suggestion_form.commentary.html_name }}"></div> <div class="-error -error-{{ work_type_suggestion_form.name.html_name }}"></div>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-xs-12 projectsBlock"> <div class="col-xs-12 projectsBlock">
<div>{{ work_type_suggestion_form.email.label }}</div> <div>{{ work_type_suggestion_form.commentary.label }}</div>
<div>{{ work_type_suggestion_form.email }}</div> <div>{{ work_type_suggestion_form.commentary }}</div>
<div class="-error -error-{{ work_type_suggestion_form.email.html_name }}"></div> <div class="-error -error-{{ work_type_suggestion_form.commentary.html_name }}"></div>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-xs-12 projectsBlock"> <div class="col-xs-12 projectsBlock">
<div>{{ work_type_suggestion_form.username.label }}</div> <div>{{ work_type_suggestion_form.email.label }}</div>
<div>{{ work_type_suggestion_form.username }}</div> <div>{{ work_type_suggestion_form.email }}</div>
<div class="-error -error-{{ work_type_suggestion_form.username.html_name }}"></div> <div class="-error -error-{{ work_type_suggestion_form.email.html_name }}"></div>
</div>
</div>
</form>
</div> </div>
</div>
<div class="modal-footer"> <div class="row">
<button type="button" class="btn btn-default" data-dismiss="modal">Отмена</button> <div class="col-xs-12 projectsBlock">
<button type="button" class="btn btn-primary -action-button">Предложить</button> <div>{{ work_type_suggestion_form.username.label }}</div>
<div>{{ work_type_suggestion_form.username }}</div>
<div class="-error -error-{{ work_type_suggestion_form.username.html_name }}"></div>
</div> </div>
</div> </div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Отмена</button>
<button type="button" class="btn btn-primary -action-button">Предложить</button>
</div>
</div> </div>
</div>
</div> </div>

@ -1,90 +1,89 @@
{% load common_tags %} {% load common_tags %}
<div class="modal-body"> <div class="modal-body">
<form method="post">{% csrf_token %} <form method="post">{% csrf_token %}
<div class="textAreaBlock2 text-nn box-sizing disTab"> <div class="textAreaBlock2 text-nn box-sizing disTab">
<p>Название заказа <span style="color: red">{{ worksell_form.name.errors.as_text }}</span></p> <p>Название заказа <span style="color: red">{{ worksell_form.name.errors.as_text }}</span></p>
<input type="text" class="box-sizing" name="{{ worksell_form.name.html_name }}" <input type="text" class="box-sizing" name="{{ worksell_form.name.html_name }}"
value="{{ worksell_form.name.value }}"> value="{{ worksell_form.name.value }}">
</div>
<div class="textAreaBlock2 text-nn box-sizing disTab">
<p>Подробно опишите задание <span style="color: red">{{ worksell_form.text.errors.as_text }}</span></p>
<textarea name="{{ worksell_form.text.html_name }}" id="text-new">{{ worksell_form.text.value }}</textarea>
</div>
<div class="textAreaBlock2 text-nn box-sizing disTab">
<select id="realtyBuildingClassificationId" class="selectpicker"
name="{{ realty_form.building_classification.html_name }}">
{% for c in realty_form.building_classification.field.queryset %}
<option value="{{ c.pk }}"
{% if realty_form.building_classification.value|int == c.pk %}selected="selected"{% endif %}>{{ c.name }}</option>
{% endfor %}
</select>
</div>
<div class="polsF1 disTab">
<div class="col-lg-3">
<input type='hidden' class="-spec-select -spec-select-level-1" style="width: 100%">
</div>
<div class="col-lg-3">
<input type='hidden' class="-spec-select -spec-select-level-2" style="width: 100%">
</div>
<div class="col-lg-3">
<input type='hidden' class="-spec-select -spec-select-level-3" style="width: 100%">
</div>
<div class="col-lg-3">
<input type='hidden' class="-spec-select -spec-select-level-4" style="width: 100%">
</div>
<input type="hidden" id="chosenSpecId" name="{{ worksell_form.specialization.html_name }}"
value="{{ worksell_form.specialization.value }}">
</div>
<div class="textAreaBlock2 text-nn box-sizing disTab">
<p>Бюджет{{ worksell_form.budget.errors.as_text }}</p>
<div class="row">
<div class="col-lg-8">
<input type="text" class="box-sizing" name="{{ form.budget.html_name }}" value="{{ form.budget.value }}">
</div> </div>
<div class="col-lg-4">
<div class="textAreaBlock2 text-nn box-sizing disTab"> {{ worksell_form.budget_type }}
<p>Подробно опишите задание <span style="color: red">{{ worksell_form.text.errors.as_text }}</span></p>
<textarea name="{{ worksell_form.text.html_name }}" id="text-new">{{ worksell_form.text.value }}</textarea>
</div> </div>
</div>
<div class="textAreaBlock2 text-nn box-sizing disTab"> </div>
<select id="realtyBuildingClassificationId" class="selectpicker"
name="{{ realty_form.building_classification.html_name }}"> <div class="textAreaBlock2 text-nn box-sizing disTab">
{% for c in realty_form.building_classification.field.queryset %} <p>Срок выаолнения{{ worksell_form.budget.errors.as_text }}</p>
<option value="{{ c.pk }}" <div class="row">
{% if realty_form.building_classification.value|int == c.pk %}selected="selected"{% endif %}>{{ c.name }}</option> <div class="col-lg-8">
{% endfor %} <input type="text" class="box-sizing" name="{{ form.budget.html_name }}" value="{{ form.budget.value }}">
</select>
</div> </div>
<div class="col-lg-4">
{{ worksell_form.term_type }}
</div>
</div>
</div>
<div class="textAreaBlock2 text-nn box-sizing disTab">
<p>Бюджет{{ worksell_form.budget.errors.as_text }}</p>
<select id="realtyConstructionTypeId" class="selectpicker" name="{{ worksell_form.construction_type.html_name }}">
{% for t in realty_form.construction_type.field.queryset %}
<option value="{{ t.pk }}"
{% if realty_form.construction_type.value|int == t.pk %}selected="selected"{% endif %}>{{ t.name }}</option>
{% endfor %}
</select>
</div>
<div class="polsF1 disTab"> <div class="searchF1 polsF1 polsFF links-filter">
<div class="col-lg-3"> <input class="btn-submit-link" type="submit" value="Разместить проект">
<input type='hidden' class="-spec-select -spec-select-level-1" style="width: 100%"> </div>
</div>
<div class="col-lg-3">
<input type='hidden' class="-spec-select -spec-select-level-2" style="width: 100%">
</div>
<div class="col-lg-3">
<input type='hidden' class="-spec-select -spec-select-level-3" style="width: 100%">
</div>
<div class="col-lg-3">
<input type='hidden' class="-spec-select -spec-select-level-4" style="width: 100%">
</div>
<input type="hidden" id="chosenSpecId" name="{{ worksell_form.specialization.html_name }}"
value="{{ worksell_form.specialization.value }}">
</div>
<div class="textAreaBlock2 text-nn box-sizing disTab"> </form>
<p>Бюджет{{ worksell_form.budget.errors.as_text }}</p>
<div class="row">
<div class="col-lg-8">
<input type="text" class="box-sizing" name="{{ form.budget.html_name }}" value="{{ form.budget.value }}">
</div>
<div class="col-lg-4">
{{ worksell_form.budget_type }}
</div>
</div>
</div>
<div class="textAreaBlock2 text-nn box-sizing disTab">
<p>Срок выаолнения{{ worksell_form.budget.errors.as_text }}</p>
<div class="row">
<div class="col-lg-8">
<input type="text" class="box-sizing" name="{{ form.budget.html_name }}" value="{{ form.budget.value }}">
</div>
<div class="col-lg-4">
{{ worksell_form.term_type }}
</div>
</div>
</div>
<div class="textAreaBlock2 text-nn box-sizing disTab">
<p>Бюджет{{ worksell_form.budget.errors.as_text }}</p>
<select id="realtyConstructionTypeId" class="selectpicker" name="{{ worksell_form.construction_type.html_name }}">
{% for t in realty_form.construction_type.field.queryset %}
<option value="{{ t.pk }}"
{% if realty_form.construction_type.value|int == t.pk %}selected="selected"{% endif %}>{{ t.name }}</option>
{% endfor %}
</select>
</div>
<div class="searchF1 polsF1 polsFF links-filter">
<input class="btn-submit-link" type="submit" value="Разместить проект">
</div>
</form>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">

File diff suppressed because it is too large Load Diff

@ -1,199 +1,184 @@
{% extends 'partials/base.html' %} {% extends 'partials/base.html' %}
{% load common_tags %} {% load common_tags i18n %}
{% block content %} {% block content %}
{% include 'partials/header.html' %} {% include 'partials/header.html' %}
<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">Поиск заказов</p> <p class="titleScore">Поиск заказов</p>
</div>
<form action="{% url 'projects:project-filter' %}" method="GET" novalidate>
<div class="col-lg-12">
<div class="filter clearfix -spec-work-type-combo-container">
<div class="triangle1"></div>
<div class="titleF1 disTab">
<div class="col-lg-3">{% trans 'project_stage0' %}</div>
</div>
<div class="polsF1 disTab">
<div class="col-lg-3">
{{ form.work_type }}
</div>
</div> </div>
<form action="{% url 'projects:project-filter' %}" method="GET" novalidate>
<div class="col-lg-12"> <div class="titleF1 disTab">
<div class="filter clearfix -spec-work-type-combo-container"> </div>
<div class="triangle1"></div>
<div class="polsF1 disTab">
<div class="col-lg-3 -single-spec-select">
<div class="-bold">{% trans 'project_stage1' %} <span
style="color: red">{{ form.specialization.errors.as_text }}</span></div>
<input type="hidden" class="-spec-select -spec-select-level-1" style="width: 100%">
</div>
<div class="col-lg-3 -single-spec-select">
<div class="-bold"><span class="-dynamic-label">{% trans 'project_stage2' %}</span></div>
<input type="hidden" class="-spec-select -spec-select-level-2" style="width: 100%">
</div>
<div class="col-lg-3 -single-spec-select">
<div class="-bold">{% trans 'project_stage3' %}</div>
<input type="hidden" class="-spec-select -spec-select-level-3" style="width: 100%">
</div>
<div class="col-lg-3 -single-spec-select">
<div class="-bold">{% trans 'project_stage4' %}</div>
<input type="hidden" class="-spec-select -spec-select-level-4" style="width: 100%">
</div>
<input type="hidden" name="{{ form.specialization.html_name }}" value="{{ form.specialization.value }}"
class="-chosen-spec-id">
</div>
<div class="titleF1 disTab"> <div class="searchF1 resSearchF1">
<div class="col-lg-3">Тип работы</div> <div class="col-lg-6">
</div> <input
<div class="polsF1 disTab"> type="text"
<div class="col-lg-3"> name="keywords"
{{ form.work_type }} onkeydown="event.keyCode === 13 && $(this).closest('form').submit()"
</div> value="{{ form.keywords.value }}"
</div> class="searchInp box-sizing"
placeholder="Ключевые слова">
</div>
<div class="col-lg-3">
<a href="#" class="findReal" onclick="$(this).closest('form').submit(); return false">
найти проект
</a>
</div>
<div class="col-lg-3">
<a href="{% url 'projects:project-filter' %}" class="clearSearch">
Очистить фильтр
</a>
</div>
</div>
<div class="titleF1 disTab"> <div class="resSearchF1">
</div> <div class="col-lg-3">
<p class="titleResF1">Расширенные поля</p>
<button class="resButtonF1">
<span class="glyphicon glyphicon-arrow-up" aria-hidden="true"></span>
</button>
</div>
<div class="col-lg-9">
<div class="borderS1"></div>
</div>
</div>
<div class="polsF1 disTab">
<div class="col-lg-3 -single-spec-select">
<div class="-bold">Стадия проекта <span style="color: red">{{ form.specialization.errors.as_text }}</span></div>
<input type="hidden" class="-spec-select -spec-select-level-1" style="width: 100%">
</div>
<div class="col-lg-3 -single-spec-select">
<div class="-bold"><span class="-dynamic-label">Стадия проекта</span></div>
<input type="hidden" class="-spec-select -spec-select-level-2" style="width: 100%">
</div>
<div class="col-lg-3 -single-spec-select">
<div class="-bold">Раздел</div>
<input type="hidden" class="-spec-select -spec-select-level-3" style="width: 100%">
</div>
<div class="col-lg-3 -single-spec-select">
<div class="-bold">Подраздел</div>
<input type="hidden" class="-spec-select -spec-select-level-4" style="width: 100%">
</div>
<input type="hidden" name="{{ form.specialization.html_name }}" value="{{ form.specialization.value }}" class="-chosen-spec-id">
</div>
<div class="searchF1 resSearchF1">
<div class="col-lg-6">
<input
type="text"
name="keywords"
onkeydown="event.keyCode === 13 && $(this).closest('form').submit()"
value="{{ form.keywords.value }}"
class="searchInp box-sizing"
placeholder="Ключевые слова">
</div>
<div class="col-lg-3">
<a href="#" class="findReal" onclick="$(this).closest('form').submit(); return false">
найти проект
</a>
</div>
<div class="col-lg-3">
<a href="{% url 'projects:project-filter' %}" class="clearSearch">
Очистить фильтр
</a>
</div>
</div>
<div class="resSearchF1">
<div class="col-lg-3">
<p class="titleResF1">Расширенные поля</p>
<button class="resButtonF1">
<span class="glyphicon glyphicon-arrow-up" aria-hidden="true"></span>
</button>
</div>
<div class="col-lg-9">
<div class="borderS1"></div>
</div>
</div>
<div class="slideRes disTab activeSlide">
<div class="titleF1 disTab">
<div class="col-lg-3">Классификация здания</div>
<div class="col-lg-3">Вид строительства</div>
<div class="col-lg-3"></div>
</div>
<div class="polsF1 disTab">
<div class="col-lg-3">
{{ realty_form.building_classification }}
</div>
<div class="col-lg-3">
{{ realty_form.construction_type }}
</div>
</div>
</div>
<div class="slideRes disTab activeSlide">
<div class="titleF1 disTab">
<div class="col-lg-3">Местоположение</div>
</div>
<div class="polsF1 disTab">
<div class="col-lg-3">
<input type="hidden" class="-location-select -location-select-country" style="width: 100%">
</div>
<div class="col-lg-3">
<input type="hidden" class="-location-select -location-select-region" style="width: 100%">
</div>
<div class="col-lg-3">
<input type="hidden" class="-location-select -location-select-city" style="width: 100%">
</div>
<input type="hidden" id="chosenLocationId" name="{{ realty_form.location.html_name }}" value="{{ realty_form.location.value }}">
</div>
<div class="sro"> <div class="slideRes disTab activeSlide">
<div class="col-lg-12"> <div class="titleF1 disTab">
<label>{{ form.cro }}<span></span></label> <div class="col-lg-3">Классификация здания</div>
<p>Требуется допуск (СРО)</p> <div class="col-lg-3">Вид строительства</div>
</div> <div class="col-lg-3"></div>
</div> </div>
</div>
</div> <div class="polsF1 disTab">
<div class="col-lg-3">
{{ realty_form.building_classification }}
</div> </div>
<div class="col-lg-3">
{{ realty_form.construction_type }}
</div>
</div>
</div>
<div class="slideRes disTab activeSlide">
<div class="titleF1 disTab">
<div class="col-lg-3">Местоположение</div>
</div>
<div class="polsF1 disTab">
<div class="col-lg-3">
<input type="hidden" class="-location-select -location-select-country" style="width: 100%">
</div>
<div class="col-lg-3">
<input type="hidden" class="-location-select -location-select-region" style="width: 100%">
</div>
<div class="col-lg-3">
<input type="hidden" class="-location-select -location-select-city" style="width: 100%">
</div>
<input type="hidden" id="chosenLocationId" name="{{ realty_form.location.html_name }}"
value="{{ realty_form.location.value }}">
</div>
<div class="sro">
<div class="col-lg-12"> <div class="col-lg-12">
<p class="titleScore">{{ display_msg }}</p> <label>{{ form.cro }}<span></span></label>
<div class="linkSort"> <p>Требуется допуск (СРО)</p>
<p>Сортировать по:</p> </div>
</div>
</div>
</div>
</div>
{% for val, text in form.order_by.field.choices %}
<button type="submit" name="{{ form.order_by.html_name }}" value="{{ val }}">{{ text }}</button>
{% endfor %}
<input type="hidden" name="{{ form.last_order_by.html_name }}" value="{{ last_order_by }}"> <div class="col-lg-12">
<input type="checkbox" name="{{ form.reverse_order.html_name }}" {% if reverse_order %}checked{% endif %} style="display: none"> <p class="titleScore">{{ display_msg }}</p>
</div> <div class="linkSort">
</div> <p>Сортировать по:</p>
</form>
{% for val, text in form.order_by.field.choices %}
<button type="submit" name="{{ form.order_by.html_name }}" value="{{ val }}">{{ text }}</button>
{% endfor %}
<input type="hidden" name="{{ form.last_order_by.html_name }}" value="{{ last_order_by }}">
<input type="checkbox" name="{{ form.reverse_order.html_name }}" {% if reverse_order %}checked{% endif %}
style="display: none">
</div>
</div>
</form>
<div class="projectsBlock disTab"> <div class="projectsBlock disTab">
{% for project in projects %} {% for project in projects %}
<div class="projectPro clearfix"> <div class="projectPro clearfix">
<div class="col-lg-9 leftPro"> <div class="col-lg-9 leftPro">
<p class="titlePro"> <p class="titlePro">
<a href="{% url 'projects:detail' pk=project.pk %}">{{ project.name }}</a> <a href="{% url 'projects:detail' pk=project.pk %}">{{ project.name }}</a>
</p> </p>
{% if project.realty and project.realty.name %} {% if project.realty and project.realty.name %}
<ul class="desPro"> <ul class="desPro">
<li> <li>
<a href="?realty={{ project.realty.pk }}">Объект "{{ project.realty.name }}"</a> <a href="?realty={{ project.realty.pk }}">Объект "{{ project.realty.name }}"</a>
</li> </li>
</ul> </ul>
{% endif %} {% endif %}
<p class="textPro">{{ project.text|linebreaksbr|truncatechars:300 }}</p> <p class="textPro">{{ project.text|linebreaksbr|truncatechars:300 }}</p>
{% if TEMPLATE_DEBUG %} {% if TEMPLATE_DEBUG %}
<pre><!-- <pre><!--
--><b>Specialization:</b> {{ project.specialization }}<br><!-- --><b>Specialization:</b> {{ project.specialization }}<br><!--
--><br><!-- --><br><!--
--><b>Realty location:</b> {{ project.realty.location }}<br><!-- --><b>Realty location:</b> {{ project.realty.location }}<br><!--
@ -202,44 +187,44 @@
--><br><!-- --><br><!--
--><b>Build. classif.:</b> {{ project.realty.building_classification }}<br><!-- --><b>Build. classif.:</b> {{ project.realty.building_classification }}<br><!--
--></pre> --></pre>
{% endif %} {% endif %}
<ul class="listPro">
<li>{{ project.created }}</li>
<li>{{ project.hit_count.hits }}</li>
<li>{{ project.answers.count }}</li>
{% if request.user.is_authenticated %}
<li>{{ project.customer.username }}</li>
{% endif %}
</ul>
</div>
<div class="col-lg-3 rightPro">
<p class="cenaPro">
{{ project.budget }} <i class="{% fa_currency_classes project.currency %}"></i>
</p>
<ul>
{% if project.secure_deal %}
<li>Безопасная сделка</li>
{% endif %}
<li>
{{ project.specialization.name }}
</li>
</ul>
</div>
</div>
{% endfor %}
</div>
<ul class="listPro">
<li>{{ project.created }}</li>
<li>{{ project.hit_count.hits }}</li>
<li>{{ project.answers.count }}</li>
<div class="col-lg-12 pagin"> {% if request.user.is_authenticated %}
{% include 'partials/pagination.html' %} <li>{{ project.customer.username }}</li>
{% endif %}
</ul>
</div>
<div class="col-lg-3 rightPro">
<p class="cenaPro">
{{ project.budget }} <i class="{% fa_currency_classes project.currency %}"></i>
</p>
<ul>
{% if project.secure_deal %}
<li>Безопасная сделка</li>
{% endif %}
<li>
{{ project.specialization.name }}
</li>
</ul>
</div> </div>
</div>
{% endfor %}
</div>
{% include 'partials/footer.html' %} <div class="col-lg-12 pagin">
</div> {% include 'partials/pagination.html' %}
</div>
{% include 'partials/footer.html' %}
</div> </div>
</div>
{% endblock %} {% endblock %}

@ -1,28 +1,33 @@
import pydash as _;
from django import template from django import template
from pprint import pprint, pformat
import pydash as _; _.map = _.map_; _.filter = _.filter_
from archilance import util
_.map = _.map_;
_.filter = _.filter_
register = template.Library() register = template.Library()
@register.filter @register.filter
def get_candidates(project): def get_candidates(project):
return tuple(c.answer.author for c in project.candidates.all()) return tuple(c.answer.author for c in project.candidates.all())
@register.filter @register.filter
def get_new_answers(project): def get_new_answers(project):
return set(project.answers.filter(rejected=False)) - set(c.answer for c in project.candidates.filter(answer__rejected=False)) return set(project.answers.filter(rejected=False)) - set(
c.answer for c in project.candidates.filter(answer__rejected=False))
@register.filter @register.filter
def get_candidate_answers(project): def get_candidate_answers(project):
return tuple(c.answer for c in project.candidates.filter(answer__rejected=False)) return tuple(c.answer for c in project.candidates.filter(answer__rejected=False))
@register.filter @register.filter
def get_rejected_answers(project): def get_rejected_answers(project):
return project.answers.filter(rejected=True) return project.answers.filter(rejected=True)
@register.filter @register.filter
def get_answer(project, contractor): def get_answer(project, contractor):
answer = _.find(project.answers.all(), lambda a: a.author == contractor) answer = _.find(project.answers.all(), lambda a: a.author == contractor)
@ -32,5 +37,4 @@ def get_answer(project, contractor):
return answer return answer
# import code; code.interact(local=dict(globals(), **locals())) # import code; code.interact(local=dict(globals(), **locals()))

@ -1,3 +1 @@
from django.test import TestCase
# Create your tests here. # Create your tests here.

@ -1,5 +1,4 @@
from django.conf import urls from django.conf import urls
from django.views.generic import TemplateView
from .views import ( from .views import (
# ContractorOfferOrder, # ContractorOfferOrder,
@ -40,24 +39,29 @@ urlpatterns = [
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'^create-answer-message/(?P<pk>\d+)/$', ProjectAnswerCreateMessageView.as_view(), name='create-answer-message'), urls.url(r'^create-answer-message/(?P<pk>\d+)/$', ProjectAnswerCreateMessageView.as_view(),
name='create-answer-message'),
urls.url(r'^reject-project-answer/(?P<pk>\d+)/$', RejectProjectAnswerView.as_view(), name='reject-project-answer'), urls.url(r'^reject-project-answer/(?P<pk>\d+)/$', RejectProjectAnswerView.as_view(), name='reject-project-answer'),
urls.url(r'^restore-project-answer/(?P<pk>\d+)/$', RestoreProjectAnswerView.as_view(), name='restore-project-answer'), urls.url(r'^restore-project-answer/(?P<pk>\d+)/$', RestoreProjectAnswerView.as_view(),
name='restore-project-answer'),
urls.url(r'^arbitration/create/$', ArbitrationCreateView.as_view(), name='arbitration-create'), urls.url(r'^arbitration/create/$', ArbitrationCreateView.as_view(), name='arbitration-create'),
urls.url(r'^answer/move/archive/$', ContractorAnswerArchiveView.as_view(), name='contractor-answer-archive'), urls.url(r'^answer/move/archive/$', ContractorAnswerArchiveView.as_view(), name='contractor-answer-archive'),
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+)/$', PortfolioDetail.as_view(), name='contractor-portfolio-detail'), urls.url(r'^portfolio/(?P<pk>\d+)/$', PortfolioDetail.as_view(), name='contractor-portfolio-detail'),
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(),
urls.url(r'^portfolio/(?P<pk>\d+)/trash/$', ContractorPortfolioTrashView.as_view(), name='contractor-portfolio-trash'), name='contractor-portfolio-edit'),
urls.url(r'^portfolio/(?P<pk>\d+)/trash/$', ContractorPortfolioTrashView.as_view(),
name='contractor-portfolio-trash'),
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/delete/(?P<pk>(\d+))/$', CandidateDeleteView.as_view(), name='delete-candidate'), urls.url(r'^candidate/delete/(?P<pk>(\d+))/$', CandidateDeleteView.as_view(), name='delete-candidate'),
urls.url(r'^candidate/comparison/sort/$', sort_candidates, name='comparison-sort'), urls.url(r'^candidate/comparison/sort/$', sort_candidates, name='comparison-sort'),
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'^customer-offer-order/(?P<answer_id>(\d+))/(?P<project_id>(\d+))/$', CustomerOfferOrderView.as_view(), name='customer-offer-order'), urls.url(r'^customer-offer-order/(?P<answer_id>(\d+))/(?P<project_id>(\d+))/$', CustomerOfferOrderView.as_view(),
name='customer-offer-order'),
urls.url(r'^suggest-work-type/$', ProjectWorkTypeSuggestionView.as_view(), name='suggest-work-type'), urls.url(r'^suggest-work-type/$', ProjectWorkTypeSuggestionView.as_view(), name='suggest-work-type'),
] ]

@ -1,26 +1,29 @@
import json
from pprint import pformat
import natsort
import pydash as _;
from django.conf import settings from django.conf import settings
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.mixins import PermissionRequiredMixin, LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.core.files.base import ContentFile from django.core.files.base import ContentFile
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.core.urlresolvers import reverse, reverse_lazy from django.core.urlresolvers import reverse, reverse_lazy
from django.db.models import Q, F from django.db.models import Q
from django.http import HttpResponseForbidden, JsonResponse, HttpResponseRedirect, HttpResponse, Http404 from django.http import HttpResponseForbidden, JsonResponse, HttpResponseRedirect, HttpResponse, Http404
from django.shortcuts import render, get_object_or_404, redirect from django.shortcuts import render, get_object_or_404, redirect
from django.views.generic import ListView, DetailView, CreateView, DeleteView, View, UpdateView, TemplateView, FormView from django.views.generic import DetailView, CreateView, DeleteView, View, UpdateView
from hitcount.models import HitCount from hitcount.models import HitCount
from hitcount.views import HitCountMixin from hitcount.views import HitCountMixin
from pprint import pprint, pformat
import json _.map = _.map_;
import natsort _.filter = _.filter_
import pydash as _; _.map = _.map_; _.filter = _.filter_
import re import re
from .mixins import LastAccessMixin
from archilance import util from archilance import util
from archilance.mixins import BaseMixin from archilance.mixins import BaseMixin
from common.mixins import CustomerRequiredMixin, ContractorRequiredMixin, NoCsrfMixin from common.mixins import NoCsrfMixin
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 ratings.models import HistoryRating from ratings.models import HistoryRating
@ -36,7 +39,6 @@ from .models import (
PortfolioPhoto, PortfolioPhoto,
Project, Project,
ProjectFile, ProjectFile,
Realty,
TERM_TYPE_MORPHS, TERM_TYPE_MORPHS,
) )
@ -108,12 +110,11 @@ class ProjectDetailWithAnswerView(BaseMixin, View):
if request.user.is_authenticated() and request.user.is_contractor(): if request.user.is_authenticated() and request.user.is_contractor():
context = self.get_context_data(**kwargs) context = self.get_context_data(**kwargs)
answer_as_team = None answer_as_team = None
project = get_object_or_404(Project, pk=kwargs.get('pk')) # TODO: Does this work? project = get_object_or_404(Project, pk=kwargs.get('pk')) # TODO: Does this work?
if request.POST.get('answer_as_team') == 'on': if request.POST.get('answer_as_team') == 'on':
answer_as_team = True answer_as_team = True
# Check for duplicate answers: # Check for duplicate answers:
if answer_as_team and util.has_related(request.user, 'team'): if answer_as_team and util.has_related(request.user, 'team'):
@ -123,7 +124,6 @@ class ProjectDetailWithAnswerView(BaseMixin, View):
if project.answers.filter(object_id=request.user.pk, content_type__model='user').exists(): if project.answers.filter(object_id=request.user.pk, content_type__model='user').exists():
raise PermissionDenied('Повторный отклик') raise PermissionDenied('Повторный отклик')
if answer_as_team: if answer_as_team:
form = self.form_class(request.POST, request=request, answer_as_team=True, project=project) form = self.form_class(request.POST, request=request, answer_as_team=True, project=project)
else: else:
@ -416,7 +416,8 @@ class CustomerProjectCreateView(BaseMixin, View):
return render(request, self.template_name, context) return render(request, self.template_name, context)
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
form = self.form_class(request.POST, request=request) # Passing `request.FILES` seems unnecessary here. Files are added manually below form = self.form_class(request.POST,
request=request) # Passing `request.FILES` seems unnecessary here. Files are added manually below
form.is_valid() form.is_valid()
realty = form.cleaned_data.get('realty') realty = form.cleaned_data.get('realty')
@ -525,7 +526,8 @@ class CustomerProjectEditView(BaseMixin, View):
if form.is_valid() and realty_form.is_valid(): if form.is_valid() and realty_form.is_valid():
project = form.save(commit=False) project = form.save(commit=False)
project.customer = request.user project.customer = request.user
project.files = form.cleaned_data.get('files') # TODO: Should we somehow get rid of this explicit assignment? project.files = form.cleaned_data.get(
'files') # TODO: Should we somehow get rid of this explicit assignment?
project.save() project.save()
form.save_m2m() form.save_m2m()
@ -566,11 +568,10 @@ class CustomerProjectEditView(BaseMixin, View):
class ContractorAnswerArchiveView(View): class ContractorAnswerArchiveView(View):
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
project_pk = request.POST.get('project_pk') project_pk = request.POST.get('project_pk')
user_pk = request.POST.get('user_pk') user_pk = request.POST.get('user_pk')
answer = Answer.objects.filter(project_id=project_pk,object_id=user_pk, content_type__model='user').first() answer = Answer.objects.filter(project_id=project_pk, object_id=user_pk, content_type__model='user').first()
answer.is_archive = True answer.is_archive = True
answer.save() answer.save()
redirect_to = request.POST.get('next') redirect_to = request.POST.get('next')
@ -691,7 +692,6 @@ def add_candidate(request, answer_id, project_id):
if not candidate: if not candidate:
Candidate.objects.create(answer=answer, project=project, position=count_answers) Candidate.objects.create(answer=answer, project=project, position=count_answers)
redirect_to = '%s%s' % (reverse('projects:detail', kwargs={'pk': project_id}), '#answers') redirect_to = '%s%s' % (reverse('projects:detail', kwargs={'pk': project_id}), '#answers')
return redirect(redirect_to) return redirect(redirect_to)
@ -902,5 +902,4 @@ class ProjectWorkTypeSuggestionView(View):
'form_errors': form_errors, 'form_errors': form_errors,
}) })
# import code; code.interact(local=dict(globals(), **locals())) # import code; code.interact(local=dict(globals(), **locals()))

@ -1,4 +1,5 @@
from django.contrib import admin from django.contrib import admin
from .models import SpecializationRating, HistoryRating from .models import SpecializationRating, HistoryRating
admin.site.register(SpecializationRating) admin.site.register(SpecializationRating)

@ -1,7 +1,8 @@
from django.db import models from django.db import models
from django.utils import timezone from django.utils import timezone
from users.models import User, Team
from specializations.models import Specialization from specializations.models import Specialization
from users.models import User, Team
class HistoryRating(models.Model): class HistoryRating(models.Model):
@ -32,7 +33,8 @@ class HistoryRating(models.Model):
class SpecializationRating(models.Model): class SpecializationRating(models.Model):
user = models.ForeignKey(User, related_name='specialization_rating', null=True, blank=True) user = models.ForeignKey(User, related_name='specialization_rating', null=True, blank=True)
team = models.ForeignKey(Team, related_name='specialization_rating', null=True, blank=True) team = models.ForeignKey(Team, related_name='specialization_rating', null=True, blank=True)
specialization = models.ForeignKey(Specialization, related_name='specialization_rating') # TODO: Pluralize related name specialization = models.ForeignKey(Specialization,
related_name='specialization_rating') # TODO: Pluralize related name
position = models.PositiveIntegerField(default=0) position = models.PositiveIntegerField(default=0)
def __str__(self): def __str__(self):

@ -1,3 +1 @@
from django.test import TestCase
# Create your tests here. # Create your tests here.

@ -1,3 +1 @@
from django.shortcuts import render
# Create your views here. # Create your views here.

@ -1,4 +1,5 @@
from django.contrib import admin from django.contrib import admin
from .models import Review from .models import Review
admin.site.register(Review) admin.site.register(Review)

@ -5,4 +5,4 @@ class ReviewConfig(AppConfig):
name = 'reviews' name = 'reviews'
def ready(self): def ready(self):
import reviews.signals pass

@ -1,9 +1,9 @@
from django import forms from django import forms
from .models import Review from .models import Review
class ReviewForm(forms.ModelForm): class ReviewForm(forms.ModelForm):
class Meta: class Meta:
model = Review model = Review
@ -18,4 +18,3 @@ class ReviewForm(forms.ModelForm):
'target_customer', 'target_customer',
'from_team', 'from_team',
) )

@ -1,5 +1,5 @@
from django.db import models
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.db import models
from django.utils import timezone from django.utils import timezone
TYPE_REVIEWS = ( TYPE_REVIEWS = (

@ -1,8 +1,7 @@
from rest_framework.serializers import ModelSerializer
from rest_framework import serializers from rest_framework import serializers
from rest_framework.serializers import ModelSerializer
from .models import Review from .models import Review
from users.serializers import UserSerializer, TeamSerializer
class ReviewSerializer(ModelSerializer): class ReviewSerializer(ModelSerializer):
@ -38,4 +37,3 @@ class ReviewSerializer(ModelSerializer):
return obj.target_contractor.pk return obj.target_contractor.pk
elif obj.target_team: elif obj.target_team:
return obj.target_team.owner.pk return obj.target_team.owner.pk

@ -1,7 +1,6 @@
from django.db.models.signals import post_save from django.db.models.signals import post_save
from django.dispatch import receiver from django.dispatch import receiver
from users.models import User, Team
from ratings.models import HistoryRating from ratings.models import HistoryRating
from .models import Review from .models import Review
@ -28,4 +27,3 @@ def add_rating_review(sender, instance, created, **kwargs):
order = instance.project.order order = instance.project.order
order.status = 'completed' order.status = 'completed'
order.save() order.save()

@ -1,3 +1 @@
from django.test import TestCase
# Create your tests here. # Create your tests here.

@ -1,8 +1,8 @@
from django.shortcuts import render from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
from django.views.generic import ListView, CreateView, DeleteView from django.views.generic import ListView, CreateView, DeleteView
from .models import Review
from .forms import ReviewForm from .forms import ReviewForm
from .models import Review
class ReviewsView(LoginRequiredMixin, ListView): class ReviewsView(LoginRequiredMixin, ListView):

@ -6,5 +6,13 @@ from .models import Specialization
class SpecializationAdmin(MPTTModelAdmin): class SpecializationAdmin(MPTTModelAdmin):
readonly_fields = ('pk', 'lft', 'rght', 'tree_id', 'level') readonly_fields = ('pk', 'lft', 'rght', 'tree_id', 'level')
list_display = ('pk', 'name', 'order')
def get_queryset(self, request):
qs = super(SpecializationAdmin, self).get_queryset(request)
qs.order_by('order')
return qs
admin.site.register(Specialization, SpecializationAdmin) admin.site.register(Specialization, SpecializationAdmin)

@ -1,6 +1,8 @@
from rest_framework_filters import FilterSet, RelatedFilter, AllLookupsFilter from rest_framework_filters import FilterSet, RelatedFilter, AllLookupsFilter
from .models import Specialization from .models import Specialization
class SpecializationFilterSet(FilterSet): class SpecializationFilterSet(FilterSet):
id = AllLookupsFilter() id = AllLookupsFilter()
level = AllLookupsFilter() level = AllLookupsFilter()

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-10-14 20:06
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('specializations', '0002_auto_20161005_0342'),
]
operations = [
migrations.AddField(
model_name='specialization',
name='order',
field=models.PositiveIntegerField(default=0),
preserve_default=False,
),
]

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-10-14 20:44
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('specializations', '0003_specialization_order'),
]
operations = [
migrations.AlterModelOptions(
name='specialization',
options={'get_latest_by': 'order', 'ordering': ['order'], 'verbose_name': 'Специализация', 'verbose_name_plural': 'Специализации'},
),
migrations.AddField(
model_name='specialization',
name='selectable',
field=models.BooleanField(default=True),
),
]

@ -1,11 +1,13 @@
from django.db import models from django.db import models
from mptt.models import MPTTModel, TreeForeignKey
from mptt.managers import TreeManager from mptt.managers import TreeManager
from mptt.models import MPTTModel, TreeForeignKey
class Specialization(MPTTModel): class Specialization(MPTTModel):
name = models.CharField(max_length=500) name = models.CharField(max_length=500)
parent = TreeForeignKey('self', null=True, blank=True, related_name='children', db_index=True) parent = TreeForeignKey('self', null=True, blank=True, related_name='children', db_index=True)
order = models.PositiveIntegerField()
selectable = models.BooleanField(default=True)
objects = TreeManager() objects = TreeManager()
@ -13,8 +15,10 @@ class Specialization(MPTTModel):
return self.name return self.name
class Meta: class Meta:
get_latest_by = 'order'
ordering = ['order']
verbose_name = 'Специализация' verbose_name = 'Специализация'
verbose_name_plural = 'Специализации' verbose_name_plural = 'Специализации'
class MPTTMeta: class MPTTMeta:
order_insertion_by = ['name'] order_insertion_by = ['order', 'name']

@ -1,3 +1 @@
from django.test import TestCase
# Create your tests here. # Create your tests here.

@ -1,5 +1,4 @@
from django.conf import urls from django.conf import urls
# from django.contrib.auth.views import login, logout
from .views import SpecListView, SpecChildrenDetailView, test_page, test_spec from .views import SpecListView, SpecChildrenDetailView, test_page, test_spec

@ -1,10 +1,11 @@
from django.shortcuts import render from django.http import HttpResponse
from django.views.generic import ListView, DetailView
from django.http import JsonResponse from django.http import JsonResponse
from django.views.generic import ListView, DetailView
from django.views.generic import TemplateView from django.views.generic import TemplateView
from django.http import HttpResponse
from .models import Specialization from .models import Specialization
class SpecListView(ListView): class SpecListView(ListView):
model = Specialization model = Specialization
template_name = 'specializations/specialization.html' template_name = 'specializations/specialization.html'
@ -29,14 +30,18 @@ def test_page(request):
children = spec.get_children() children = spec.get_children()
return JsonResponse({"hello": 'yes'}) return JsonResponse({"hello": 'yes'})
else: else:
return JsonResponse({"hello":"python"}) return JsonResponse({"hello": "python"})
import json import json
def test_spec(request): def test_spec(request):
spec = Specialization.objects.get(pk=2) spec = Specialization.objects.get(pk=2)
children = spec.get_children() children = spec.get_children()
return HttpResponse(json.dumps(children)) return HttpResponse(json.dumps(children))
class SpecChildrenDetailView(DetailView): class SpecChildrenDetailView(DetailView):
model = Specialization model = Specialization

@ -11,8 +11,8 @@ from .models import (
class UserAdmin(admin.ModelAdmin): class UserAdmin(admin.ModelAdmin):
readonly_fields = ('pk','is_staff') readonly_fields = ('pk', 'is_staff')
list_display = ('username', 'email', 'get_groups', 'cro', 'is_active', 'rating','last_time_visit') list_display = ('username', 'email', 'get_groups', 'cro', 'is_active', 'rating', 'last_time_visit')
ordering = ('-rating',) ordering = ('-rating',)
def get_groups(self, obj): def get_groups(self, obj):

@ -5,4 +5,4 @@ class UsersConfig(AppConfig):
name = 'users' name = 'users'
def ready(self): def ready(self):
import users.signals pass

@ -1,11 +1,9 @@
from django.conf import settings
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from .models import User from .models import User
class EmailOrUsernameModelBackend(object): class EmailOrUsernameModelBackend(object):
def authenticate(self, username=None, password=None): def authenticate(self, username=None, password=None):
if '@' in username: if '@' in username:
kwargs = {'email': username} kwargs = {'email': username}

@ -1,5 +1,8 @@
import pydash as _;
from rest_framework_filters import FilterSet, RelatedFilter, AllLookupsFilter, MethodFilter from rest_framework_filters import FilterSet, RelatedFilter, AllLookupsFilter, MethodFilter
import pydash as _; _.map = _.map_; _.filter = _.filter_
_.map = _.map_;
_.filter = _.filter_
from .models import User, Team, ContractorResumeFiles, ContractorResume from .models import User, Team, ContractorResumeFiles, ContractorResume

@ -1,11 +1,15 @@
import itertools
import pydash as _;
from django import forms from django import forms
from mptt.forms import TreeNodeChoiceField from mptt.forms import TreeNodeChoiceField
import itertools
import pydash as _; _.map = _.map_; _.filter = _.filter_ _.map = _.map_;
_.filter = _.filter_
from .models import User, UserFinancialInfo, Team, ContractorResume, ContractorResumeFiles, GENDERS from .models import User, UserFinancialInfo, Team, ContractorResume, ContractorResumeFiles, GENDERS
from common.models import Location, LiveImageUpload from common.models import Location, LiveImageUpload
from projects.models import Project, Realty, BuildingClassfication, ConstructionType from projects.models import Project, BuildingClassfication, ConstructionType
from specializations.models import Specialization from specializations.models import Specialization
@ -165,8 +169,7 @@ class ContractorFilterForm(forms.Form):
last_order_by = forms.ChoiceField(required=False, choices=CONTRACTOR_ORDER_CHOICES) last_order_by = forms.ChoiceField(required=False, choices=CONTRACTOR_ORDER_CHOICES)
reverse_order = forms.BooleanField(required=False) reverse_order = forms.BooleanField(required=False)
try: # TODO: dirty
try: #TODO: dirty
qs = Specialization.objects.root_nodes()[0].get_descendants() qs = Specialization.objects.root_nodes()[0].get_descendants()
except: except:
qs = Specialization.objects qs = Specialization.objects
@ -203,7 +206,7 @@ class ContractorFilterForm(forms.Form):
) )
work_type = forms.ChoiceField( work_type = forms.ChoiceField(
choices=tuple(itertools.chain((('',''),), Project.WORK_TYPES)), choices=tuple(itertools.chain((('', ''),), Project.WORK_TYPES)),
widget=forms.Select(attrs={'class': 'selectpicker -project-work-type-select-field'}), widget=forms.Select(attrs={'class': 'selectpicker -project-work-type-select-field'}),
required=False, required=False,
) )
@ -233,7 +236,6 @@ class ContractorFilterForm(forms.Form):
class CustomerProfileProjectRealtyForm(forms.Form): class CustomerProfileProjectRealtyForm(forms.Form):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request') self.request = kwargs.pop('request')
self.customer = kwargs.pop('customer') self.customer = kwargs.pop('customer')
@ -252,5 +254,4 @@ class CustomerProfileProjectRealtyForm(forms.Form):
required=False, required=False,
) )
# import code; code.interact(local=dict(globals(), **locals())) # import code; code.interact(local=dict(globals(), **locals()))

@ -1,15 +1,19 @@
def get_projects_grouped(contractor): def get_projects_grouped(contractor):
private_open_projects = tuple(a.project for a in contractor.contractor_answers.filter(project__state='active', rejected=False)) private_open_projects = tuple(
a.project for a in contractor.contractor_answers.filter(project__state='active', rejected=False))
try: try:
team_open_projects = tuple(a.project for a in contractor.team.answers.filter(project__state='active', rejected=False)) team_open_projects = tuple(
a.project for a in contractor.team.answers.filter(project__state='active', rejected=False))
except: except:
team_open_projects = () team_open_projects = ()
private_archived_projects = tuple(a.project for a in contractor.contractor_answers.filter(project__state='active', rejected=True)) private_archived_projects = tuple(
a.project for a in contractor.contractor_answers.filter(project__state='active', rejected=True))
try: try:
team_archived_projects = tuple(a.project for a in contractor.team.answers.filter(project__state='active', rejected=True)) team_archived_projects = tuple(
a.project for a in contractor.team.answers.filter(project__state='active', rejected=True))
except: except:
team_archived_projects = () team_archived_projects = ()

@ -0,0 +1,42 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-10-14 22:49+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: templates/contractor_filter.html:27 templates/portfolio_create_form.html:25
#: templates/worksell_create_form.html:20
msgid "project_stage0"
msgstr "Тип работы"
#: templates/contractor_filter.html:46 templates/portfolio_create_form.html:37
#: templates/worksell_create_form.html:32
msgid "project_stage1"
msgstr "Стадия проекта"
#: templates/contractor_filter.html:50 templates/portfolio_create_form.html:42
#: templates/worksell_create_form.html:37
msgid "project_stage2"
msgstr "Раздел"
#: templates/contractor_filter.html:54 templates/portfolio_create_form.html:47
#: templates/worksell_create_form.html:42
msgid "project_stage3"
msgstr "Подраздел"
#: templates/contractor_filter.html:58 templates/portfolio_create_form.html:52
#: templates/worksell_create_form.html:47
msgid "project_stage4"
msgstr "Подраздел ( доп. )"

@ -14,6 +14,5 @@ class CheckForUserMixin(object):
class OwnershipMixin(object): class OwnershipMixin(object):
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
pass pass

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save