Customer order/project offer functionality

remotes/origin/PR-39
ArturBaybulatov 9 years ago
parent e8c52ad55a
commit 5b2628fa00
  1. 28
      assets/index.js
  2. 2
      chat/views.py
  3. 6
      projects/forms.py
  4. 22
      projects/migrations/0027_auto_20160907_1658.py
  5. 2
      projects/models.py
  6. 2
      projects/templates/chattest.html
  7. 2
      projects/templates/project_detail.html
  8. 8
      projects/urls.py
  9. 8
      projects/views.py
  10. 8
      templates/test.html
  11. 2
      users/forms.py
  12. 19
      users/migrations/0016_remove_team_avatar.py
  13. 1
      users/models.py
  14. 2
      users/serializers.py
  15. 96
      users/templates/contractor_filter.html
  16. 2
      users/templates/contractor_office.html
  17. 4
      users/templates/partials/modals/add_team_member.html
  18. 19
      users/templates/partials/modals/project_selection.html
  19. 8
      users/views.py

@ -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),
}))
})
}

@ -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,

@ -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()))

@ -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),
),
]

@ -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)

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

@ -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 %}
<div class="exBigBlock disTab">
<div class="col-lg-12">
<p class="titleEx">Исполнители</p>

@ -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<pk>\d+)/$', ProjectComparisonView.as_view(), name='comparison'),
urls.url(r'^offerorder/(?P<answer_id>(\d+))/(?P<project_id>(\d+))/$', OfferOrderView.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'^portfolio/create/$', PortfolioCreateView.as_view(), name='portfolio-create'),
]

@ -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):

@ -15,7 +15,13 @@
<div class='container-fluid'>
<div class='row'>
<div class='col-xs-12' style='margin-top: 15px'>
{{ request.get_host }}{{ request.get_full_path }}
{# {% url 'projects:customer-offer-order-answerless' contractor_id=11 project_id=485 as url %}#}
{# #}
{# <form action="{{ url }}" method="POST" novalidate>#}
{# {% csrf_token %}#}
{# #}
{# <button type="submit">{{ url }}</button>#}
{# </form>#}
</div>
</div>
</div>

@ -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={

@ -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',
),
]

@ -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)

@ -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',

@ -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 %}
<div class="executorBlock clearfix">
<div class="col-lg-4">
<a href="#" class="aLinkExe"><div class="imgExecutor">
<img src="img/profile.jpg" alt="execitor-image">
</div></a>
<a href="#" class="aLinkExe">
<div class="imgExecutor">
{% if team.owner.avatar %}
{% thumbnail team.owner.avatar "126x125" crop="center" as avatar %}
<img src="{{ avatar.url }}" alt="profile-image">
{% endthumbnail %}
{% else %}
<img src="{% static 'img/profile.jpg' %}" alt="profile-image">
{% endif %}
</div>
</a>
<p class="nameExecutor">
<a href="">{{ team.name }}</a> {# TODO #}
</p>
@ -186,14 +195,16 @@
<div class="col-lg-2">
<ul class="listExecutor">
<li>
<a href="javascript:void(0)">
<a href="{% url 'users:team-profile' pk=team.pk %}">
смотреть профиль
</a>
</li>
<li>
<a href="javascript:void(0)">
{% if request.user.is_customer %}
<a href="#" onclick="return false" class="-contractor-offer-order" data-contractor-id="{{ team.owner.pk }}" data-is-team-offer="true">
предложить проект
</a>
{% endif %}
</li>
<li>
{# TODO #}
@ -286,12 +297,11 @@
{% with contractor=obj %}
<div class="executorBlock clearfix">
<div class="col-lg-4">
<a href="{% url 'users:contractor-profile' pk=obj.pk %}" class="aLinkExe">
<a href="{% url 'users:contractor-profile' pk=contractor.pk %}" class="aLinkExe">
<div class="imgExecutor">
{% if contractor.avatar %}
{% thumbnail contractor.avatar "126x125" crop="center" as im %}
<img src="{{ im.url }}" alt="profile-image">
{% thumbnail contractor.avatar "126x125" crop="center" as avatar %}
<img src="{{ avatar.url }}" alt="profile-image">
{% endthumbnail %}
{% else %}
<img src="{% static 'img/profile.jpg' %}" alt="profile-image">
@ -299,7 +309,7 @@
</div>
</a>
<p class="nameExecutor">
<a href="{% url 'users:contractor-profile' pk=obj.pk %}">{{ contractor.get_full_name }} [{{ contractor.username }}]</a>
<a href="{% url 'users:contractor-profile' pk=contractor.pk %}">{{ contractor.get_full_name }} [{{ contractor.username }}]</a>
</p>
<p class="navv2">На сайте 8 лет и 3 месяца</p>
<div class="statusUser">Свободен</div>
@ -309,20 +319,27 @@
<div class="col-lg-2">
<ul class="listExecutor">
<li>
<a href="{% url 'users:contractor-profile' pk=obj.pk %}">
<a href="{% url 'users:contractor-profile' pk=contractor.pk %}">
смотреть профиль
</a>
</li>
{% if request.user.is_customer %}
<li>
<a href="javascript:void(0)">
<a
href="#"
onclick="return false"
class="-contractor-offer-order"
data-contractor-id="{{ contractor.pk }}"
data-toggle="modal"
data-target="#projectSelectionModal">
предложить проект
</a>
</li>
{% endif %}
<li>
<a href="{% url 'chat:chat-user' %}?user_id={{ obj.pk }}">
<a href="{% url 'chat:chat-user' %}?user_id={{ contractor.pk }}">
написать сообщение
</a>
</li>
@ -336,8 +353,8 @@
<div class="col-lg-3 retts">
{% ratings_widget obj.pk 'restList2' %}
{% if obj.cro %}
{% ratings_widget contractor.pk 'restList2' %}
{% if contractor.cro %}
<div class="sroUser sroExecutor">
<div class="iconSRO"></div>
<p>Есть допуск СРО</p>
@ -392,3 +409,52 @@
</div>
</div>
{% endblock %}
{% block js_block %}
<script>
{% if request.user.is_customer %}
var customerId = {{ request.user.pk }}
var $projectSelectionModal = $('#projectSelectionModal')
$projectSelectionModal.on('shown.bs.modal', function($evt) {
var $that = $(this)
var $modalOpenButton = $($evt.relatedTarget)
var $projectSelect = $that.find('.-project-select').first()
$that.data('modalOpenButton', $modalOpenButton)
initProjectSelect($projectSelect, customerId)
})
$projectSelectionModal.find('.-action-button').first().on('click', function($evt) {
var $projectSelect = $projectSelectionModal.find('.-project-select').first()
var $modalOpenButton = $projectSelectionModal.data('modalOpenButton')
var isTeamOffer = $modalOpenButton.data('isTeamOffer')
var project = $projectSelect.select2('data')
var contractorId = $modalOpenButton.data('contractorId')
$projectSelectionModal.modal('hide')
$projectSelect.select2('destroy')
if (isTeamOffer)
var msg = 'Вашей команде предлагается проект ' + project.id
else
var msg = 'Вам предлагается проект ' + project.id
socketMain.add_message({
format_type: 'add_message_contact',
data: {
sender_id: customerId,
recipent_id: contractorId,
chat_message: msg,
},
})
$.jGrowl('Предложение успешно отправлено')
$modalOpenButton.fadeOut()
})
{% endif %}
</script>
{% endblock %}

@ -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%/'#}

@ -3,7 +3,7 @@
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span>&times;</span></button>
<h4 class="modal-title" id="myModalLabel">Modal title</h4>
<h4 class="modal-title">Выбор пользователя</h4>
</div>
<div class="modal-body">
@ -12,7 +12,7 @@
<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>
<button type="button" class="btn btn-primary -action-button">ОК</button>
</div>
</div>
</div>

@ -0,0 +1,19 @@
<div class="modal fade" id="projectSelectionModal" tabindex="-1">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span>&times;</span></button>
<h4 class="modal-title">Выбор проекта</h4>
</div>
<div class="modal-body">
<input type="hidden" class="-project-select" style="width: 100%">
</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>

@ -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')

Loading…
Cancel
Save