From 852546771b50d230e43fdd746ce6d46f57b705d4 Mon Sep 17 00:00:00 2001 From: Mukhtar Date: Thu, 7 Jul 2016 20:00:53 +0300 Subject: [PATCH] #ARC-6 Duplicate for portfolio --- projects/forms.py | 6 + .../migrations/0039_auto_20160707_1724.py | 56 +++++++++ projects/models.py | 14 +-- .../templates/contractor_portfolio_edit.html | 97 ++++++++++++++++ projects/urls.py | 6 +- projects/views.py | 31 ++++- users/templates/contractor_profile.html | 24 +++- users/templates/portfolio_create_form.html | 41 ++++--- users/templates/worksell_create_form.html | 8 +- users/views.py | 3 + work_sell/filters.py | 12 ++ work_sell/forms.py | 3 +- work_sell/templates/worksell_delete.html | 10 ++ work_sell/templates/worksell_detail.html | 106 ++++-------------- work_sell/templates/worksell_edit.html | 13 +-- work_sell/templates/worksells_list.html | 36 +++--- work_sell/urls.py | 4 +- work_sell/views.py | 25 ++++- 18 files changed, 342 insertions(+), 153 deletions(-) create mode 100644 projects/migrations/0039_auto_20160707_1724.py create mode 100644 projects/templates/contractor_portfolio_edit.html create mode 100644 work_sell/filters.py create mode 100644 work_sell/templates/worksell_delete.html diff --git a/projects/forms.py b/projects/forms.py index 8e978dd..fa0b5b9 100644 --- a/projects/forms.py +++ b/projects/forms.py @@ -92,6 +92,12 @@ class PortfolioForm(forms.ModelForm): model = Portfolio fields = '__all__' + widgets = { + 'construction_type': forms.Select(attrs={'class':'selectpicker'}), + 'building_classification': forms.Select(attrs={'class':'selectpicker'}), + 'currency': forms.Select(attrs={'class':'selectpicker'}), + 'term_type': forms.Select(attrs={'class':'selectpicker'}), + } class ContractorProjectAnswerForm(forms.ModelForm): # def __init__(self, *args, **kwargs): diff --git a/projects/migrations/0039_auto_20160707_1724.py b/projects/migrations/0039_auto_20160707_1724.py new file mode 100644 index 0000000..3c52cb5 --- /dev/null +++ b/projects/migrations/0039_auto_20160707_1724.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.6 on 2016-07-07 14:24 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import mptt.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('projects', '0038_auto_20160706_1249'), + ] + + operations = [ + migrations.RemoveField( + model_name='portfolio', + name='budget_by_agreement', + ), + migrations.AddField( + model_name='portfolio', + name='currency', + field=models.CharField(blank=True, choices=[('rur', 'RUR'), ('usd', 'USD'), ('eur', 'EUR')], default='rur', max_length=20, null=True), + ), + migrations.AlterField( + model_name='portfolio', + name='budget', + field=models.DecimalField(blank=True, decimal_places=0, default=0, max_digits=10, null=True), + ), + migrations.AlterField( + model_name='portfolio', + name='building_classification', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='portfolios', to='projects.BuildingClassfication'), + ), + migrations.AlterField( + model_name='portfolio', + name='construction_type', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='portfolios', to='projects.ConstructionType'), + ), + migrations.AlterField( + model_name='portfolio', + name='specialization', + field=mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='portfolios', to='specializations.Specialization'), + ), + migrations.AlterField( + model_name='portfolio', + name='term', + field=models.IntegerField(blank=True, default=0, null=True), + ), + migrations.AlterField( + model_name='portfolio', + name='term_type', + field=models.CharField(blank=True, choices=[('project', 'За проект'), ('hour', 'За час'), ('day', 'За день'), ('month', 'За месяц')], default='hour', max_length=20, null=True), + ), + ] diff --git a/projects/models.py b/projects/models.py index e08d8f8..6eea696 100644 --- a/projects/models.py +++ b/projects/models.py @@ -180,13 +180,13 @@ class Candidate(models.Model): class Portfolio(models.Model): description = models.TextField() name = models.CharField(max_length=255) - budget = models.DecimalField(max_digits=10, decimal_places=0, default=0, null=True) - budget_by_agreement = models.BooleanField(default=False) - specialization = TreeForeignKey(Specialization, related_name='portfolios') - term = models.IntegerField(default=0) - term_type = models.CharField(max_length=20, choices=TERMS, default='hour') - building_classification = models.ForeignKey(BuildingClassfication, related_name='portfolios') - construction_type = models.ForeignKey(ConstructionType, related_name='portfolios') + budget = models.DecimalField(max_digits=10, decimal_places=0, default=0, null=True, blank=True) + currency = models.CharField(max_length=20, default='rur', choices=CURRENCIES, null=True, blank=True) + specialization = TreeForeignKey(Specialization, related_name='portfolios',null=True, blank=True) + term = models.IntegerField(default=0,null=True, blank=True) + term_type = models.CharField(max_length=20, choices=TERMS, default='hour',null=True, blank=True) + building_classification = models.ForeignKey(BuildingClassfication, related_name='portfolios',null=True, blank=True) + construction_type = models.ForeignKey(ConstructionType, related_name='portfolios',null=True, blank=True) location = TreeForeignKey('common.Location', related_name='portfolios', null=True, blank=True) worksell = models.BooleanField(default=False) user = models.ForeignKey(User, related_name='portfolios') diff --git a/projects/templates/contractor_portfolio_edit.html b/projects/templates/contractor_portfolio_edit.html new file mode 100644 index 0000000..06eea9c --- /dev/null +++ b/projects/templates/contractor_portfolio_edit.html @@ -0,0 +1,97 @@ +{% extends 'partials/base.html' %} + +{% load common_tags %} + +{% block content %} + {% include 'partials/header.html' %} + +
+
+
+

Изменение портфолио

+
+ +
{% csrf_token %} +
+

Название {{ form.name.errors.as_text }}

+ + +
+ +
+

Описание{{ form.description.errors.as_text }}

+ +
+ +
+

Специализации

+
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ + + + +
+

Бюджет{{ form.budget.errors.as_text }}

+
+
+ +
+
+ {{ form.currency}} +
+
+
+ +
+

Срок выполнения{{ form.budget.errors.as_text }}

+
+
+ +
+
+ {{ form.term_type }} +
+
+
+ +
+
+
+

Вид строительства

+ {{ form.construction_type}} +
+ +
+

Классификация здания

+ {{ form.building_classification}} +
+ +
+ +
+ + +
+ {% include 'partials/footer.html' %} +
+
+{% endblock %} diff --git a/projects/urls.py b/projects/urls.py index 4f9ccd4..7614498 100644 --- a/projects/urls.py +++ b/projects/urls.py @@ -13,6 +13,8 @@ from .views import ( ProjectComparisonView, ProjectsView, ProjectView, + contractor_portfolio_create, + ContractorPortfolioUpdateView, ) app_name = 'projects' @@ -23,11 +25,13 @@ urlpatterns = [ urls.url(r'^create/$', CustomerProjectCreateView.as_view(), name='customer-project-create'), urls.url(r'^(?P\d+)/$', ProjectView.as_view(), name='detail'), urls.url(r'^(?P\d+)/edit/$', CustomerProjectEditView.as_view(), name='customer-project-edit'), + urls.url(r'^(?P\d+)/trash/$', CustomerProjectTrashView.as_view(), name='customer-project-trash'), urls.url(r'^(?P\d+)/restore/$', CustomerProjectRestoreView.as_view(), name='customer-project-restore'), urls.url(r'^(?P\d+)/delete/$', CustomerProjectDeleteView.as_view(), name='customer-project-delete'), urls.url(r'^(?P\d+)/answer/$', ContractorProjectAnswerView.as_view(), name='contractor-project-answer'), - + urls.url(r'^portfolio/create/$', contractor_portfolio_create, name='contractor-portfolio-create'), + urls.url(r'^portfolio/(?P\d+)/edit/$', ContractorPortfolioUpdateView.as_view(), name='contractor-portfolio-edit'), urls.url(r'^candidate/add/(?P(\d+))/(?P(\d+))/$', add_candidate, name='add-candidate'), urls.url(r'^candidate/comparison/(?P\d+)$', ProjectComparisonView.as_view(), name='comparison'), # urls.url(r'^portfolio/create/$', PortfolioCreateView.as_view(), name='portfolio-create'), diff --git a/projects/views.py b/projects/views.py index 1fecc0f..8f74ddf 100644 --- a/projects/views.py +++ b/projects/views.py @@ -1,12 +1,14 @@ +import json +from pprint import pprint, pformat +import pydash as _ + from django.contrib import messages from django.contrib.auth.mixins import PermissionRequiredMixin, LoginRequiredMixin from django.core.urlresolvers import reverse, reverse_lazy -from django.http import HttpResponseForbidden, HttpResponseRedirect, HttpResponse +from django.http import HttpResponseForbidden, HttpResponseRedirect, HttpResponse, Http404 from django.shortcuts import render, get_object_or_404, redirect -from django.views.generic import ListView, DetailView, CreateView, View, TemplateView, FormView +from django.views.generic import ListView, DetailView, CreateView, View, UpdateView, TemplateView, FormView from django.views.generic.base import ContextMixin -from pprint import pprint, pformat -import pydash as _ from .mixins import LastAccessMixin from .models import Project, ProjectFile, Portfolio, Candidate, Answer, Realty, Order @@ -312,4 +314,25 @@ class OfferOrderView(View): return render(request, self.template_name) +def contractor_portfolio_create(request): + if request.is_ajax(): + form = PortfolioForm(data=request.POST) + if form.is_valid(): + instance = form.save(commit=False) + instance.save() + data = {'status': 'ok'} + else: + data = {'status': 'no', 'form_errors': form.errors} + return HttpResponse(json.dumps(data), content_type='application/json') + else: + raise Http404 + + +class ContractorPortfolioUpdateView(UpdateView): + model = Portfolio + form_class = PortfolioForm + template_name = 'contractor_portfolio_edit.html' + + def get_success_url(self): + return reverse('proje') # import code; code.interact(local=dict(globals(), **locals())) diff --git a/users/templates/contractor_profile.html b/users/templates/contractor_profile.html index 3c3568c..9c643a0 100644 --- a/users/templates/contractor_profile.html +++ b/users/templates/contractor_profile.html @@ -123,7 +123,7 @@
- {% for p in user.portfolio.all %} + {% for p in user.portfolios.all %}

{{ p.name }}

+
+
@@ -431,13 +433,25 @@ }); - $('#portfolio-add-form').on('submit', function(e){ + $('#portfolio-add-form').on('submit', function(e) { e.preventDefault(); var dataSerializer = $(this).serialize(); - alert(dataSerializer); - }); - + $.ajax({ + url: '/projects/portfolio/create/', + method: 'POST', + data: dataSerializer, + dataType: 'json', + success: function (data) { + if (data.status == 'ok') { + location.reload(); + } + }, + error: function (jqXHR, exception) { + console.log(jqXHR.statusCode); + } + }); + }); }); {% endblock %} diff --git a/users/templates/portfolio_create_form.html b/users/templates/portfolio_create_form.html index beb2de8..fc9ba9c 100644 --- a/users/templates/portfolio_create_form.html +++ b/users/templates/portfolio_create_form.html @@ -3,14 +3,14 @@
{% csrf_token %}
-

Название заказа {{ worksell_form.name.errors.as_text }}

- +

Название{{ portfolio_form.name.errors.as_text }}

+
-

Подробно опишите задание {{ worksell_form.description.errors.as_text }}

- +

Описание{{ portfolio_form.description.errors.as_text }}

+
@@ -33,46 +33,55 @@
- +
-

Бюджет{{ worksell_form.budget.errors.as_text }}

+

Бюджет{{ portfolio_form.budget.errors.as_text }}

- {{ worksell_form.budget_type }} + {{ portfolio_form.currency}}
-

Срок выполнения{{ worksell_form.budget.errors.as_text }}

+

Срок выполнения{{ portfolio_form.budget.errors.as_text }}

- {{ worksell_form.term_type }} + {{ portfolio_form.term_type }}
+
-
+

Вид строительства

- {{ worksell_form.construction_type}} + {{ portfolio_form.construction_type}}
-
+

Классификация здания

- {{ worksell_form.building_classification}} + {{ portfolio_form.building_classification}}
+
+ +
+ +
+ +
+ diff --git a/users/templates/worksell_create_form.html b/users/templates/worksell_create_form.html index 7327442..7c710bf 100644 --- a/users/templates/worksell_create_form.html +++ b/users/templates/worksell_create_form.html @@ -61,21 +61,21 @@
-
+

Вид строительства

{{ worksell_form.construction_type}}
-
+

Классификация здания

{{ worksell_form.building_classification}}
-
+
-
+
diff --git a/users/views.py b/users/views.py index 1ce4004..05f48f9 100644 --- a/users/views.py +++ b/users/views.py @@ -9,6 +9,7 @@ from archilance.mixins import BaseMixin from common.utils import get_or_none from specializations.models import Specialization from work_sell.forms import WorkSellForm +from projects.forms import PortfolioForm from .models import User, ContractorFinancialInfo from .mixins import CheckForUserMixin from .forms import UserEditForm, ContractorFinancicalInfoForm @@ -30,12 +31,14 @@ class ContractorListView(ListView): class ContractorProfileDetailView(DetailView): model = User worksell_form_class = WorkSellForm + portfolio_form_class = PortfolioForm template_name = 'contractor_profile.html' context_object_name = 'contractor' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['worksell_form'] = self.worksell_form_class + context['portfolio_form'] = self.portfolio_form_class return context diff --git a/work_sell/filters.py b/work_sell/filters.py new file mode 100644 index 0000000..fd1221b --- /dev/null +++ b/work_sell/filters.py @@ -0,0 +1,12 @@ +import django_filters + +from work_sell.models import WorkSell + +class WorkSellFilter(django_filters.FilterSet): + budget = django_filters.NumberFilter() + budget__gt = django_filters.NumberFilter(name='budget', lookup_expr='gt') + budget__lt = django_filters.NumberFilter(name='budget', lookup_expr='lt') + + class Meta: + model = WorkSell + diff --git a/work_sell/forms.py b/work_sell/forms.py index 86979b8..114c8b1 100644 --- a/work_sell/forms.py +++ b/work_sell/forms.py @@ -13,10 +13,11 @@ class WorkSellForm(forms.ModelForm): widgets = { 'construction_type': forms.Select(attrs={'class':'selectpicker'}), 'building_classification': forms.Select(attrs={'class':'selectpicker'}), + 'currency': forms.Select(attrs={'class':'selectpicker'}), + 'term_type': forms.Select(attrs={'class':'selectpicker'}), } def __init__(self, *args, **kwargs): # self.request = kwargs.pop('request') super().__init__(*args, **kwargs) - self.fields['location'].queryset = Location.objects.root_nodes()[0].get_descendants() diff --git a/work_sell/templates/worksell_delete.html b/work_sell/templates/worksell_delete.html new file mode 100644 index 0000000..4f50a16 --- /dev/null +++ b/work_sell/templates/worksell_delete.html @@ -0,0 +1,10 @@ +{% extends 'partials/base.html' %} + +{% load common_tags %} + +{% block content %} +
{% csrf_token %} +

Вы дейтсвительно хотите удалить? "{{ object }}"?

+ +
+{% endblock %} diff --git a/work_sell/templates/worksell_detail.html b/work_sell/templates/worksell_detail.html index 63378ab..a3ca0dd 100644 --- a/work_sell/templates/worksell_detail.html +++ b/work_sell/templates/worksell_detail.html @@ -2,87 +2,7 @@ {% load staticfiles %} {% load thumbnail %} {% block content %} - - + {% include 'partials/header.html' %}
@@ -97,24 +17,40 @@ + + +

Описание:

diff --git a/work_sell/templates/worksell_edit.html b/work_sell/templates/worksell_edit.html index 8a52a84..9592bc5 100644 --- a/work_sell/templates/worksell_edit.html +++ b/work_sell/templates/worksell_edit.html @@ -11,11 +11,11 @@

Изменение готового проекта

-
{% csrf_token %} + {% csrf_token %}

Название заказа {{ form.name.errors.as_text }}

- + +
@@ -63,7 +63,7 @@

Срок выполнения{{ form.budget.errors.as_text }}

- +
{{ form.term_type }} @@ -83,14 +83,9 @@ {{ form.building_classification}}
-
- -
-
- diff --git a/work_sell/templates/worksells_list.html b/work_sell/templates/worksells_list.html index b3cf2f9..c5bcd1a 100644 --- a/work_sell/templates/worksells_list.html +++ b/work_sell/templates/worksells_list.html @@ -9,6 +9,7 @@

Работы на продажу

+
diff --git a/work_sell/urls.py b/work_sell/urls.py index a560133..c755e47 100644 --- a/work_sell/urls.py +++ b/work_sell/urls.py @@ -5,6 +5,7 @@ from .views import ( WorkSellDetail, WorkSellCreateView, WorkSellUpdateView, + WorkSellDeleteView, work_sell_create, ) @@ -13,7 +14,8 @@ app_name = 'work_sell' urlpatterns = [ urls.url(r'^$', WorkSellsView.as_view(), name='list'), urls.url(r'^create/$', WorkSellCreateView.as_view(), name='create'), - urls.url(r'^(?P\d+)/edit/$', WorkSellUpdateView.as_view(), name='edit'), + urls.url(r'^(?P\d+)/edit/$',WorkSellUpdateView.as_view(), name='edit'), + urls.url(r'^(?P\d+)/delete/$',WorkSellDeleteView.as_view(), name='delete'), urls.url(r'^test/$', work_sell_create, name='test'), urls.url(r'^(?P\d+)/$', WorkSellDetail.as_view(), name='detail'), ] diff --git a/work_sell/views.py b/work_sell/views.py index 63093ae..7909a52 100644 --- a/work_sell/views.py +++ b/work_sell/views.py @@ -4,15 +4,31 @@ from django.core.urlresolvers import reverse from django.http import JsonResponse, HttpResponse from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView, TemplateView +from projects.models import BuildingClassfication, ConstructionType from .models import WorkSell from .forms import WorkSellForm - class WorkSellsView(ListView): model = WorkSell template_name = 'worksells_list.html' paginate_by = 20 + def get_form_kwargs(self, **kwargs): + kwargs = super().get_form_kwargs + + def get_queryset(self, **kwargs): + qs = WorkSell.objects.all() + # if self.request.GET: + # budget_from = self.request.GET + # pass + return qs + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['building_classifications'] = BuildingClassfication.objects.all() + context['construction_types'] = ConstructionType.objects.all() + return context + class WorkSellDetail(DetailView): model = WorkSell @@ -34,7 +50,6 @@ def work_sell_create(request): else: data = {'status': 'no', 'form_errors': form.errors} return HttpResponse(json.dumps(data), content_type='application/json') - return HttpResponse("HEllo") class WorkSellCreateView(CreateView): @@ -52,8 +67,12 @@ class WorkSellUpdateView(UpdateView): return reverse('work_sell:list') -class WorkSellDeleteView(CreateView): +class WorkSellDeleteView(DeleteView): model = WorkSell + template_name = 'worksell_delete.html' + + def get_success_url(self): + return reverse('work_sell:list') class JSONResponseMixin(object):