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рок этапа рассчитывается с момента резервирования средств

' + '

' + statusName + '

'; }); 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 }}
@@ -290,3 +296,55 @@
{% 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 }}
@@ -304,3 +310,55 @@
{% 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 @@ -