#ARC-16 Filter messages for orders

remotes/origin/PR-39
Mukhtar 10 years ago
parent 58d97a49c7
commit fbac71997e
  1. 5
      api/views.py
  2. 4
      assets/css/extra.css
  3. 263
      assets/js/chat.js
  4. 2
      chat/chat.py
  5. 1
      chat/filters.py
  6. 1
      chat/serializers.py
  7. 111
      chat/templates/chat_contractor.html
  8. 121
      chat/templates/chat_customer.html
  9. 18
      chat/views.py
  10. 20
      projects/migrations/0018_auto_20160829_1751.py
  11. 19
      projects/migrations/0019_remove_stage_term.py
  12. 23
      projects/migrations/0020_stage_term.py
  13. 2
      projects/models.py
  14. 14
      projects/serializers.py
  15. 9
      projects/templates/comparison.html
  16. 6
      projects/templates/project_detail.html
  17. 6
      projects/views.py
  18. 10
      templates/partials/base.html
  19. 20
      work_sell/migrations/0007_auto_20160829_1740.py

@ -72,7 +72,7 @@ class DocumentViewSet(ModelViewSet):
if search_param: if search_param:
# import code; code.interact(local=dict(globals(), **locals())) # import code; code.interact(local=dict(globals(), **locals()))
if search_param == 'in': if search_param == 'in':
queryset = queryset.filter(Q(sender__in=[sender_id,recipent_id]),Q(recipent__in=[sender_id,recipent_id])).order_by('created') queryset = queryset.filter(Q(sender__in=[sender_id, recipent_id]),Q(recipent__in=[sender_id, recipent_id])).filter(order__isnull=True).order_by('created')
return queryset return queryset
@ -99,6 +99,7 @@ class NoteViewSet(ModelViewSet):
queryset = queryset.filter(Q(sender__in=[sender_id,recipent_id]),Q(recipent__in=[sender_id,recipent_id])).order_by('created') queryset = queryset.filter(Q(sender__in=[sender_id,recipent_id]),Q(recipent__in=[sender_id,recipent_id])).order_by('created')
return queryset return queryset
class MessageViewSet(ModelViewSet): class MessageViewSet(ModelViewSet):
queryset = Message.objects.all() queryset = Message.objects.all()
serializer_class = MessageSerializer serializer_class = MessageSerializer
@ -112,7 +113,7 @@ class MessageViewSet(ModelViewSet):
if search_param: if search_param:
# import code; code.interact(local=dict(globals(), **locals())) # import code; code.interact(local=dict(globals(), **locals()))
if search_param == 'in': if search_param == 'in':
queryset = queryset.filter(Q(sender__in=[sender_id,recipent_id]),Q(recipent__in=[sender_id,recipent_id])).order_by('created') queryset = queryset.filter(Q(sender__in=[sender_id,recipent_id]),Q(recipent__in=[sender_id,recipent_id])).filter(order__isnull=True).order_by('created')
return queryset return queryset

@ -107,3 +107,7 @@
font-size: 15px; font-size: 15px;
} }
#jGrowl .jGrowl-notification a, #jGrowl .jGrowl-notification a:visited {
color: #777620;
}

@ -14,7 +14,13 @@ var SocketHandler = function () {
var message = JSON.parse(event.data); var message = JSON.parse(event.data);
var inbox; var inbox;
if (message.answer_type == 'contact' || message.answer_type == 'add_message_contact') { if (message.answer_type == 'contact' || message.answer_type == 'add_message_contact') {
inbox = document.getElementById('message-chat-space'); var sumSenderRecipent = parseInt(message.recipent_id) + parseInt(message.sender_id);
var inboxClass = document.getElementsByClassName('contact-space' + sumSenderRecipent);
if (inboxClass.length > 0) {
inbox = inboxClass[0];
}else{
$(".contact-count-" + sumSenderRecipent).text(parseInt($(".contact-count-" + sumSenderRecipent).text()) + 1);
}
} else if (message.answer_type == 'order' || message.answer_type == 'add_message_order') { } else if (message.answer_type == 'order' || message.answer_type == 'add_message_order') {
inbox = document.getElementById('message-chat-order-space'); inbox = document.getElementById('message-chat-order-space');
} else if (message.answer_type == 'add_message_team') { } else if (message.answer_type == 'add_message_team') {
@ -123,6 +129,99 @@ $(function () {
} }
// Вытащить сообщения для конактов
$('.user-block').on('click', function () {
var contactId = $(this).attr('data-id');
$("#contact-chat-form #recipentContactId").val(contactId);
$("#add-form-contractor-note #recipentNoteContractor").val(contactId);
$('.user-block').each(function () {
$(this).removeClass('mesAct');
});
$(this).addClass('mesAct');
var inbox = document.getElementById('message-chat-space');
var sumSenderRecipent = parseInt(userId) + parseInt(contactId);
$("#message-chat-space").removeClass().addClass("contact-space" + sumSenderRecipent);
$(".contact-count-"+ sumSenderRecipent).text(0);
var docList = document.getElementById('documentSpace');
inbox.innerHTML = '';
docList.innerHTML = '';
$.ajax({
url: '/api/documents',
type: 'GET',
data: {
csrfmiddlewaretoken: csrftoken,
'operand': 'in',
'sender_id': userId,
'recipent_id': contactId,
},
dataType: 'json',
success: function (json) {
console.log(json);
$.each(json.results, function (i, v) {
docList.innerHTML += '<li style="word-break: break-all;">' + v.file + '</li>';
});
},
error: function (e) {
console.log(e);
}
});
$.ajax({
url: '/api/message',
type: 'GET',
data: {
csrfmiddlewaretoken: csrftoken,
'operand': 'in',
'sender_id': userId,
'recipent_id': contactId
},
dataType: 'json',
success: function (json) {
$.each(json.results, function (i, v) {
var senderName = 'Вы';
var className = 'youChat';
if (v.sender.id == contactId) {
senderName = v.sender.username;
className = '';
}
inbox.innerHTML += '<div class="col-lg-12 insetCommChat ' + className + '"><div class="topCommChat">' +
'<p class="nameCommChat">' + senderName + '</p> <span>' + v.created + '</span></div>' +
'<p class="textCommChat">' + v.text + '</p></div>';
});
}
});
$.ajax({
url: '/api/note/',
type: 'GET',
data: {
csrfmiddlewaretoken: csrftoken,
'operand': 'in',
'sender_id': userId,
'recipent_id': contactId
},
dataType: 'json',
success: function (json) {
console.log(json.results);
var noteHtmlInbox = '';
$.each(json.results, function (i, v) {
noteHtmlInbox += '<li>' + v.text + '<li>';
});
$(".contractor-notes-block").html(noteHtmlInbox);
}
});
});
$('.deleteMess').on('click', function (e) { $('.deleteMess').on('click', function (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
@ -182,81 +281,111 @@ $(function () {
var senderId = $("#chat-order-add #senderId").val(); var senderId = $("#chat-order-add #senderId").val();
var orderId = $("#chat-order-add #orderId").val(); var orderId = $("#chat-order-add #orderId").val();
socket.add_contact_message({ if (chatMessage) {
"format_type": "add_message_order", $("#chat-order-add .errorEmptyMessage").hide();
"data": { socket.add_contact_message({
"sender_id": senderId, "format_type": "add_message_order",
"recipent_id": recipentId, "data": {
"chat_message": chatMessage, "sender_id": senderId,
"order_id": orderId, "recipent_id": recipentId,
"chat_message": chatMessage,
"order_id": orderId,
} }
});
});
$("#chat-order-add #chat").val("");
$("#document-send-order").html("");
} else {
$("#chat-order-add .errorEmptyMessage").show();
}
});
$('#contact-chat-add-message').on('click', function (e) {
e.preventDefault();
var chatMessage = $("#chat").val();
var recipentId = $("#recipentContactId").val();
var senderId = $("#senderContactId").val();
if (chatMessage) {
$("#contact-chat-form .errorEmptyMessage").hide();
socket.add_contact_message({
"format_type": "add_message_contact",
"data": {
"sender_id": senderId,
"recipent_id": recipentId,
"chat_message": chatMessage,
}
});
$("#chat").val("");
$("#document-send-contact").html("");
} else {
$("#contact-chat-form .errorEmptyMessage").show();
}
$("#chat-order-add #chat").val("");
$("#document-send-order").html("");
}); });
// Добавление отзыва // Добавление отзыва
$('#order-review-add').on('click', function (e) { $('#order-review-add').on('click', function (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
var formData = $("#review-adds-form").serialize(); var formData = $("#review-adds-form").serialize();
$.ajax({ $.ajax({
url: '/api/reviews/', url: '/api/reviews/',
type: 'POST', type: 'POST',
beforeSend: function (xhr) { beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken')) xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
}, },
data: formData, data: formData,
dataType: 'json', dataType: 'json',
success: function (json) { success: function (json) {
console.log("Успешно"); console.log("Успешно");
$("#review-add").modal('hide'); $("#review-add").modal('hide');
$.jGrowl("Ваш отзыв успешно добавлен", { $.jGrowl("Ваш отзыв успешно добавлен", {
life: 4000 life: 4000
}); });
}, },
error: function (e) { error: function (e) {
console.log('error'); console.log('error');
console.log(e); console.log(e);
} }
}); });
}); });
// Добавление сообщения в арбитраж // Добавление сообщения в арбитраж
$('#order-arbitration-add').on('click', function (e) { $('#order-arbitration-add').on('click', function (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
var formData = $("#arbitration-add-form").serialize(); var formData = $("#arbitration-add-form").serialize();
$.ajax({ $.ajax({
url: '/projects/arbitration/create/', url: '/projects/arbitration/create/',
type: 'POST', type: 'POST',
beforeSend: function (xhr) { beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken')) xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
}, },
data: formData, data: formData,
dataType: 'json', dataType: 'json',
success: function (json) { success: function (json) {
console.log(json); console.log(json);
$("#arbitration-add").modal('hide'); $("#arbitration-add").modal('hide');
$.jGrowl("Обращение в арбитраж добавлено", { $.jGrowl("Обращение в арбитраж добавлено", {
life: 4000 life: 4000
}); });
}, },
error: function (e) { error: function (e) {
console.log('error'); console.log('error');
console.log(e); console.log(e);
} }
}); });
}); });
$("#upload-document-order").bind('fileuploadsubmit', function(e, data){ $("#upload-document-order").bind('fileuploadsubmit', function (e, data) {
data.formData = { data.formData = {
sender: $("#chat-order-add #senderId").val(), sender: $("#chat-order-add #senderId").val(),
recipent: $("#chat-order-add #recipentId").val(), recipent: $("#chat-order-add #recipentId").val(),
order: $("#chat-order-add #orderId").val(), order: $("#chat-order-add #orderId").val(),
} }
}); });
//Загрузка документов //Загрузка документов
@ -296,17 +425,15 @@ $(function () {
.parent().addClass($.support.fileInput ? undefined : 'disabled'); //Загрузка документов .parent().addClass($.support.fileInput ? undefined : 'disabled'); //Загрузка документов
$("#upload-document-contact").bind('fileuploadsubmit', function (e, data) {
$("#upload-document-contact").bind('fileuploadsubmit', function(e, data){ data.formData = {
data.formData = { sender: $("#contact-chat-form #senderContactId").val(),
sender: $("#contact-chat-form #senderContactId").val(), recipent: $("#contact-chat-form #recipentContactId").val(),
recipent: $("#contact-chat-form #recipentContactId").val(), }
}
}); });
$('#upload-document-contact').fileupload({ $('#upload-document-contact').fileupload({
url: '/chat/create/', url: '/chat/create/',
crossDomain: false, crossDomain: false,

@ -94,7 +94,7 @@ class ChatHandler(websocket.WebSocketHandler):
waiters = tuple(w for c, w in self.waiters if c == recipent_id or c == sender_id) waiters = tuple(w for c, w in self.waiters if c == recipent_id or c == sender_id)
for waiter in waiters: for waiter in waiters:
waiter.write_message({'msg': message, 'msg_time': msg_time, 'sender_id': sender_id, 'sender_name': sender_name, 'answer_type': answer_type}) waiter.write_message({'msg': message, 'msg_time': msg_time, 'order_id': order_id, 'recipent_id': recipent_id,'sender_id': sender_id, 'sender_name': sender_name, 'answer_type': answer_type})
def check_origin(self, origin): def check_origin(self, origin):
return True return True

@ -20,6 +20,7 @@ class MessageFilterSet(FilterSet):
sender = RelatedFilter('users.filters.UserFilterSet') sender = RelatedFilter('users.filters.UserFilterSet')
recipent = RelatedFilter('users.filters.UserFilterSet') recipent = RelatedFilter('users.filters.UserFilterSet')
private_type = AllLookupsFilter() private_type = AllLookupsFilter()
team = RelatedFilter('users.filters.TeamFilterSet')
class Meta: class Meta:
model = Message model = Message

@ -35,6 +35,7 @@ class MessageSerializer(ModelSerializer):
'sender', 'sender',
'recipent', 'recipent',
'private_type', 'private_type',
'team',
) )

@ -58,7 +58,7 @@
<a href="#" class="conMess">Контакты</a> <a href="#" class="conMess">Контакты</a>
<span>0</span> <span class="contact-count-{{ contact.pk|add:request.user.pk }}">0</span>
<a href="#" class="deleteMess" data-recipent-id="{{ contact.pk }}"> <a href="#" class="deleteMess" data-recipent-id="{{ contact.pk }}">
Удалить контакт Удалить контакт
</a> </a>
@ -71,20 +71,31 @@
<div class="col-lg-6 commChat" id="contact-chat"> <div class="col-lg-6 commChat" id="contact-chat">
<div id="message-chat-space"></div> <div id="message-chat-space"></div>
<form id="contact-chat-form"> <form id="contact-chat-form">
<input type="hidden" value="{{ request.user.pk }}" name="senderId" id="senderId"/> <input type="hidden" value="{{ request.user.pk }}" name="senderId" id="senderContactId"/>
<input type="hidden" value="" name="recipentId" id="recipentId"/> <input type="hidden" value="" name="recipentId" id="recipentContactId"/>
<textarea id="chat" name="chat_message" class="box-sizing"></textarea> <textarea id="chat" name="chat_message" class="box-sizing"></textarea>
<p class="errorEmptyMessage" style="color: red;display:none;">Пустое сообщение нельзя отправить</p>
<div class="bunChat"> <div class="bunChat">
<div class="setChat box-sizing"> <div class="setChat box-sizing upload">
<p>Прикрепить файл</p> <input type="file" name="file" id="upload-document-contact">
<span>Не более 10 файлов с общим объемом 500мб</span> <p>Прикрепить файл</p>
</div> </div>
<a id="contact-chat-add-message" href="javascript:void(0)">отправить</a> <div id="document-send-contact"></div>
<a id="contact-chat-add-message" href="#">отправить</a>
</div> </div>
</form> </form>
</div> </div>
<div class="col-lg-3 wrChat1"> <div class="col-lg-3 wrChat1">
<div class="col-lg-12 documentsChat">
<p>Входящие документы</p>
<ul id="documentSpace">
</ul>
{# <a href="javascript:void(0)">#}
{# Распечатать с помощью ресурса#}
{# </a>#}
</div>
<div class="textAreaBlock2 box-sizing disTab"> <div class="textAreaBlock2 box-sizing disTab">
<ul class="contractor-notes-block"> <ul class="contractor-notes-block">
</ul> </ul>
@ -131,6 +142,7 @@
<input type="hidden" id="senderId" value="{{ request.user.pk }}"/> <input type="hidden" id="senderId" value="{{ request.user.pk }}"/>
<input type="hidden" id="recipentId"> <input type="hidden" id="recipentId">
<textarea id="chat" class="box-sizing"></textarea> <textarea id="chat" class="box-sizing"></textarea>
<p class="errorEmptyMessage" style="color: red;display:none;">Пустое сообщение нельзя отправить</p>
<div class="bunChat"> <div class="bunChat">
<div class="setChat box-sizing upload"> <div class="setChat box-sizing upload">
<input type="file" name="file" id="upload-document-order"/> <input type="file" name="file" id="upload-document-order"/>
@ -433,7 +445,6 @@
$(this).removeClass('orAct'); $(this).removeClass('orAct');
}); });
$(this).addClass('orAct'); $(this).addClass('orAct');
var orderId = $(this).attr('data-id'); var orderId = $(this).attr('data-id');
var recipentId = $(this).attr('data-recipent-id'); var recipentId = $(this).attr('data-recipent-id');
var projectId = $(this).attr('data-project-id'); var projectId = $(this).attr('data-project-id');
@ -447,15 +458,13 @@
$("#targetCustomerId").val(recipentId); $("#targetCustomerId").val(recipentId);
$("#add-form-order-note #recipentNote").val(recipentId); $("#add-form-order-note #recipentNote").val(recipentId);
var inbox = document.getElementById('message-chat-order-space'); var inbox = document.getElementById('message-chat-order-space');
inbox.innerHTML = ''; inbox.innerHTML = '';
$.ajax({ $.ajax({
url: '/api/message', url: '/api/message',
type: 'GET', type: 'GET',
data: {csrfmiddlewaretoken: csrftoken, 'order': orderId}, data: {csrfmiddlewaretoken: csrftoken, 'order': orderId, 'team__isnull': 'true'},
dataType: 'json', dataType: 'json',
success: function (json) { success: function (json) {
$.each(json.results, function (i, v) { $.each(json.results, function (i, v) {
@ -531,7 +540,7 @@
htmlInbox += '<div data-id="' + v.id + '" class="numberStepp box-sizing stage-block-approve"><div class="insetNumStepp">' + htmlInbox += '<div data-id="' + v.id + '" class="numberStepp box-sizing stage-block-approve"><div class="insetNumStepp">' +
'<p class="titleNumStepp"><span>Этап ' + v.pos + '</span>' + v.name + '</p>' + '<p class="titleNumStepp"><span>Этап ' + v.pos + '</span>' + v.name + '</p>' +
'<p class="textNumStepp">Результаты этапа:' + v.result + '</p><div>' + '<p class="textNumStepp">Результаты этапа:' + v.result + '</p><div>' +
'<p>' + v.term + '</p><span>' + v.cost + '<i class="fa fa-rub"></i></span></div></div></div>'; '<p> до ' + v.term + '</p><span>' + v.cost + '<i class="fa fa-rub"></i></span></div></div></div>';
}); });
if (statusNotAgreed) { if (statusNotAgreed) {
@ -639,67 +648,7 @@
}); });
}); });
// Вытащить сообщения для конактов
$('.user-block').on('click', function () {
var userId = $(this).attr('data-id');
$("#contact-chat-form #recipentId").val(userId);
$("#add-form-contractor-note #recipentNoteContractor").val(userId);
$('.user-block').each(function () {
$(this).removeClass('mesAct');
});
$(this).addClass('mesAct');
var inbox = document.getElementById('message-chat-space');
inbox.innerHTML = '';
$.ajax({
url: '/api/message',
type: 'GET',
data: {
csrfmiddlewaretoken: csrftoken,
'operand': 'in',
'sender_id': currentChatUser,
'recipent_id': userId
},
dataType: 'json',
success: function (json) {
$.each(json.results, function (i, v) {
console.log(v.sender.id);
var senderName = 'Вы';
var className = 'youChat';
if (v.sender.id == userId) {
senderName = v.sender.username;
className = '';
}
inbox.innerHTML += '<div class="col-lg-12 insetCommChat ' + className + '"><div class="topCommChat">' +
'<p class="nameCommChat">' + senderName + '</p> <span>' + v.created + '</span></div>' +
'<p class="textCommChat">' + v.text + '</p></div>';
});
}
});
$.ajax({
url: '/api/note/',
type: 'GET',
data: {csrfmiddlewaretoken: csrftoken,
'operand': 'in',
'sender_id': currentChatUser,
'recipent_id': userId},
dataType: 'json',
success: function (json) {
console.log(json.results);
var noteHtmlInbox = '';
$.each(json.results, function (i, v) {
noteHtmlInbox += '<li>' + v.text + '<li>';
});
$(".contractor-notes-block").html(noteHtmlInbox);
}
});
});
//Добавить сообщение для исполнителей в группе //Добавить сообщение для исполнителей в группе
$("#add-team-chat-message").on('click', function () { $("#add-team-chat-message").on('click', function () {
var chatMessage = $("#team-chat-form #chatText").val(); var chatMessage = $("#team-chat-form #chatText").val();
var recipentId = $("#team-chat-form #recipentId").val(); var recipentId = $("#team-chat-form #recipentId").val();
@ -727,24 +676,6 @@
$("#document-send").html(""); $("#document-send").html("");
}); });
// Добавить сообщение для контакта
$('#contact-chat-add-message').on('click', function () {
var chatMessage = $("#chat").val();
var recipentId = $("#recipentId").val();
var senderId = $("#senderId").val();
socket.add_contact_message({
"format_type": "add_message_contact",
"data": {
"sender_id": senderId,
"recipent_id": recipentId,
"chat_message": chatMessage,
}
});
var inbox = $('#message-chat-space').html();
$("#chat").val("");
});
}); });
</script> </script>

@ -52,7 +52,7 @@
<a href="#" data-target="#userModal" data-toggle="modal" <a href="#" data-target="#userModal" data-toggle="modal"
class="conMess">Контакты</a> class="conMess">Контакты</a>
<span>0</span> <span class="contact-count-{{ contact.pk|add:request.user.pk }}">0</span>
<a href="#" class="deleteMess" data-recipent-id="{{ contact.pk }}"> <a href="#" class="deleteMess" data-recipent-id="{{ contact.pk }}">
Удалить контакт Удалить контакт
</a> </a>
@ -67,8 +67,8 @@
<form id="contact-chat-form"> <form id="contact-chat-form">
<input type="hidden" value="{{ request.user.pk }}" name="senderId" id="senderContactId"/> <input type="hidden" value="{{ request.user.pk }}" name="senderId" id="senderContactId"/>
<input type="hidden" name="recipentId" id="recipentContactId"> <input type="hidden" name="recipentId" id="recipentContactId">
<textarea id="chat" name="chat_message" class="box-sizing"></textarea> <textarea id="chat" name="chat_message" class="box-sizing"></textarea>
<p class="errorEmptyMessage" style="color: red;display:none;">Пустое сообщение нельзя отправить</p>
<div class="bunChat"> <div class="bunChat">
<div class="setChat box-sizing upload"> <div class="setChat box-sizing upload">
@ -137,6 +137,7 @@
<input type="hidden" name="recipentId" id="recipentId"> <input type="hidden" name="recipentId" id="recipentId">
<input type="hidden" name="orderId" id="orderId"> <input type="hidden" name="orderId" id="orderId">
<textarea id="chat" class="box-sizing"></textarea> <textarea id="chat" class="box-sizing"></textarea>
<p class="errorEmptyMessage" style="color: red;display:none;">Пустое сообщение нельзя отправить</p>
<div class="bunChat"> <div class="bunChat">
<div class="setChat box-sizing upload"> <div class="setChat box-sizing upload">
<input type="file" name="file" id="upload-document-order"> <input type="file" name="file" id="upload-document-order">
@ -192,6 +193,14 @@
</a> </a>
</div> </div>
<div class="col-lg-12 documentsChat">
<p>Входящие документы</p>
<ul id="documentOrderSpace"></ul>
{# <a href="javascript:void(0)">#}
{# Распечатать с помощью ресурса#}
{# </a>#}
</div>
<div class="textAreaBlock2 box-sizing disTab"> <div class="textAreaBlock2 box-sizing disTab">
<p>Для заметок</p> <p>Для заметок</p>
<textarea id="chat2"></textarea> <textarea id="chat2"></textarea>
@ -229,6 +238,12 @@
var currentChatUser = {{ request.user.pk }}; var currentChatUser = {{ request.user.pk }};
var form = document.getElementById('message_form'); var form = document.getElementById('message_form');
$('body').on('focus',".term-picker", function(){
$(this).datepicker({
minDate: 0,
});
})
$("#reserve-button").on("click",function(e) { $("#reserve-button").on("click",function(e) {
e.preventDefault(); e.preventDefault();
$("#reserve-stage-modal").modal('show'); $("#reserve-stage-modal").modal('show');
@ -279,7 +294,6 @@
}); });
$("#tab2").on("change","#stagesSelect", function(e){ $("#tab2").on("change","#stagesSelect", function(e){
var sumStage = $(this).find('option:selected').attr("data-stage-sum"); var sumStage = $(this).find('option:selected').attr("data-stage-sum");
$("#choiceWayStage").val(sumStage); $("#choiceWayStage").val(sumStage);
@ -313,7 +327,7 @@
'<label for="">Название</label><input class="form-control" name="name" type="text" />' + '<label for="">Название</label><input class="form-control" name="name" type="text" />' +
'<label for="">Цена</label><input class="form-control" name="cost" type="text" />' + '<label for="">Цена</label><input class="form-control" name="cost" type="text" />' +
'<input class="form-control orderStagesInput" name="order" type="hidden" value="' + orderId + '"/>' + '<input class="form-control orderStagesInput" name="order" type="hidden" value="' + orderId + '"/>' +
'<label for="">Срок</label><input class="form-control" name="term" type="text" />' + '<label for="">Срок</label><input class="term-picker form-control datepicker" name="term" type="text" />' +
'<label for="">Результат</label><input class="form-control" name="result" type="text" />' + '<label for="">Результат</label><input class="form-control" name="result" type="text" />' +
'<input class="form-control" name="pos" value="1" type="hidden" />' + '<input class="form-control" name="pos" value="1" type="hidden" />' +
'</form></div>'; '</form></div>';
@ -342,7 +356,7 @@
'<label for="">Название</label><input class="form-control" type="text" name="name" value="' + v.name + '" />' + '<label for="">Название</label><input class="form-control" type="text" name="name" value="' + v.name + '" />' +
'<label for="">Цена</label><input class="form-control" type="text" name="cost" value="' + v.cost + '" />' + '<label for="">Цена</label><input class="form-control" type="text" name="cost" value="' + v.cost + '" />' +
'<input class="form-control orderStagesInput" type="hidden" name="order" value="' + v.order + '"/>' + '<input class="form-control orderStagesInput" type="hidden" name="order" value="' + v.order + '"/>' +
'<label for="">Срок</label><input class="form-control" type="text" name="term" value="' + v.term + '" />' + '<label for="">Срок</label><input class="term-picker form-control datepicker" type="text" name="term" value="' + v.term + '" />' +
'<label for="">Результат</label><input class="form-control" type="text" name="result" value="' + v.result + '" />' + '<label for="">Результат</label><input class="form-control" type="text" name="result" value="' + v.result + '" />' +
'</form></div>'; '</form></div>';
} else { } else {
@ -358,14 +372,11 @@
}); });
if (statusNotAgreed) { if (statusNotAgreed) {
var orderSecureCheckbox = ''; if(!data.secure) {
if(data.secure) { htmlInbox += '<div class="box-sizing disTab">' +
orderSecureCheckbox = "checked"; '<div class="checkbox"><input name="secure" id="secureOrder" type="checkbox" style="opacity:1">' +
}
htmlInbox += '<div class="box-sizing disTab">' +
'<div class="checkbox"><input name="secure" id="secureOrder" '+ orderSecureCheckbox +' type="checkbox" style="opacity:1">' +
'Перейти в режим безопасной сделки</div></div>'; 'Перейти в режим безопасной сделки</div></div>';
}
htmlInbox +='<div class="textAreaBlock2 box-sizing disTab">' + htmlInbox +='<div class="textAreaBlock2 box-sizing disTab">' +
'<a href="#" data-sender-id="' + senderId +'" ' + '<a href="#" data-sender-id="' + senderId +'" ' +
@ -447,7 +458,6 @@
}); });
}); });
// Добавление этапов // Добавление этапов
$("#order-stages").on('click', "#addStagesForm", function (e) { $("#order-stages").on('click', "#addStagesForm", function (e) {
e.preventDefault(); e.preventDefault();
@ -554,7 +564,7 @@
'<label for="">Название</label><input class="form-control" name="name" type="text" />' + '<label for="">Название</label><input class="form-control" name="name" type="text" />' +
'<label for="">Цена</label><input class="form-control" name="cost" type="text" />' + '<label for="">Цена</label><input class="form-control" name="cost" type="text" />' +
'<input class="form-control orderStagesInput" name="order" type="hidden" value="' + orderId + '" />' + '<input class="form-control orderStagesInput" name="order" type="hidden" value="' + orderId + '" />' +
'<label for="">Срок</label><input class="form-control" name="term" type="text" />' + '<label for="">Срок</label><input class="term-picker form-control datepicker" name="term" type="text" />' +
'<label for="">Результат</label><input class="form-control" name="result" type="text" />' + '<label for="">Результат</label><input class="form-control" name="result" type="text" />' +
'<input class="form-control" name="pos" value="' + pos + '" type="hidden" />' '<input class="form-control" name="pos" value="' + pos + '" type="hidden" />'
'</form></div>'; '</form></div>';
@ -598,44 +608,7 @@
$("#chat-order-add #recipentId").val(recipentId); $("#chat-order-add #recipentId").val(recipentId);
$(".orderStagesInput").val(orderId); $(".orderStagesInput").val(orderId);
var inbox = document.getElementById('message-chat-order-space'); var inbox = document.getElementById('message-chat-order-space');
inbox.innerHTML = ''; var docList = document.getElementById('documentOrderSpace');
$.ajax({
url: '/api/message',
type: 'GET',
data: {csrfmiddlewaretoken: csrftoken, 'order': orderId},
dataType: 'json',
success: function (json) {
$.each(json.results, function (i, v) {
var senderName = 'Вы';
var className = 'youChat';
if (v.sender.id !== currentChatUser) {
senderName = v.sender.username;
className = '';
}
inbox.innerHTML += '<div class="col-lg-12 insetCommChat ' + className + '"><div class="topCommChat">' +
'<p class="nameCommChat">' + senderName + '</p><span>' + v.created + '</span></div>' +
'<p class="textCommChat">' + v.text + '</p></div>';
});
}
});
getStages(orderId,userId,recipentId, secureOrder);
});
// Вытащить сообщения для конактов
$('.user-block').on('click', function () {
var userId = $(this).attr('data-id');
$("#contact-chat-form #recipentContactId").val(userId);
$("#add-form-contractor-note #recipentNoteContractor").val(userId);
$('.user-block').each(function () {
$(this).removeClass('mesAct');
});
$(this).addClass('mesAct');
var inbox = document.getElementById('message-chat-space');
var docList = document.getElementById('documentSpace');
inbox.innerHTML = ''; inbox.innerHTML = '';
docList.innerHTML = ''; docList.innerHTML = '';
@ -644,68 +617,42 @@
type: 'GET', type: 'GET',
data:{ data:{
csrfmiddlewaretoken: csrftoken, csrfmiddlewaretoken: csrftoken,
'operand': 'in', 'order': orderId
'sender_id': currentChatUser,
'recipent_id': userId
}, },
dataType: 'json', dataType: 'json',
success: function (json){ success: function (json){
console.log(json); console.log(json);
$.each(json.results, function (i, v) { $.each(json.results, function (i, v) {
docList.innerHTML += '<li style="word-break: break-all;">'+ v.file+'<div></div></li>'; docList.innerHTML += '<li style="word-break: break-all;">'+ v.file+'</li>';
}); });
}, },
error: function(e){ error: function(e){
console.log(e); console.log(e);
} }
}); });
$.ajax({ $.ajax({
url: '/api/message', url: '/api/message',
type: 'GET', type: 'GET',
data: { data: {csrfmiddlewaretoken: csrftoken, 'order': orderId,'team__isnull': 'true'},
csrfmiddlewaretoken: csrftoken,
'operand': 'in',
'sender_id': currentChatUser,
'recipent_id': userId
},
dataType: 'json', dataType: 'json',
success: function (json) { success: function (json) {
$.each(json.results, function (i, v) { $.each(json.results, function (i, v) {
var senderName = 'Вы'; var senderName = 'Вы';
var className = 'youChat'; var className = 'youChat';
if (v.sender.id == userId) {
if (v.sender.id !== currentChatUser) {
senderName = v.sender.username; senderName = v.sender.username;
className = ''; className = '';
} }
inbox.innerHTML += '<div class="col-lg-12 insetCommChat ' + className + '"><div class="topCommChat">' +
'<p class="nameCommChat">' + senderName + '</p> <span>' + v.created + '</span></div>' + inbox.innerHTML += '<div class="col-lg-12 insetCommChat ' + className + '"><div class="topCommChat">' +
'<p class="nameCommChat">' + senderName + '</p><span>' + v.created + '</span></div>' +
'<p class="textCommChat">' + v.text + '</p></div>'; '<p class="textCommChat">' + v.text + '</p></div>';
}); });
} }
}); });
getStages(orderId,userId,recipentId, secureOrder);
});
$('#contact-chat-add-message').on('click', function (e) {
e.preventDefault();
var chatMessage = $("#chat").val();
var recipentId = $("#recipentContactId").val();
var senderId = $("#senderContactId").val();
socket.add_contact_message({
"format_type": "add_message_contact",
"data": {
"sender_id": senderId,
"recipent_id": recipentId,
"chat_message": chatMessage,
}
});
$("#chat").val("");
$("#document-send-contact").html("");
}); });

@ -55,7 +55,7 @@ class ChatUserView(LoginRequiredMixin, View):
contacts_users = User.objects.filter(pk__in=users_ids) contacts_users = User.objects.filter(pk__in=users_ids)
chat_messages = Message.objects.filter(Q(sender=request.user.pk) | Q(recipent=request.user.pk)) 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) orders = request.user.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) transaction = Transaction.objects.get_or_create(customer=request.user, type='reservation', complete=False)
self.template_name = 'chat_customer.html' self.template_name = 'chat_customer.html'
return render(request, self.template_name, {'contacts_users': contacts_users, return render(request, self.template_name, {'contacts_users': contacts_users,
@ -65,7 +65,15 @@ class ChatUserView(LoginRequiredMixin, View):
'YANDEX_MONEY': settings.YANDEX_MONEY, 'YANDEX_MONEY': settings.YANDEX_MONEY,
}) })
else: else:
orders = request.user.orders.all() team_ids = []
if request.user.is_owner_team():
team_ids.append(request.user.team.pk)
team_orders = request.user.team.orders.all()
else:
teams = Team.objects.filter(contractors__id=request.user.pk).all()
team_orders = Order.objects.filter(team_id__in=[team.pk for team in teams]).all()
orders = Order.objects.filter(Q(contractor=request.user) | Q(team_id__in=team_ids)).all()
contractor_contacts = Message.objects.values_list('sender_id', 'recipent_id').filter( contractor_contacts = Message.objects.values_list('sender_id', 'recipent_id').filter(
Q(recipent_id=request.user.pk) | Q(sender_id=request.user.pk)).filter(Q(team_id=None)).distinct() Q(recipent_id=request.user.pk) | Q(sender_id=request.user.pk)).filter(Q(team_id=None)).distinct()
users_ids = [] users_ids = []
@ -81,11 +89,7 @@ class ChatUserView(LoginRequiredMixin, View):
chat_messages = Message.objects.filter(Q(sender=request.user.pk) | Q(recipent=request.user.pk)).order_by( chat_messages = Message.objects.filter(Q(sender=request.user.pk) | Q(recipent=request.user.pk)).order_by(
'created') 'created')
if request.user.is_owner_team():
team_orders = request.user.team.orders.all()
else:
teams = Team.objects.filter(contractors__id=request.user.pk).all()
team_orders = Order.objects.filter(team_id__in=[team.pk for team in teams]).all()
self.template_name = 'chat_contractor.html' self.template_name = 'chat_contractor.html'
return render(request, self.template_name, {'orders': orders, return render(request, self.template_name, {'orders': orders,

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-08-29 14:51
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('projects', '0017_arbitration'),
]
operations = [
migrations.AlterField(
model_name='portfolio',
name='created',
field=models.DateTimeField(auto_created=True, auto_now_add=True),
),
]

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-08-29 14:58
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('projects', '0018_auto_20160829_1751'),
]
operations = [
migrations.RemoveField(
model_name='stage',
name='term',
),
]

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-08-29 15:02
from __future__ import unicode_literals
import datetime
from django.db import migrations, models
from django.utils.timezone import utc
class Migration(migrations.Migration):
dependencies = [
('projects', '0019_remove_stage_term'),
]
operations = [
migrations.AddField(
model_name='stage',
name='term',
field=models.DateTimeField(auto_now_add=True, default=datetime.datetime(2016, 8, 29, 15, 2, 54, 818311, tzinfo=utc)),
preserve_default=False,
),
]

@ -251,7 +251,7 @@ class Stage(models.Model):
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
order = models.ForeignKey(Order, related_name='stages') order = models.ForeignKey(Order, related_name='stages')
result = models.CharField(max_length=255) result = models.CharField(max_length=255)
term = models.IntegerField(default=0) term = models.DateTimeField(auto_now_add=True)
term_type = models.CharField(max_length=10, choices=TERMS, default='hour') term_type = models.CharField(max_length=10, choices=TERMS, default='hour')
status = models.CharField(choices=STATUSES, max_length=30, default='not_agreed') status = models.CharField(choices=STATUSES, max_length=30, default='not_agreed')
created = models.DateTimeField(default=timezone.now) created = models.DateTimeField(default=timezone.now)

@ -1,3 +1,4 @@
from rest_framework import serializers
from generic_relations.relations import GenericRelatedField from generic_relations.relations import GenericRelatedField
from rest_framework.serializers import ModelSerializer, ImageField, FileField, SerializerMethodField, PrimaryKeyRelatedField from rest_framework.serializers import ModelSerializer, ImageField, FileField, SerializerMethodField, PrimaryKeyRelatedField
@ -49,7 +50,7 @@ class RealtySerializer(ModelSerializer):
class StageSerializer(ModelSerializer): class StageSerializer(ModelSerializer):
# order = OrderSerializer() term = serializers.DateTimeField(format="%d-%m-%Y")
class Meta: class Meta:
model = Stage model = Stage
@ -72,17 +73,6 @@ class StageSerializer(ModelSerializer):
) )
# def update(self, inst, validated_data):
# import code; code.interact(local=dict(globals(), **locals()))
# inst.id = validated_data.get('id',inst.id)
# inst.name = validated_data.get('name', inst.name)
# inst.cost = validated_data.get('cost', inst.cost)
# inst.order = validated_data.get('order', inst.order)
# inst.result = validated_data.get('result', inst.result)
# inst.save()
# return inst
class OrderSerializer(ModelSerializer): class OrderSerializer(ModelSerializer):
stages = StageSerializer(many=True, read_only=True) stages = StageSerializer(many=True, read_only=True)

@ -76,9 +76,12 @@
<td> <td>
<div class="tableButtons disTab"> <div class="tableButtons disTab">
<a href="{% url 'chat:chat-user' %}"> <form action="{% url 'projects:customer-offer-order' answer_id=cand.answer.pk project_id=cand.project.pk %}" method="POST" novalidate>
<div class="btnTab btnTab1"></div> {% csrf_token %}
</a> <a href="#" onclick="$(this).closest('form').submit(); return false">
<div class="btnTab btnTab1"></div>
</a>
</form>
<a href="{% url 'chat:chat-user' %}?user_id={{ cand.answer.author.pk }}"> <a href="{% url 'chat:chat-user' %}?user_id={{ cand.answer.author.pk }}">
<div class="btnTab btnTab2"></div> <div class="btnTab btnTab2"></div>

@ -708,7 +708,11 @@
</div> </div>
<div class="col-lg-3 retts"> <div class="col-lg-3 retts">
{% ratings_widget answer.author.pk 'restList2' %} {% if answer.author|class_name == 'User' %}
{% ratings_widget answer.author.pk 'restList2' %}
{% elif answer.author|class_name == 'Team'%}
{% ratings_team_widget answer.author.pk 'restList2' %}
{% endif %}
{% if answer.author|class_name == 'User' and answer.author.cro %} {% if answer.author|class_name == 'User' and answer.author.cro %}
<div class="sroUser sroExecutor"> <div class="sroUser sroExecutor">

@ -594,9 +594,9 @@ class ProjectComparisonView(DetailView):
model = Project model = Project
template_name = 'comparison.html' template_name = 'comparison.html'
def get_context_data(self, **kwargs): # def get(self, request, **kwargs):
context = super().get_context_data() # self.object = self.get_object()
return context
def add_candidate(request, answer_id, project_id): def add_candidate(request, answer_id, project_id):

@ -97,7 +97,15 @@
sock.onmessage = function (event) { sock.onmessage = function (event) {
var notificationData = JSON.parse(event.data); var notificationData = JSON.parse(event.data);
$.jGrowl("Вам пришло новое сообщение!" + notificationData.msg, {sticky: true}); console.log(notificationData);
var outMessage = "";
if (notificationData.answer_type == 'add_message_contact'){
outMessage += "<a href='/chat/?user_id=" + notificationData.sender_id + "'>"+ notificationData.msg +"<a>";
}else if((notificationData.answer_type == 'approve_stages') || (notificationData.answer_type == 'add_message_order')){
outMessage += "<a href='/chat/#order" + notificationData.order_id + "'>"+ notificationData.msg +"<a>";
}
$.jGrowl("Вам пришло новое сообщение!<br />" + outMessage, { life: 15000});
}; };
} }
}; };

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-08-29 14:40
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('work_sell', '0006_remove_worksell_team'),
]
operations = [
migrations.AlterField(
model_name='worksell',
name='created',
field=models.DateTimeField(auto_now_add=True),
),
]
Loading…
Cancel
Save