From 8ef7e8f1336d110d92cb9f0d29965eb8b603bb68 Mon Sep 17 00:00:00 2001 From: Mukhtar Date: Tue, 23 Aug 2016 16:30:27 +0300 Subject: [PATCH 1/3] #ARC-16 Fixes --- assets/js/chat.js | 16 ++++++--- chat/chat.py | 25 ++++++++++---- chat/serializers.py | 2 ++ chat/templates/chat_customer.html | 23 ++++--------- projects/templates/project_detail.html | 45 +++++++------------------- projects/urls.py | 2 +- projects/views.py | 9 ++++-- users/mixins.py | 7 ++-- wallets/forms.py | 1 + wallets/signals.py | 2 +- wallets/templates/score-detail.html | 17 +++++----- wallets/views.py | 13 ++++++-- 12 files changed, 82 insertions(+), 80 deletions(-) diff --git a/assets/js/chat.js b/assets/js/chat.js index 93c8c3b..1375c1f 100644 --- a/assets/js/chat.js +++ b/assets/js/chat.js @@ -1,6 +1,6 @@ var SocketHandler = function () { domain = domain.replace(':' + port, ''); - var url = 'ws://' + domain + '/chat/' + userId + '/'; + var url = 'ws://' + domain + ':8888/chat/' + userId + '/'; var sock = new WebSocket(url); var intervalId; sock.onopen = function () { @@ -23,9 +23,17 @@ var SocketHandler = function () { alert('approve stages'); } if (inbox) { - inbox.innerHTML += '
' + - '

ВЫ

Сейчас
' + - '

' + message.msg + '

'; + var textMessage = message.msg; + var classMessage = 'youChat'; + var senderName = 'Вы'; + var timeMessage = message.msg_time; + if (message.sender_id != userId){ + senderName = message.sender_name; + classMessage = ''; + } + inbox.innerHTML += '
' + + '

'+ senderName +'

' + timeMessage + '
' + + '

' + textMessage + '

'; } }; diff --git a/chat/chat.py b/chat/chat.py index c4143ab..84897e0 100644 --- a/chat/chat.py +++ b/chat/chat.py @@ -1,4 +1,4 @@ -import os.path +import html from tornado import gen, web, websocket, escape, options from tornado.ioloop import IOLoop from tornado.httpserver import HTTPServer @@ -33,7 +33,6 @@ class ChatHandler(websocket.WebSocketHandler): if 'dummy' in parsed: return - print(parsed['format_type']) if 'approve_stages' in parsed['format_type']: self.approve_stages(parsed) else: @@ -60,6 +59,8 @@ class ChatHandler(websocket.WebSocketHandler): order_id = message_data['data'].get('order_id', None) team_id = message_data['data'].get('team_id', None) message = message_data['data'].get('chat_message', None) + message = html.escape(message) + message = message.replace('\n', '
') answer_type = message_data['format_type'] private_type = 'true' if not order_id and not team_id else 'false' @@ -74,14 +75,26 @@ class ChatHandler(websocket.WebSocketHandler): insert_sql = "INSERT INTO chat_message (id,text,created, sender_id,recipent_id," \ " private_type,team_id, order_id,is_delete,is_new) " \ - "VALUES (DEFAULT,'{0}',NOW(),{1},{2},{3},{4},{5},{6},{7})".\ + "VALUES (DEFAULT,'{0}',NOW(),{1},{2},{3},{4},{5},{6},{7}) RETURNING id".\ format(message, sender_id, recipent_id, private_type, team_value,order_value, is_delete, is_new) - yield self.db.execute(insert_sql) - waiters = tuple(w for c, w in self.waiters if c == recipent_id or c == sender_id) + cursor_list = yield dict(cursor=self.db.execute(insert_sql)) + cursor = cursor_list.get('cursor') + result = cursor.fetchone() + message_id = result[0] + select_last_sql = "SELECT chat_message.id, chat_message.text, chat_message.created, chat_message.sender_id," \ + "users_user.id, users_user.username FROM chat_message" \ + " INNER JOIN users_user ON (chat_message.sender_id = users_user.id)" \ + " WHERE chat_message.id = {0}".format(message_id) + + cursor_msg = yield self.db.execute(select_last_sql) + msg_data = cursor_msg.fetchone() + sender_name = msg_data[5] + msg_time = msg_data[2].strftime("%Y-%m-%d %H:%M:%S") + waiters = tuple(w for c, w in self.waiters if c == recipent_id or c == sender_id) for waiter in waiters: - waiter.write_message({'msg': message, 'answer_type': answer_type}) + waiter.write_message({'msg': message, 'msg_time': msg_time, 'sender_id': sender_id, 'sender_name': sender_name, 'answer_type': answer_type}) def check_origin(self, origin): return True diff --git a/chat/serializers.py b/chat/serializers.py index cd43c8d..e4d8467 100644 --- a/chat/serializers.py +++ b/chat/serializers.py @@ -1,3 +1,4 @@ +from rest_framework import serializers from rest_framework.serializers import ModelSerializer from .models import Message, Notes, Documents @@ -20,6 +21,7 @@ class DocumentsSerializer(ModelSerializer): class MessageSerializer(ModelSerializer): sender = UserSerializer() recipent = UserSerializer() + created = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S") class Meta: model = Message diff --git a/chat/templates/chat_customer.html b/chat/templates/chat_customer.html index 12c4df7..a3db522 100644 --- a/chat/templates/chat_customer.html +++ b/chat/templates/chat_customer.html @@ -72,7 +72,7 @@ - отправить + отправить @@ -108,7 +108,7 @@

Испонитель: {{ order.order.contractor.get_full_name }}

- + Полное описание заказа @@ -134,7 +134,7 @@ Не более 10 файлов с общим объемом 500мб - отправить + отправить @@ -448,18 +448,7 @@ } ii--; }); - - } -{# #} -{# var updateFormStages = $(".update-stages-form");#} -{# var limitCount = countStage + 1;#} -{# for (var i = 2; i < limitCount; i++) {#} -{# var stageCopy = $("#stage1").clone().attr("id", "stage" + i).addClass("stages_form");#} -{# stageCopy.find('.stage-span-id').html(i);#} -{# $("#stage1").after(stageCopy);#} -{##} -{# }#} }); $('.order-block').on('click', function () { @@ -545,7 +534,8 @@ }); - $('#contact-chat-add-message').on('click', function () { + $('#contact-chat-add-message').on('click', function (e) { + e.preventDefault(); var chatMessage = $("#chat").val(); var recipentId = $("#recipentId").val(); var senderId = $("#senderId").val(); @@ -566,7 +556,8 @@ alert('add review'); }); - $('#order-chat-add-message').on('click', function () { + $('#order-chat-add-message').on('click', function (e) { + e.preventDefault(); var chatMessage = $("#chat-order-add #chat").val(); var recipentId = $("#chat-order-add #recipentId").val(); var senderId = $("#chat-order-add #senderId").val(); diff --git a/projects/templates/project_detail.html b/projects/templates/project_detail.html index e4d6105..2dcd2a3 100644 --- a/projects/templates/project_detail.html +++ b/projects/templates/project_detail.html @@ -36,21 +36,8 @@ {{ project.customer.get_full_name }} [{{ project.customer.username }}]

- - {% if not request.user.is_contractor %} - - {% endif %} - - {% if request.user.is_contractor %} +
- {% endif %} - -
- {% specialization_widget contractor.pk %} -{#
#} -{#

#} -{# Специализации:#} -{#

#} -{#
#} -
+
- {% if project.cro %}
@@ -554,10 +527,14 @@ Кандидат - - + + +
+ {% csrf_token %} + предложить проект - + +
{% csrf_token %} diff --git a/projects/urls.py b/projects/urls.py index 9044f0e..cf359b9 100644 --- a/projects/urls.py +++ b/projects/urls.py @@ -49,7 +49,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='offer-order'), + urls.url(r'^offerorder/(?P(\d+))/(?P(\d+))/$', OfferOrderView.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 263309f..77bbc1b 100644 --- a/projects/views.py +++ b/projects/views.py @@ -1,4 +1,5 @@ from django.conf import settings +from django.core.exceptions import PermissionDenied from django.contrib import messages from django.contrib.auth.mixins import PermissionRequiredMixin, LoginRequiredMixin from django.core.files.base import ContentFile @@ -346,7 +347,7 @@ class CustomerProjectCreateView(BaseMixin, View): if request.user.is_authenticated() and request.user.is_customer(): return super().dispatch(request, *args, **kwargs) else: - return HttpResponseForbidden() + raise PermissionDenied def get(self, request, *args, **kwargs): form = self.form_class(request=request) @@ -622,6 +623,7 @@ class CandidateDeleteView(DeleteView): def get(self, *args, **kwargs): return self.post(*args, **kwargs) + def sort_candidates(request): if request.is_ajax(): items = request.POST.getlist('items[]') @@ -641,8 +643,9 @@ def sort_candidates(request): class OfferOrderView(View): template_name = 'chattest.html' - def get(self, request, *args, **kwargs): - return render(request, self.template_name) + def post(self,request, *args, **kwargs): + print("Add chat") + return HttpResponseRedirect(reverse('chat:chat-user')) def contractor_portfolio_create(request): diff --git a/users/mixins.py b/users/mixins.py index a1bb811..b1e16bd 100644 --- a/users/mixins.py +++ b/users/mixins.py @@ -1,5 +1,4 @@ -from django.http import HttpResponseForbidden -from django.contrib import messages +from django.core.exceptions import PermissionDenied class CheckForUserMixin(object): @@ -8,9 +7,9 @@ class CheckForUserMixin(object): pk = kwargs.get('pk') if pk: if request.user.pk != int(pk): - return HttpResponseForbidden('403 Forbidden') + raise PermissionDenied else: - return HttpResponseForbidden('403 Forbidden') + raise PermissionDenied return super().dispatch(request, *args, **kwargs) diff --git a/wallets/forms.py b/wallets/forms.py index bdfd997..d8afe1a 100644 --- a/wallets/forms.py +++ b/wallets/forms.py @@ -43,6 +43,7 @@ class TmpPaymentAvisoForm(forms.Form): md5 = forms.CharField() shopId = forms.IntegerField() invoiceId = forms.IntegerField() + orderSumAmount = forms.DecimalField() def clean_action(self): action = self.cleaned_data.get('action') diff --git a/wallets/signals.py b/wallets/signals.py index 50d2f08..785383c 100644 --- a/wallets/signals.py +++ b/wallets/signals.py @@ -22,7 +22,7 @@ def send_for_accountant(sender, instance, created, **kwargs): @receiver(post_save, sender=Transaction) def add_invoice_history(sender, instance, created, **kwargs): - if 'add' in instance.type: + if 'add' in instance.type and instance.complete: inv_history = InvoiceHistory() inv_history.comment = 'Пополнение счета' inv_history.sum = instance.sum diff --git a/wallets/templates/score-detail.html b/wallets/templates/score-detail.html index 9a9f2c9..275e727 100644 --- a/wallets/templates/score-detail.html +++ b/wallets/templates/score-detail.html @@ -23,7 +23,7 @@ {% endif %} @@ -75,15 +75,14 @@ diff --git a/ratings/templatetags/specializtions_tags.py b/ratings/templatetags/specializtions_tags.py index 6ef72bb..2659523 100644 --- a/ratings/templatetags/specializtions_tags.py +++ b/ratings/templatetags/specializtions_tags.py @@ -1,11 +1,13 @@ from django import template -from archilance import util -from users.models import User, Team +from projects.models import Order from ratings.models import SpecializationRating +from reviews.models import Review +from users.models import User, Team register = template.Library() + @register.inclusion_tag('templatetags/specializations_widget.html', takes_context=True) def specialization_widget(context, user_id, class_name=None): user_id = int(user_id) @@ -25,18 +27,26 @@ def specialization_team_widget(context, team_id): } - @register.inclusion_tag("templatetags/ratings_widget.html", takes_context=True) def ratings_widget(context, user_id, class_name=None): ratings = User.objects.get(pk=user_id).rating return { 'ratings': ratings, - 'class_name': class_name + 'class_name': class_name, + 'deals': Order.objects.filter(secure=True, contractor_id=user_id, status=1).count(), + 'reviews_n': Review.objects.filter(target_contractor_id=user_id, type='neutral').count(), + 'reviews_m': Review.objects.filter(target_contractor_id=user_id, type='negative').count(), + 'reviews_p': Review.objects.filter(target_contractor_id=user_id, type='positive').count(), } + @register.inclusion_tag("templatetags/ratings_widget.html", takes_context=True) def ratings_team_widget(context, team_id): ratings = Team.objects.get(pk=team_id).rating return { 'ratings': ratings, + 'deals': Order.objects.filter(secure=True, team_id=team_id, status=1).count(), + 'reviews_n': Review.objects.filter(target_team_id=team_id, type='neutral').count(), + 'reviews_m': Review.objects.filter(target_team_id=team_id, type='negative').count(), + 'reviews_p': Review.objects.filter(target_team_id=team_id, type='positive').count(), } diff --git a/users/templates/contractor_office.html b/users/templates/contractor_office.html index de876f1..18e87b8 100644 --- a/users/templates/contractor_office.html +++ b/users/templates/contractor_office.html @@ -91,7 +91,8 @@ Программист
- + {% empty %} + В группе пока нет участников {% endfor %}
@@ -176,15 +177,19 @@ + {% empty %} +
+

Работ в портфолио пока нет

+
{% endfor %} - -
- -
+{# TODO:#} +{#
#} +{# #} +{#
#}
@@ -208,38 +213,45 @@
+ {% empty %} +
+

Готовых работ пока нет

+
{% endfor %} -
- -
+{# TODO#} +{#
#} +{# #} +{#
#}
+ {% for review in reviews %}

- Иванов Петр Иванович + {{ review.get_sender }}

- - Безопасная сделка - + {% if review.project.deal_type == 'secure_deal' %} + + Безопасная сделка + + {% endif %}

- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean euismod bibendum - + {{ review.text|safe }}

+ {% empty %} +
+

Отзывов пока нет

+
+ {% endfor %}
diff --git a/users/templates/contractor_profile.html b/users/templates/contractor_profile.html index 0d69861..55c0941 100644 --- a/users/templates/contractor_profile.html +++ b/users/templates/contractor_profile.html @@ -196,7 +196,12 @@ {% endif %} + {% empty %} +
+

Работ в портфолио пока нет

+
{% endfor %} +
@@ -455,6 +460,10 @@

+ {% empty %} +
+

Отзывов пока нет

+
{% endfor %} diff --git a/users/views.py b/users/views.py index d87e666..e51ba37 100644 --- a/users/views.py +++ b/users/views.py @@ -375,6 +375,7 @@ class ContractorOfficeDetailView(DetailView): work_sells = WorkSell.objects.filter(contractor__in=user_ids) context['portfolios'] = portfolios context['work_sells'] = work_sells + context['reviews'] = Review.objects.filter(target_contractor__in=user_ids) return context diff --git a/wallets/views.py b/wallets/views.py index e5a11f8..84df34c 100644 --- a/wallets/views.py +++ b/wallets/views.py @@ -1,27 +1,25 @@ -from django.conf import urls, settings +from django.conf import settings from django.contrib import messages +from django.contrib.auth.mixins import LoginRequiredMixin from django.db.models import Sum -from django.http import HttpResponse, JsonResponse, HttpResponseForbidden +from django.http import HttpResponse, JsonResponse from django.shortcuts import render, get_object_or_404 from django.utils import timezone from django.utils.decorators import method_decorator from django.views.decorators.csrf import csrf_exempt from django.views.generic import DetailView, CreateView from django.views.generic.base import View -from pprint import pprint, pformat -import logging +from users.models import User from .forms import WithDrawForm, TmpCheckOrderForm, TmpPaymentAvisoForm from .models import InvoiceHistory, WithDraw, Transaction -from users.mixins import CheckForUserMixin -from users.models import User class ScoreDetailView(DetailView): model = User template_name = 'score-detail.html' context_object_name = 'user_score' - + def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) user_score_balance = InvoiceHistory.objects.filter(user=self.get_object()).aggregate(Sum('sum')) @@ -30,16 +28,15 @@ class ScoreDetailView(DetailView): return context -class ScoreView(View): +class ScoreView(LoginRequiredMixin, View): template_name = 'score-detail.html' def get(self, request, *args, **kwargs): - # transaction = Transaction.objects.get_or_create(customer=request.user, complete=False) - transaction = Transaction.objects.create(customer=request.user,type='add') + transaction = Transaction.objects.create(customer=request.user, type='add') user_score = get_object_or_404(User.objects, pk=kwargs.get('pk')) current_sum_info = InvoiceHistory.objects.filter(user=user_score).aggregate(Sum('sum')) user_score_balance = current_sum_info['sum__sum'] or 0 - + return render(request, self.template_name, { 'transaction': transaction, 'YANDEX_MONEY': settings.YANDEX_MONEY, @@ -96,23 +93,22 @@ class WithDrawCreate(CreateView): return super().form_invalid(form) - # Yandex Money ------------------------------------------------ class TmpCheckOrderView(View): form_class = TmpCheckOrderForm - + @method_decorator(csrf_exempt) def dispatch(self, request, *args, **kwargs): return super().dispatch(request, *args, **kwargs) - + def post(self, request, *args, **kwargs): form = self.form_class(request.POST) - + # trans = form.cleaned_data.get('transaction') - + if form.is_valid(): res = """ @@ -141,21 +137,21 @@ class TmpCheckOrderView(View): invoice_id=form.cleaned_data.get('invoiceId'), shop_id=form.cleaned_data.get('shopId'), ) - + return HttpResponse(res, content_type='application/xml') # return HttpResponse('
{msg}
'.format(msg=pformat(form.errors))) # Debug class TmpPaymentAvisoView(View): form_class = TmpPaymentAvisoForm - + @method_decorator(csrf_exempt) def dispatch(self, request, *args, **kwargs): return super().dispatch(request, *args, **kwargs) - + def post(self, request, *args, **kwargs): form = self.form_class(request.POST) - + if form.is_valid(): transaction = form.cleaned_data.get('transaction_id') transaction.complete = True @@ -173,7 +169,7 @@ class TmpPaymentAvisoView(View): invoice_id=form.cleaned_data.get('invoiceId'), shop_id=form.cleaned_data.get('shopId'), ) - + return HttpResponse(res, content_type='application/xml') else: res = """ @@ -183,6 +179,6 @@ class TmpPaymentAvisoView(View): message="Payment aviso, validation error" techMessage="Payment aviso, validation error"/> """.format(date=timezone.now().isoformat()) - + return HttpResponse(res, content_type='application/xml') # return HttpResponse('
{msg}
'.format(msg=pformat(form.errors))) # Debug