diff --git a/chat/app.py b/chat/app.py index 2416eec..dedfad5 100644 --- a/chat/app.py +++ b/chat/app.py @@ -50,3 +50,15 @@ def main(): if __name__ == '__main__': main() + + + + + @gen.coroutine + def get_messages_from_order_chat(self, order_id): + sql = "SELECT text FROM chat_message WHERE order_id=" + order_id + cursor = yield self.db.execute(sql) + messages = cursor.fetchall() + for msg in messages: + for waiter in self.waiters: + waiter.write_message({'msg': msg[0], 'answer_type': 'contact'}) diff --git a/chat/migrations/0002_message_team.py b/chat/migrations/0002_message_team.py new file mode 100644 index 0000000..cebcf7c --- /dev/null +++ b/chat/migrations/0002_message_team.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-08-02 14:32 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0003_auto_20160726_1931'), + ('chat', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='message', + name='team', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='team_messages', to='users.Team'), + ), + ] diff --git a/chat/models.py b/chat/models.py index ad0aac1..2901f26 100644 --- a/chat/models.py +++ b/chat/models.py @@ -2,7 +2,7 @@ from django.db import models from django.utils import timezone from projects.models import Order -from users.models import User +from users.models import User, Team class Message(models.Model): @@ -12,6 +12,7 @@ class Message(models.Model): sender = models.ForeignKey(User, related_name='sender_messages') recipent = models.ForeignKey(User, related_name='recipent_messages') private_type = models.BooleanField(default=False) + team = models.ForeignKey(Team, related_name='team_messages', null=True, blank=True) def __str__(self): return self.text diff --git a/chat/templates/chat_contractor.html b/chat/templates/chat_contractor.html index 17a40da..f5888b4 100644 --- a/chat/templates/chat_contractor.html +++ b/chat/templates/chat_contractor.html @@ -23,9 +23,11 @@ Заказчики + {% if team_orders %}
  • Исполнители
  • + {% endif %} @@ -163,34 +165,51 @@ + {% if team_orders %}

    Заказы

    -
    + {% for torder in team_orders %} +

    - Дизай-проект квартиры на набережной 200 m2 + {{ torder }}

    - Заказчик: Группа Икс +{# Заказчик: {{ torder.project.customer }}#} + Исполнитель: {{ torder.team.name }}

      -
    • Иванов Петр Иванович
    • -
    • Сергей Пенкин
    • + {% for tuser in torder.team.users.all %} +
    • {{ tuser }}
    • + {% endfor %}
    + +

    + Чаты: + {% for tuser in torder.team.users.all %} + {{ tuser.username }}, + {% endfor %} +

    Полное описание заказа
    + {% endfor %}
    - +
    + + + + +

    Прикрепить файл

    @@ -198,39 +217,16 @@ Не более 10 файлов с общим объемом 500мб
    - отправить + отправить
    +
    -

    Этапы работы

    -
    -

    1 / Согласование условий

    -

    - Обсуджение задания и условий выполнения работы. Подтверждение заказа исполнителем. -

    -
    -
    -
    -

    2 / Резервирование

    -

    - Резервирование заказчиком суммы оплаты по заказ. Деньги перечисляются и хранятся на - сайте. -

    -
      -
    • Сумма еще не зарезервирована
    • -
    • Сумма за этап1, Зарезервирована
    • -
    -
    -
    -

    3 / Выполнение работы

    -

    - Процесс выполнения задания в заказе до получения заказчиком итогового результата работы. -

    -
    + {% endif %}
    {% include 'partials/footer.html' %} @@ -258,9 +254,9 @@ var message = JSON.parse(event.data); var inbox; - if (message.answer_type == 'contact') { + if (message.answer_type == 'contact' || message.answer_type == 'add_message_contact') { inbox = document.getElementById('message-chat-space'); - } else if (message.answer_type == 'order' || message.answer_type == 'add_order') { + } else if (message.answer_type == 'order' || message.answer_type == 'add_message_order') { inbox = document.getElementById('message-chat-order-space'); } inbox.innerHTML += '
    ' + @@ -277,6 +273,11 @@ console.log(data); }; + this.add_team_message = function(messageData){ + console.log(messageData); + sock.send(JSON.stringify(messageData)); + } + this.add_contact_message = function (messageData) { console.log(messageData); sock.send(JSON.stringify(messageData)); @@ -311,6 +312,18 @@ }); }); + $(".team-chat-user").on('click',function(){ + var recipentId = $(this).attr('data-id'); + $("#team-chat-form #recipentId").val(recipentId); + }); + + $(".team-order-block").on('click', function(){ + var teamId = $(this).attr('data-team-id'); + var orderId = $(this).attr('data-order-id'); + $("#team-chat-form #teamId").val(teamId); + $("#team-chat-form #orderId").val(orderId); + }); + // Вытащить сообщения для чата заказа $('.order-block').on('click', function () { $('.order-block').each(function () { @@ -453,6 +466,26 @@ }); + + //Добавить сообщение для исполнителей в группе + + $("#add-team-chat-message").on('click', function(){ + var chatMessage = $("#team-chat-form #chatText").val(); + var recipentId = $("#team-chat-form #recipentId").val(); + var senderId = $("#team-chat-form #senderId").val(); + var teamId = $("#team-chat-form #teamId").val(); + + socket.add_team_message({ + "format_type": "add_message_team", + "data": { + "sender_id": senderId, + "recipent_id": recipentId, + "chat_message": chatMessage, + "team_id": teamId, + } + }); + }); + // Добавить сообщение для контакта $('#contact-chat-add-message').on('click', function () { var chatMessage = $("#chat").val(); diff --git a/chat/testapp.py b/chat/testapp.py index 92df387..8d245d3 100644 --- a/chat/testapp.py +++ b/chat/testapp.py @@ -26,29 +26,7 @@ class BaseHandler(web.RequestHandler): return self.application.db -class TestHandler(web.RequestHandler): - @property - def db(self): - return self.application.db - - @gen.coroutine - def get(self, *args, **kwargs): - sql = "SELECT text,created FROM chat_message" - cursor = yield self.db.execute(sql) - data = cursor.fetchall() - for d in data: - print(d[1]) - print(type(d[1])) - print(str(d[1])) - - -class NotificationHandler(websocket.WebSocketHandler): - @property - def db(self): - return self.application.db - - -class TutorialHandler(websocket.WebSocketHandler): +class ChatHandler(websocket.WebSocketHandler): @property def db(self): return self.application.db @@ -65,63 +43,36 @@ class TutorialHandler(websocket.WebSocketHandler): if 'dummy' in parsed: return - if parsed['format_type'] == 'add_message_contact': - self.add_message_for_contact(parsed['data']['chat_message'], parsed['data']['sender_id'], - parsed['data']['recipent_id']) - elif parsed['format_type'] == 'add_message_order': - self.add_message_for_order(parsed['data']['chat_message'], parsed['data']['sender_id'], - parsed['data']['recipent_id'], parsed['data']['order_id']) - elif parsed['format_type'] == 'order_message': - self.get_messages_from_order_chat(parsed['order_id']) - else: - self.get_messages_from_order(parsed['user_id']) + self.add_message(parsed) def on_close(self): self.waiters.remove((self.user_id, self)) - # insert_sql = "INSERT INTO chat_message (id,text,created,order_id, user_id) VALUES (DEFAULT,'{0}',NOW(),6,4)".format(str(parsed['message'])) - # yield self.db.execute(insert_sql) - # - # # cursor = yield self.db.execute("SELECT * FROM chat_message") - # # data = cursor.fetchall() - # for waiter in self.waiters: - # waiter.write_message({'msg': parsed['message']}) +# waiter.write_message({'msg': message, 'answer_type': 'add_contact'}) +# waiter.write_message({'msg': message, 'answer_type': 'add_order'}) @gen.coroutine - def add_message_for_contact(self, message, sender_id, recipent_id): - insert_sql = "INSERT INTO chat_message (id,text,created,order_id, sender_id,recipent_id, private_type) " \ - "VALUES (DEFAULT,'{0}',NOW(),NULL,{1},{2},'true')".format(message, sender_id, recipent_id) - yield self.db.execute(insert_sql) - waiters = tuple(w for c, w in self.waiters if c == recipent_id) - for waiter in waiters: - waiter.write_message({'msg': message, 'answer_type': 'add_contact'}) + def add_message(self, message_data): + sender_id = message_data['data']['sender_id'] + recipent_id = message_data['data']['recipent_id'] + 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) + + answer_type = message_data['format_type'] + private_type = 'true' if not order_id and not team_id else 'false' + + team_value = "NULL" if team_id is None else team_id + order_value = "NULL" if order_id is None else order_id + + insert_sql = "INSERT INTO chat_message (id,text,created, sender_id,recipent_id, private_type,team_id, order_id) " \ + "VALUES (DEFAULT,'{0}',NOW(),{1},{2},{3},{4},{5})".format(message, sender_id, recipent_id, private_type, team_value,order_value) - @gen.coroutine - def add_message_for_order(self, message, sender_id,recipent_id, order_id): - insert_sql = "INSERT INTO chat_message (id,text,created,order_id, sender_id,recipent_id, private_type) " \ - "VALUES (DEFAULT,'{0}',NOW(),{1},{2},{3},'false')".format(message,order_id, sender_id, recipent_id) yield self.db.execute(insert_sql) 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': 'add_order'}) - - @gen.coroutine - def get_messages_from_order(self, order_id): - sql = "SELECT text FROM chat_message WHERE recipent_id=" + order_id - cursor = yield self.db.execute(sql) - messages = cursor.fetchall() - for msg in messages: - for waiter in self.waiters: - waiter.write_message(json.dumps({'msg': msg[0], 'answer_type': 'order'})) - @gen.coroutine - def get_messages_from_order_chat(self, order_id): - sql = "SELECT text FROM chat_message WHERE order_id=" + order_id - cursor = yield self.db.execute(sql) - messages = cursor.fetchall() - for msg in messages: - for waiter in self.waiters: - waiter.write_message({'msg': msg[0], 'answer_type': 'contact'}) + for waiter in waiters: + waiter.write_message({'msg': message, 'answer_type': answer_type}) def check_origin(self, origin): return True @@ -130,8 +81,7 @@ class TutorialHandler(websocket.WebSocketHandler): class Application(web.Application): def __init__(self): handlers = [ - (r"/chat/(?P\d+)/", TutorialHandler), - (r"/test", TestHandler), + (r"/chat/(?P\d+)/", ChatHandler), ] super().__init__(handlers=handlers, **settings) diff --git a/chat/views.py b/chat/views.py index ed44c24..49c5e0c 100644 --- a/chat/views.py +++ b/chat/views.py @@ -45,10 +45,15 @@ class ChatUserView(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)).order_by( 'created') + + if request.user.is_owner_team(): + team_orders = request.user.team.team_orders.all() + self.template_name = 'chat_contractor.html' return render(request, self.template_name, {'orders': orders, 'contacts_users': contacts_users, - 'chat_messages': chat_messages + 'chat_messages': chat_messages, + 'team_orders': team_orders, }) diff --git a/projects/filters.py b/projects/filters.py index 5ba3066..444d426 100755 --- a/projects/filters.py +++ b/projects/filters.py @@ -45,6 +45,7 @@ class ProjectFilterSet(FilterSet): class OrderFilterSet(FilterSet): id = AllLookupsFilter() contractor = RelatedFilter('users.filters.UserFilterSet') + team = RelatedFilter('users.filters.TeamFilterSet') created = AllLookupsFilter() project = RelatedFilter('projects.filters.ProjectFilterSet') secure = AllLookupsFilter() diff --git a/projects/migrations/0009_auto_20160802_1226.py b/projects/migrations/0009_auto_20160802_1226.py new file mode 100644 index 0000000..a327d92 --- /dev/null +++ b/projects/migrations/0009_auto_20160802_1226.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-08-02 09:26 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0003_auto_20160726_1931'), + ('projects', '0008_merge'), + ] + + operations = [ + migrations.AddField( + model_name='order', + name='team', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='team_orders', to='users.Team'), + ), + migrations.AlterField( + model_name='stage', + name='created', + field=models.DateTimeField(default=django.utils.timezone.now), + ), + ] diff --git a/projects/models.py b/projects/models.py index a296928..6f6b209 100644 --- a/projects/models.py +++ b/projects/models.py @@ -136,6 +136,7 @@ class Answer(models.Model): class Order(models.Model): contractor = models.ForeignKey(User, null=True, blank=True, related_name='orders') + team = models.ForeignKey(Team, null=True, blank=True, related_name='team_orders') created = models.DateTimeField(default=timezone.now) project = models.OneToOneField(Project, related_name='order') secure = models.BooleanField(default=False) diff --git a/projects/serializers.py b/projects/serializers.py index e48b5cd..5d8fdba 100755 --- a/projects/serializers.py +++ b/projects/serializers.py @@ -52,6 +52,7 @@ class OrderSerializer(ModelSerializer): fields = ( 'id', 'contractor', + 'team', 'created', 'project', 'secure', diff --git a/users/filters.py b/users/filters.py index 82a0753..c796aff 100755 --- a/users/filters.py +++ b/users/filters.py @@ -1,5 +1,5 @@ from rest_framework_filters import FilterSet, RelatedFilter, AllLookupsFilter -from .models import User +from .models import User, Team class UserFilterSet(FilterSet): id = AllLookupsFilter() @@ -12,3 +12,13 @@ class UserFilterSet(FilterSet): class Meta: model = User + + +class TeamFilterSet(FilterSet): + id = AllLookupsFilter() + name = AllLookupsFilter() + owner = RelatedFilter('users.filters.UserFilterSet') + + + class Meta: + model = Team diff --git a/users/serializers.py b/users/serializers.py index 8bca6a9..59c94db 100755 --- a/users/serializers.py +++ b/users/serializers.py @@ -1,10 +1,24 @@ from rest_framework.serializers import ModelSerializer -from .models import User +from .models import User, Team from projects.models import Project +class TeamSerializer(ModelSerializer): + + class Meta: + model = Team + + fields = ( + 'created', + 'name', + 'owner', + 'specializations', + 'users', + ) + class UserSerializer(ModelSerializer): + class Meta: model = User