diff --git a/assets/css/main.css b/assets/css/main.css
index 46f23b6..1dd75f8 100644
--- a/assets/css/main.css
+++ b/assets/css/main.css
@@ -237,14 +237,14 @@ ul li {
}
.changeBlock1 > a, .changeBlock1 > a:link, .changeBlock1 > a:visited {
- background: url('../img/button1.png') no-repeat 25px , white;
- color: black;
+ background: url('../img/button1.png') no-repeat 25px , black;
+ color: white;
padding: 24px 26px 20px 72px;
}
.changeBlock2 > a, .changeBlock2 > a:link, .changeBlock2 > a:visited {
- background: url('../img/button2.png') no-repeat 27px, black;
- color: white;
+ background: url('../img/button2.png') no-repeat 27px, white;
+ color: black;
padding: 24px 26px 20px 72px;
}
diff --git a/assets/js/chat_contractor.js b/assets/js/chat_contractor.js
index cf8ead8..5ba73f1 100644
--- a/assets/js/chat_contractor.js
+++ b/assets/js/chat_contractor.js
@@ -489,7 +489,7 @@ $(function () {
'
Этап ' + v.pos + '' + v.name + '
' +
'Результаты этапа:' + v.result + '
' +
'
Срок до ' + v.term + '
' + v.cost + ' ' +
- '
Cрок заказа рассчитывается с момента резервирования средств
' +
+ '
Cрок этапа рассчитывается с момента резервирования средств
' +
'
';
});
diff --git a/common/templatetags/common_tags.py b/common/templatetags/common_tags.py
index 5347785..28e7f56 100644
--- a/common/templatetags/common_tags.py
+++ b/common/templatetags/common_tags.py
@@ -42,6 +42,11 @@ def interact(**kwargs):
import code; code.interact(local=dict(kwargs, **dict(globals(), **locals())))
+@register.simple_tag
+def random_ident(*args, **kwargs):
+ return util.random_ident(*args, **kwargs)
+
+
@register.filter('int')
def to_int(val):
return int(val)
diff --git a/projects/admin.py b/projects/admin.py
index d45017a..703d11d 100644
--- a/projects/admin.py
+++ b/projects/admin.py
@@ -12,6 +12,7 @@ from .models import (
PortfolioPhoto,
Project,
ProjectFile,
+ ProjectWorkTypeSuggestion,
Realty,
Stage,
)
@@ -42,14 +43,15 @@ class StageAdmin(admin.ModelAdmin):
admin.site.register(Answer)
-admin.site.register(Portfolio)
-admin.site.register(PortfolioPhoto)
-admin.site.register(Realty)
-admin.site.register(Order, OrderAdmin)
-admin.site.register(Candidate)
-admin.site.register(Stage, StageAdmin)
+admin.site.register(Arbitration)
admin.site.register(BuildingClassfication)
+admin.site.register(Candidate)
admin.site.register(ConstructionType)
+admin.site.register(Order, OrderAdmin)
+admin.site.register(Portfolio)
+admin.site.register(PortfolioPhoto)
admin.site.register(Project, ProjectAdmin)
admin.site.register(ProjectFile)
-admin.site.register(Arbitration)
+admin.site.register(ProjectWorkTypeSuggestion)
+admin.site.register(Realty)
+admin.site.register(Stage, StageAdmin)
diff --git a/projects/forms.py b/projects/forms.py
index 6196118..0845229 100644
--- a/projects/forms.py
+++ b/projects/forms.py
@@ -4,8 +4,9 @@ from django.forms.models import inlineformset_factory
from mptt.forms import TreeNodeChoiceField
from pprint import pprint, pformat
import itertools
+import pydash as _; _.map = _.map_; _.filter = _.filter_
-from .models import Project, ProjectFile, Portfolio, Answer, AnswerMessage, Realty, PortfolioPhoto, Stage
+from .models import Project, ProjectFile, Portfolio, Answer, AnswerMessage, Realty, PortfolioPhoto, Stage, ProjectWorkTypeSuggestion
from archilance import util
from common.models import Location, LiveImageUpload
from specializations.models import Specialization
@@ -363,4 +364,28 @@ class CustomerProjectDeleteForm(forms.Form):
self.fields['pk'].queryset = self.req.user.customer_projects.filter(Q(state='active') | Q(state='trashed'))
+class ProjectWorkTypeSuggestionForm(forms.ModelForm):
+ class Meta:
+ model = ProjectWorkTypeSuggestion
+
+ fields = (
+ 'name',
+ 'commentary',
+ 'email',
+ 'username',
+ )
+
+ def __init__(self, *args, **kwargs):
+ self.request = kwargs.pop('request', None)
+ super().__init__(*args, **kwargs)
+
+ # for bfield in self:
+ # attrs = bfield.field.widget.attrs
+ # attrs['class'] = _.join(_.compact((attrs.get('class'), '-error -error-%s' % bfield.html_name)), ' ')
+
+ if self.request and self.request.user.is_authenticated():
+ self['username'].field.initial = self.request.user.username
+ self['email'].field.initial = self.request.user.email
+
+
# import code; code.interact(local=dict(globals(), **locals()))
diff --git a/projects/migrations/0032_auto_20160915_2056.py b/projects/migrations/0032_auto_20160915_2056.py
new file mode 100644
index 0000000..e9ed737
--- /dev/null
+++ b/projects/migrations/0032_auto_20160915_2056.py
@@ -0,0 +1,45 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.7 on 2016-09-15 17:56
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('projects', '0031_merge'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='ProjectWorkTypeSuggestion',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=255)),
+ ('commentary', models.TextField(blank=True)),
+ ('processed', models.BooleanField(default=False)),
+ ('username', models.CharField(max_length=255)),
+ ('email', models.CharField(max_length=255)),
+ ],
+ options={
+ 'verbose_name': 'Предложение типов работ (проектов)',
+ 'verbose_name_plural': 'Предложения типов работ (проектов)',
+ },
+ ),
+ migrations.AlterField(
+ model_name='answerfile',
+ name='file',
+ field=models.FileField(upload_to='projects/answer_files/'),
+ ),
+ migrations.AlterField(
+ model_name='portfoliophoto',
+ name='img',
+ field=models.ImageField(upload_to='projects/portfolio/'),
+ ),
+ migrations.AlterField(
+ model_name='projectfile',
+ name='file',
+ field=models.FileField(upload_to='projects/project_files/'),
+ ),
+ ]
diff --git a/projects/migrations/0033_auto_20160916_1534.py b/projects/migrations/0033_auto_20160916_1534.py
new file mode 100644
index 0000000..8f7487e
--- /dev/null
+++ b/projects/migrations/0033_auto_20160916_1534.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.7 on 2016-09-16 12:34
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('projects', '0032_auto_20160915_2056'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='projectworktypesuggestion',
+ name='email',
+ field=models.EmailField(max_length=254),
+ ),
+ ]
diff --git a/projects/models.py b/projects/models.py
index 3b9eff1..2a6c468 100644
--- a/projects/models.py
+++ b/projects/models.py
@@ -359,3 +359,18 @@ class PortfolioPhoto(models.Model):
def __str__(self):
return self.img and self.img.url or str(self.img)
+
+
+class ProjectWorkTypeSuggestion(models.Model):
+ name = models.CharField(max_length=255)
+ commentary = models.TextField(blank=True)
+ processed = models.BooleanField(default=False)
+ username = models.CharField(max_length=255)
+ email = models.EmailField()
+
+ class Meta:
+ verbose_name = 'Предложение типов работ (проектов)'
+ verbose_name_plural = 'Предложения типов работ (проектов)'
+
+ def __str__(self):
+ return self.name
diff --git a/projects/templates/customer_project_create.html b/projects/templates/customer_project_create.html
index 17396c2..508d25f 100644
--- a/projects/templates/customer_project_create.html
+++ b/projects/templates/customer_project_create.html
@@ -1,8 +1,14 @@
{% extends 'partials/base.html' %}
-{% load common_tags %}
+{% block head_css %}
+
+{% endblock %}
+
{% block content %}
+ {% include 'partials/modals/project_work_type_suggestion.html' %}
{% include 'partials/header.html' %}
@@ -25,12 +31,12 @@
{% endif %}
-
Название заказа {{ form.name.errors.as_text }}
+
Название заказа {{ form.name.errors.as_text }}
-
Подробно опишите задание {{ form.text.errors.as_text }}
+
Подробно опишите задание {{ form.text.errors.as_text }}
@@ -52,7 +58,7 @@
- Тип работы {{ form.work_type.errors.as_text }}
+ Тип работы {{ form.work_type.errors.as_text }}
{% for id, text in form.work_type.field.choices %}
@@ -71,14 +77,14 @@
{% endfor %}
-
Специализация проекта {{ form.specialization.errors.as_text }}
+
Специализация проекта {{ form.specialization.errors.as_text }}
@@ -103,7 +109,7 @@
-
Бюджет {{ form.budget.errors.as_text }}
+
Бюджет {{ form.budget.errors.as_text }}
@@ -140,7 +146,7 @@
Сделать для исполнителей обязательным для заполнения поля цена и срок
-
Способ оплаты {{ form.deal_type.errors.as_text }}
+
Способ оплаты {{ form.deal_type.errors.as_text }}
@@ -203,10 +209,10 @@
-
Выбор объекта
{{ form.realty.errors.as_text }}
-
Наименование
{{ realty_form.name.errors.as_text }}
-
Классификация здания
{{ realty_form.building_classification.errors.as_text }}
-
Вид строительства
{{ realty_form.construction_type.errors.as_text }}
+
Выбор объекта
{{ form.realty.errors.as_text }}
+
Наименование
{{ realty_form.name.errors.as_text }}
+
Классификация здания
{{ realty_form.building_classification.errors.as_text }}
+
Вид строительства
{{ realty_form.construction_type.errors.as_text }}
@@ -252,7 +258,7 @@
-
Местоположение {{ realty_form.location.errors.as_text }}
+
Местоположение {{ realty_form.location.errors.as_text }}
{% endblock %}
+
+
+{% block js_block %}
+
+{% endblock %}
diff --git a/projects/templates/customer_project_edit.html b/projects/templates/customer_project_edit.html
index 39f7dae..5df41ac 100644
--- a/projects/templates/customer_project_edit.html
+++ b/projects/templates/customer_project_edit.html
@@ -1,8 +1,14 @@
{% extends 'partials/base.html' %}
-{% load common_tags %}
+{% block head_css %}
+
+{% endblock %}
+
{% block content %}
+ {% include 'partials/modals/project_work_type_suggestion.html' %}
{% include 'partials/header.html' %}
@@ -26,12 +32,12 @@
{% endif %}
-
Название заказа {{ form.name.errors.as_text }}
+
Название заказа {{ form.name.errors.as_text }}
-
Подробно опишите задание {{ form.text.errors.as_text }}
+
Подробно опишите задание {{ form.text.errors.as_text }}
@@ -62,7 +68,7 @@
-
Тип работы {{ form.work_type.errors.as_text }}
+
Тип работы {{ form.work_type.errors.as_text }}
{% for id, text in form.work_type.field.choices %}
@@ -81,14 +87,14 @@
{% endfor %}
-
Специализация проекта {{ form.specialization.errors.as_text }}
+
Специализация проекта {{ form.specialization.errors.as_text }}
@@ -113,7 +119,7 @@
-
Бюджет {{ form.budget.errors.as_text }}
+
Бюджет {{ form.budget.errors.as_text }}
@@ -150,7 +156,7 @@
Сделать для исполнителей обязательным для заполнения поля цена и срок
-
Способ оплаты {{ form.deal_type.errors.as_text }}
+
Способ оплаты {{ form.deal_type.errors.as_text }}
@@ -212,10 +218,10 @@
-
Выбор объекта
{{ form.realty.errors.as_text }}
-
Наименование
{{ realty_form.name.errors.as_text }}
-
Классификация здания
{{ realty_form.building_classification.errors.as_text }}
-
Вид строительства
{{ realty_form.construction_type.errors.as_text }}
+
Выбор объекта
{{ form.realty.errors.as_text }}
+
Наименование
{{ realty_form.name.errors.as_text }}
+
Классификация здания
{{ realty_form.building_classification.errors.as_text }}
+
Вид строительства
{{ realty_form.construction_type.errors.as_text }}
@@ -261,7 +267,7 @@
-
Местоположение {{ realty_form.location.errors.as_text }}
+
Местоположение {{ realty_form.location.errors.as_text }}
{% endblock %}
+
+
+{% block js_block %}
+
+{% endblock %}
diff --git a/projects/templates/partials/modals/project_work_type_suggestion.html b/projects/templates/partials/modals/project_work_type_suggestion.html
new file mode 100644
index 0000000..42ac5cc
--- /dev/null
+++ b/projects/templates/partials/modals/project_work_type_suggestion.html
@@ -0,0 +1,55 @@
+
diff --git a/projects/urls.py b/projects/urls.py
index 41a786e..f510473 100644
--- a/projects/urls.py
+++ b/projects/urls.py
@@ -22,6 +22,7 @@ from .views import (
ProjectComparisonView,
ProjectDetailWithAnswerView,
ProjectFilterView,
+ ProjectWorkTypeSuggestionView,
RejectProjectAnswerView,
RestoreProjectAnswerView,
sort_candidates,
@@ -58,6 +59,5 @@ urlpatterns = [
urls.url(r'^customer-offer-order/(?P
(\d+))/(?P(\d+))/$', CustomerOfferOrderView.as_view(), name='customer-offer-order'),
- # urls.url(r'^(?P\d+)/contractor-offer-order/(?P\d+)/$', ContractorOfferOrder.as_view(), name='contractor-offer-order'),
- # urls.url(r'^(?P\d+)/team-offer-order/(?P\d+)/$', TeamOfferOrder.as_view(), name='team-offer-order'),
+ urls.url(r'^suggest-work-type/$', ProjectWorkTypeSuggestionView.as_view(), name='suggest-work-type'),
]
diff --git a/projects/views.py b/projects/views.py
index 5c336bd..4009023 100644
--- a/projects/views.py
+++ b/projects/views.py
@@ -51,6 +51,7 @@ from .forms import (
ProjectAnswerMessageForm,
ProjectFilterForm,
ProjectFilterRealtyForm,
+ ProjectWorkTypeSuggestionForm,
RealtyForm,
)
@@ -374,6 +375,7 @@ class ProjectFilterView(BaseMixin, View):
class CustomerProjectCreateView(BaseMixin, View):
form_class = CustomerProjectEditForm
realty_form = RealtyForm
+ work_type_suggestion_form = ProjectWorkTypeSuggestionForm
template_name = 'customer_project_create.html'
def dispatch(self, request, *args, **kwargs):
@@ -383,11 +385,17 @@ class CustomerProjectCreateView(BaseMixin, View):
raise PermissionDenied
def get(self, request, *args, **kwargs):
+ context = self.get_context_data(**_.merge({}, request.GET, kwargs))
+
form = self.form_class(request=request)
realty_form = self.realty_form(request=request, prefix='realty_form')
-
- context = self.get_context_data(**_.merge({}, request.GET, kwargs))
- context.update({'form': form, 'realty_form': realty_form})
+ work_type_suggestion_form = self.work_type_suggestion_form(request=request, prefix='work_type_suggestion')
+
+ context.update({
+ 'form': form,
+ 'realty_form': realty_form,
+ 'work_type_suggestion_form': work_type_suggestion_form,
+ })
return render(request, self.template_name, context)
@@ -448,17 +456,24 @@ class CustomerProjectCreateView(BaseMixin, View):
class CustomerProjectEditView(BaseMixin, View):
form_class = CustomerProjectEditForm
realty_form = RealtyForm
+ work_type_suggestion_form = ProjectWorkTypeSuggestionForm
template_name = 'customer_project_edit.html'
def dispatch(self, request, *args, **kwargs):
if request.user.is_authenticated() and request.user.is_customer():
- return super().dispatch(request, *args, **kwargs)
- else:
- raise PermissionDenied
+ # Prevent editing when project's taken:
+
+ project = get_object_or_404(request.user.customer_projects, pk=kwargs.get('pk'))
+
+ if not project.order.contractor and not project.order.team:
+ return super().dispatch(request, *args, **kwargs)
+
+ raise PermissionDenied
def get(self, request, *args, **kwargs):
project = get_object_or_404(request.user.customer_projects, pk=kwargs.get('pk'))
form = self.form_class(instance=project, request=request)
+ work_type_suggestion_form = self.work_type_suggestion_form(request=request, prefix='work_type_suggestion')
realty = project.realty
@@ -468,7 +483,12 @@ class CustomerProjectEditView(BaseMixin, View):
realty_form = self.realty_form(request=request, prefix='realty_form')
context = self.get_context_data(**_.merge({}, request.GET, kwargs))
- context.update({'form': form, 'realty_form': realty_form})
+
+ context.update({
+ 'form': form,
+ 'realty_form': realty_form,
+ 'work_type_suggestion_form': work_type_suggestion_form,
+ })
return render(request, self.template_name, context)
@@ -831,22 +851,28 @@ class ArbitrationCreateView(CreateView):
return super().form_invalid(form)
-# class ContractorOfferOrder(NoCsrfMixin, CustomerRequiredMixin, View):
-# def post(self, request, *args, project_id, contractor_id, **kwargs):
-# project = get_object_or_404(Project, pk=project_id)
-# contractor = get_object_or_404(User.contractor_objects, pk=contractor_id)
-#
-# # project.order.contractor
-#
-# return JsonResponse({'status': 'success'})
-#
-#
-# class TeamOfferOrder(NoCsrfMixin, CustomerRequiredMixin, View):
-# def post(self, request, *args, project_id, team_id, **kwargs):
-# project = get_object_or_404(Project, pk=project_id)
-# team = get_object_or_404(Team, pk=team_id)
-#
-# return JsonResponse({'status': 'success'})
+class ProjectWorkTypeSuggestionView(View):
+ form_class = ProjectWorkTypeSuggestionForm
+ template_name = 'customer_project_work_type_suggestion.html'
+
+ # def get(self, request, *args, **kwargs):
+ # form = self.form_class(request=request, prefix='work_type_suggestion')
+ # context = {'form': form}
+ # return render(request, self.template_name, context)
+
+ def post(self, request, *args, **kwargs):
+ form = self.form_class(request.POST, request=request, prefix='work_type_suggestion')
+
+ if form.is_valid():
+ form.save()
+ return JsonResponse({'status': 'success'})
+ else:
+ form_errors = {'.-error-%s' % bfield.html_name: bfield.errors for bfield in form}
+
+ return JsonResponse({
+ 'status': 'error',
+ 'form_errors': form_errors,
+ })
# import code; code.interact(local=dict(globals(), **locals()))
diff --git a/templates/partials/base_test.html b/templates/partials/base_test.html
new file mode 100644
index 0000000..97ad665
--- /dev/null
+++ b/templates/partials/base_test.html
@@ -0,0 +1,83 @@
+{% load staticfiles %}
+{% load compress %}
+
+
+
+
+
+
+
+
+
+
+ {% block head %}{% endblock %}
+
+ PROEKTON
+
+ {% compress css %}
+
+
+{# #}
+{# #}
+{# #}
+{# #}
+{# #}
+{# #}
+{# #}
+{# #}
+
+ {% block head_css %}{% endblock %}
+
+{# #}
+{# #}
+
+ {% endcompress %}
+
+
+
+{% if messages %}
+ {% for message in messages %}
+ {{ message|safe }}
+ {% endfor %}
+{% endif %}
+
+
+ {{ request.user }}
+
+ {% if request.user.is_authenticated %}
+ PK: {{ request.user.pk }}
+ Groups: {{ request.user.groups.all }}
+ {% endif %}
+
+
+{% block content %}{% endblock %}
+
+
+
+
+
+
+
+
+
+
+
+
+{##}
+{##}
+{##}
+{##}
+{##}
+{##}
+{##}
+{##}
+
+
+
+{# #}
+
+
+{% block js_block %}{% endblock %}
+
+
diff --git a/users/templates/contractor_profile.html b/users/templates/contractor_profile.html
index 2f089db..a9a9aba 100644
--- a/users/templates/contractor_profile.html
+++ b/users/templates/contractor_profile.html
@@ -588,7 +588,7 @@
-