From 5b2628fa002db791dc72fb487d822a0e4fb45131 Mon Sep 17 00:00:00 2001 From: ArturBaybulatov Date: Wed, 7 Sep 2016 17:04:33 +0300 Subject: [PATCH] Customer order/project offer functionality --- assets/index.js | 28 ++++ chat/views.py | 2 +- projects/forms.py | 6 +- .../migrations/0027_auto_20160907_1658.py | 22 ++++ projects/models.py | 2 +- projects/templates/chattest.html | 2 +- projects/templates/project_detail.html | 2 +- projects/urls.py | 8 +- projects/views.py | 8 +- templates/test.html | 8 +- users/forms.py | 2 +- users/migrations/0016_remove_team_avatar.py | 19 +++ users/models.py | 1 - users/serializers.py | 2 - users/templates/contractor_filter.html | 120 ++++++++++++++---- users/templates/contractor_office.html | 2 +- .../partials/modals/add_team_member.html | 4 +- .../partials/modals/project_selection.html | 19 +++ users/views.py | 8 +- 19 files changed, 211 insertions(+), 54 deletions(-) create mode 100644 projects/migrations/0027_auto_20160907_1658.py create mode 100644 users/migrations/0016_remove_team_avatar.py create mode 100644 users/templates/partials/modals/project_selection.html diff --git a/assets/index.js b/assets/index.js index 12a62af..1aea79f 100644 --- a/assets/index.js +++ b/assets/index.js @@ -229,6 +229,34 @@ function initContractorSelect($select) { +// Order offer project select --------------------------------------------- + + +var projectSelectOptions = { + language: 'ru', + placeholder: 'Выберите проект', // Required by `allowClear` + allowClear: true, +} + +function initProjectSelect($select, customerId) { + return $.ajax({url: '/api/projects/?customer=' + customerId, method: 'GET', dataType: 'json'}) + .then(function(res) { + var projects = res.results + + $select.select2(_.merge(projectSelectOptions, { + data: _.map(function(project) { + return { + id: project.id, + text: project.name, + origItem: project, + } + }, projects), + })) + }) +} + + + diff --git a/chat/views.py b/chat/views.py index 3b93839..cef04f0 100644 --- a/chat/views.py +++ b/chat/views.py @@ -55,7 +55,7 @@ class ChatUserView(LoginRequiredMixin, View): contacts_users = User.objects.filter(pk__in=users_ids) chat_messages = Message.objects.filter(Q(sender=request.user.pk) | Q(recipent=request.user.pk)) - orders = request.user.projects.select_related('order').exclude(order__contractor__isnull=True, order__team__isnull=True) + orders = request.user.customer_projects.select_related('order').exclude(order__contractor__isnull=True, order__team__isnull=True) transaction = Transaction.objects.get_or_create(customer=request.user, type='reservation', complete=False) self.template_name = 'chat_customer.html' return render(request, self.template_name, {'contacts_users': contacts_users, diff --git a/projects/forms.py b/projects/forms.py index 01f57f1..e16d95c 100644 --- a/projects/forms.py +++ b/projects/forms.py @@ -276,7 +276,7 @@ class CustomerProjectTrashForm(forms.Form): self.req = kwargs.pop('req') super().__init__(*args, **kwargs) - self.fields['pk'].queryset = self.req.user.projects.filter(state='active') + self.fields['pk'].queryset = self.req.user.customer_projects.filter(state='active') class ContractorPortfolioTrashForm(forms.Form): @@ -296,7 +296,7 @@ class CustomerProjectRestoreForm(forms.Form): self.req = kwargs.pop('req') super().__init__(*args, **kwargs) - self.fields['pk'].queryset = self.req.user.projects.filter(state='trashed') + self.fields['pk'].queryset = self.req.user.customer_projects.filter(state='trashed') class CustomerProjectDeleteForm(forms.Form): @@ -306,7 +306,7 @@ class CustomerProjectDeleteForm(forms.Form): self.req = kwargs.pop('req') super().__init__(*args, **kwargs) - self.fields['pk'].queryset = self.req.user.projects.filter(Q(state='active') | Q(state='trashed')) + self.fields['pk'].queryset = self.req.user.customer_projects.filter(Q(state='active') | Q(state='trashed')) # import code; code.interact(local=dict(globals(), **locals())) diff --git a/projects/migrations/0027_auto_20160907_1658.py b/projects/migrations/0027_auto_20160907_1658.py new file mode 100644 index 0000000..97a9673 --- /dev/null +++ b/projects/migrations/0027_auto_20160907_1658.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-09-07 13:58 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('projects', '0026_auto_20160906_1621'), + ] + + operations = [ + migrations.AlterField( + model_name='project', + name='customer', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='customer_projects', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/projects/models.py b/projects/models.py index 0c0b805..ccf519c 100644 --- a/projects/models.py +++ b/projects/models.py @@ -91,7 +91,7 @@ class Project(models.Model, HitCountMixin): created = models.DateTimeField(default=timezone.now) cro = models.BooleanField(default=False) currency = models.CharField(max_length=20, default='rur', choices=CURRENCIES) - customer = models.ForeignKey(User, related_name='projects') # Related name should've been "customer_projects" + customer = models.ForeignKey(User, related_name='customer_projects') deal_type = models.CharField(max_length=20, default='secure_deal', choices=DEAL_TYPES) name = models.CharField(max_length=255) price_and_term_required = models.BooleanField(default=False) diff --git a/projects/templates/chattest.html b/projects/templates/chattest.html index f0261f3..2ab5cc3 100644 --- a/projects/templates/chattest.html +++ b/projects/templates/chattest.html @@ -3,7 +3,7 @@

Мои проекты

- {% for proj in request.user.projects.all %} + {% for proj in request.user.customer_projects.all %}

{{ proj }}

{{ proj.order }}
{% endfor %} diff --git a/projects/templates/project_detail.html b/projects/templates/project_detail.html index da3f7cd..7904f1c 100644 --- a/projects/templates/project_detail.html +++ b/projects/templates/project_detail.html @@ -476,7 +476,7 @@ - {% elif request.user.is_customer and project in request.user.projects.all %} + {% elif request.user.is_customer and project in request.user.customer_projects.all %}

Исполнители

diff --git a/projects/urls.py b/projects/urls.py index bbf00a8..e220158 100644 --- a/projects/urls.py +++ b/projects/urls.py @@ -3,25 +3,25 @@ from django.views.generic import TemplateView from .views import ( add_candidate, + ArbitrationCreateView, CandidateDeleteView, contractor_portfolio_create, ContractorAnswerArchiveView, ContractorPortfolioTrashView, ContractorPortfolioUpdateView, + CustomerOfferOrderView, CustomerProjectCreateView, CustomerProjectDeleteView, CustomerProjectEditView, CustomerProjectRestoreView, CustomerProjectTrashView, - OfferOrderView, + PortfolioDetail, ProjectAnswerCreateMessageView, ProjectComparisonView, ProjectDetailWithAnswerView, ProjectFilterView, RejectProjectAnswerView, sort_candidates, - PortfolioDetail, - ArbitrationCreateView, ) app_name = 'projects' @@ -51,7 +51,7 @@ urlpatterns = [ urls.url(r'^candidate/comparison/sort/$', sort_candidates, name='comparison-sort'), urls.url(r'^candidate/comparison/(?P\d+)/$', ProjectComparisonView.as_view(), name='comparison'), - urls.url(r'^offerorder/(?P(\d+))/(?P(\d+))/$', OfferOrderView.as_view(), name='customer-offer-order'), + urls.url(r'^customer-offer-order/(?P(\d+))/(?P(\d+))/$', CustomerOfferOrderView.as_view(), name='customer-offer-order'), # urls.url(r'^portfolio/create/$', PortfolioCreateView.as_view(), name='portfolio-create'), ] diff --git a/projects/views.py b/projects/views.py index d2daa8e..04fbfac 100644 --- a/projects/views.py +++ b/projects/views.py @@ -215,7 +215,7 @@ class RejectProjectAnswerView(BaseMixin, View): if not answer: raise Http404 elif request.user.is_customer(): - project = get_object_or_404(request.user.projects, answers__pk=kwargs.get('pk')) + project = get_object_or_404(request.user.customer_projects, answers__pk=kwargs.get('pk')) answer = get_object_or_404(project.answers, pk=kwargs.get('pk')) answer.rejected = True @@ -435,7 +435,7 @@ class CustomerProjectEditView(BaseMixin, View): raise PermissionDenied def get(self, request, *args, **kwargs): - project = get_object_or_404(request.user.projects, pk=kwargs.get('pk')) + project = get_object_or_404(request.user.customer_projects, pk=kwargs.get('pk')) form = self.form_class(instance=project, request=request) realty = project.realty @@ -451,7 +451,7 @@ class CustomerProjectEditView(BaseMixin, View): return render(request, self.template_name, context) def post(self, request, *args, **kwargs): - project = get_object_or_404(request.user.projects, pk=kwargs.get('pk')) + project = get_object_or_404(request.user.customer_projects, pk=kwargs.get('pk')) form = self.form_class(request.POST, request.FILES, request=request, instance=project) form.is_valid() @@ -660,7 +660,7 @@ def sort_candidates(request): return HttpResponse(json.dumps(data), content_type='application/json') -class OfferOrderView(View): +class CustomerOfferOrderView(View): template_name = 'chattest.html' def post(self, request, *args, **kwargs): diff --git a/templates/test.html b/templates/test.html index b09ae45..cdd7dc4 100644 --- a/templates/test.html +++ b/templates/test.html @@ -15,7 +15,13 @@
- {{ request.get_host }}{{ request.get_full_path }} +{# {% url 'projects:customer-offer-order-answerless' contractor_id=11 project_id=485 as url %}#} +{# #} +{#
#} +{# {% csrf_token %}#} +{# #} +{# #} +{#
#}
diff --git a/users/forms.py b/users/forms.py index 725310b..d148a40 100644 --- a/users/forms.py +++ b/users/forms.py @@ -223,7 +223,7 @@ class CustomerProfileProjectRealtyForm(forms.Form): super().__init__(*args, **kwargs) - realties = _.uniq(tuple(p.realty for p in self.customer.projects.all())) + realties = _.uniq(tuple(p.realty for p in self.customer.customer_projects.all())) self.fields['realty'] = forms.ChoiceField( widget=forms.Select(attrs={ diff --git a/users/migrations/0016_remove_team_avatar.py b/users/migrations/0016_remove_team_avatar.py new file mode 100644 index 0000000..979f0c4 --- /dev/null +++ b/users/migrations/0016_remove_team_avatar.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-09-07 13:58 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0015_user_phone2'), + ] + + operations = [ + migrations.RemoveField( + model_name='team', + name='avatar', + ), + ] diff --git a/users/models.py b/users/models.py index 00a9b76..2892ae1 100644 --- a/users/models.py +++ b/users/models.py @@ -232,7 +232,6 @@ class User(AbstractBaseUser, PermissionsMixin): class Team(models.Model): answers = GenericRelation('projects.Answer', related_query_name='teams') - avatar = models.ImageField(upload_to='teams/avatars/', blank=True) # TODO: Unused field? created = models.DateTimeField(default=timezone.now) name = models.CharField(max_length=255) owner = models.OneToOneField(User, related_name='team', blank=True, null=True) diff --git a/users/serializers.py b/users/serializers.py index c618117..1bfef6e 100755 --- a/users/serializers.py +++ b/users/serializers.py @@ -86,7 +86,6 @@ class UserSerializer(ModelSerializer): class TeamSerializer(ModelSerializer): _type = SerializerMethodField() # Distinguish when used with generic serializers # answers = AnswerSerializer(many=True) - avatar = ImageField() contractors = UserSerializer(many=True) owner = UserSerializer() specializations = SpecializationSerializer(many=True) @@ -97,7 +96,6 @@ class TeamSerializer(ModelSerializer): fields = ( '_type', # 'answers', - 'avatar', 'contractors', 'created', 'id', diff --git a/users/templates/contractor_filter.html b/users/templates/contractor_filter.html index affc691..e209bbe 100644 --- a/users/templates/contractor_filter.html +++ b/users/templates/contractor_filter.html @@ -5,6 +5,7 @@ {% load thumbnail %} {% block content %} + {% include 'partials/modals/project_selection.html' %} {% include 'partials/header.html' %} @@ -172,9 +173,17 @@ {% with team=obj %}
-
- execitor-image -
+ +
+ {% if team.owner.avatar %} + {% thumbnail team.owner.avatar "126x125" crop="center" as avatar %} + profile-image + {% endthumbnail %} + {% else %} + profile-image + {% endif %} +
+

{{ team.name }} {# TODO #}

@@ -186,14 +195,16 @@
  • - + смотреть профиль
  • - - предложить проект - + {% if request.user.is_customer %} + + предложить проект + + {% endif %}
  • {# TODO #} @@ -286,20 +297,19 @@ {% with contractor=obj %}
    - +
    - - {% if contractor.avatar %} - {% thumbnail contractor.avatar "126x125" crop="center" as im %} - profile-image - {% endthumbnail %} - {% else %} - profile-image - {% endif %} + {% if contractor.avatar %} + {% thumbnail contractor.avatar "126x125" crop="center" as avatar %} + profile-image + {% endthumbnail %} + {% else %} + profile-image + {% endif %}

    - {{ contractor.get_full_name }} [{{ contractor.username }}] + {{ contractor.get_full_name }} [{{ contractor.username }}]

    Свободен
    @@ -309,20 +319,27 @@
    • - + смотреть профиль
    • + {% if request.user.is_customer %} -
    • - - предложить проект - -
    • +
    • + + предложить проект + +
    • {% endif %} - +
    • - + написать сообщение
    • @@ -336,8 +353,8 @@
      - {% ratings_widget obj.pk 'restList2' %} - {% if obj.cro %} + {% ratings_widget contractor.pk 'restList2' %} + {% if contractor.cro %}

      Есть допуск СРО

      @@ -392,3 +409,52 @@
      {% endblock %} + +{% block js_block %} + +{% endblock %} diff --git a/users/templates/contractor_office.html b/users/templates/contractor_office.html index 716c0fa..bc3e9d5 100644 --- a/users/templates/contractor_office.html +++ b/users/templates/contractor_office.html @@ -334,7 +334,7 @@ {% if request.user.has_team %} - var $contractorSelect = window.$contractorSelect = $('.-contractor-select').first() + var $contractorSelect = $('.-contractor-select').first() var $addTeamMemberModal = $('#addTeamMemberModal') {# var addTeamMemberUrl = '/users/add-team-member/%id%/'#} diff --git a/users/templates/partials/modals/add_team_member.html b/users/templates/partials/modals/add_team_member.html index f106f37..ef86cee 100644 --- a/users/templates/partials/modals/add_team_member.html +++ b/users/templates/partials/modals/add_team_member.html @@ -3,7 +3,7 @@ diff --git a/users/templates/partials/modals/project_selection.html b/users/templates/partials/modals/project_selection.html new file mode 100644 index 0000000..f31e836 --- /dev/null +++ b/users/templates/partials/modals/project_selection.html @@ -0,0 +1,19 @@ + diff --git a/users/views.py b/users/views.py index d6d2d3e..9406152 100644 --- a/users/views.py +++ b/users/views.py @@ -527,8 +527,8 @@ class CustomerProfileOpenProjectsView(BaseMixin, View): context = self.get_context_data(**_.merge({}, request.GET, kwargs)) customer = get_object_or_404(User.customer_objects, pk=kwargs.get('pk')) form = self.form_class(request.GET, request=request, customer=customer) - projects = customer.projects.filter(state='active') - trashed_projects = customer.projects.filter(state='trashed') + projects = customer.customer_projects.filter(state='active') + trashed_projects = customer.customer_projects.filter(state='trashed') if form.is_valid(): realty = form.cleaned_data.get('realty') @@ -577,8 +577,8 @@ class CustomerProfileTrashedProjectsView(BaseMixin, View): context = self.get_context_data(**_.merge({}, request.GET, kwargs)) customer = get_object_or_404(User.customer_objects, pk=kwargs.get('pk')) form = self.form_class(request.GET, request=request, customer=customer) - projects = customer.projects.filter(state='trashed') - open_projects = customer.projects.filter(state='active') + projects = customer.customer_projects.filter(state='trashed') + open_projects = customer.customer_projects.filter(state='active') if form.is_valid(): realty = form.cleaned_data.get('realty')