#ARC-16 Fixes bugs

remotes/origin/PR-39
Mukhtar 9 years ago
parent c9440bf5b5
commit aa673dd9f2
  1. 174
      assets/js/chat.js
  2. 568
      assets/js/chat_contractor.js
  3. 22
      chat/migrations/0012_notes_team.py
  4. 22
      chat/migrations/0013_auto_20160907_1556.py
  5. 3
      chat/models.py
  6. 5
      chat/serializers.py
  7. 570
      chat/templates/chat_contractor.html
  8. 46
      chat/templates/chat_customer.html
  9. 7
      chat/templates/contact-info.html
  10. 2
      chat/templates/order_info.html
  11. 3
      chat/urls.py
  12. 13
      chat/views.py
  13. 19
      common/migrations/0014_auto_20160907_1101.py
  14. 6
      users/serializers.py
  15. 391
      users/templates/contractor_office_chat_projects.html

@ -19,7 +19,7 @@ var SocketHandler = function () {
var inboxClass = document.getElementsByClassName('contact-space' + sumSenderRecipent);
if (inboxClass.length > 0) {
inbox = inboxClass[0];
}else{
} else {
$(".contact-count-" + sumSenderRecipent).text(parseInt($(".contact-count-" + sumSenderRecipent).text()) + 1);
}
} else if (message.answer_type == 'order' || message.answer_type == 'add_message_order') {
@ -52,7 +52,6 @@ var SocketHandler = function () {
var height = inbox.scrollHeight;
inbox.scrollTop = height;
inbox.animate({scrollTop: height});
}
};
@ -115,7 +114,6 @@ var csrftoken = getCookie('csrftoken');
$(function () {
var currentHash = URI(location.href).hash();
if (currentHash.indexOf("#order") == 0) {
var ordHashId = currentHash.replace("#order", "");
setTimeout(function () {
@ -125,53 +123,84 @@ $(function () {
} else if (currentHash.indexOf("#team") == 0) {
} else {
setTimeout(function () {
$(".user-block").first().trigger('click');
}, 10);
setTimeout(function () {
$(".order-block").first().trigger('click');
}, 500);
}
$(".full-order-info").click('on', function (e) {
e.preventDefault();
e.stopPropagation();
var orderId = $(this).closest('.orderBlock').attr('data-id');
$.ajax({
url: '/api/orders/' + orderId + '/',
data: {
csrfmiddlewaretoken: csrftoken,
},
dataType: 'json',
success: function (data) {
var outTable = '';
outTable += '<tr><td>Название</td><td>' + data.project.name + '</td>';
outTable += '<tr><td>Безопасная сделка</td><td>' + data.secure + '</td>';
if (data.project.realty) {
outTable += '<tr><td>Тип здания</td><td>' + data.project.realty.building_classification.name + '</td>';
outTable += '<tr><td>Классификация здания</td><td>' + data.project.realty.construction_type.name + '</td>';
}
$("#order-info table").html(outTable);
$("#order-info").modal('show');
},
error: function (e, jqxhr) {
console.log(e);
}
});
});
$(".conMess").click('on', function (e) {
e.preventDefault();
e.stopPropagation();
$(".full-order-info").click('on',function(e){
e.preventDefault();
e.stopPropagation();
var orderId = $(this).closest('.orderBlock').attr('data-id');
$.ajax({
url: '/api/orders/' + orderId + '/',
data: {
csrfmiddlewaretoken: csrftoken,
},
dataType: 'json',
success: function(data){
var outTable = '';
outTable += '<tr><td>Название</td><td>'+data.project.name +'</td>';
outTable += '<tr><td>Безопасная сделка</td><td>'+data.secure +'</td>';
if(data.project.realty) {
outTable += '<tr><td>Тип здания</td><td>' + data.project.realty.building_classification.name + '</td>';
outTable += '<tr><td>Классификация здания</td><td>' + data.project.realty.construction_type.name + '</td>';
}
$("#order-info table").html(outTable);
$("#order-info").modal('show');
},
error: function(e,jqxhr){
console.log(e);
}
});
});
var userId = $(this).attr('data-id');
$.ajax({
url: '/api/users/' + userId + '/',
data: {
csrfmiddlewaretoken: csrftoken,
},
dataType: 'json',
success: function (data) {
var outTable = '';
if(data.username) {
outTable += '<tr><td>Ник</td><td>' + data.username + '</td>';
}
if(data.fio) {
outTable += '<tr><td>Ф.И.О</td><td>' + data.fio + '</td>';
}
if(data.skype) {
outTable += '<tr><td>Skype</td><td>'+ data.skype +'</td>';
}
if(data.website) {
outTable += '<tr><td>Сайт</td><td>'+ data.website +'</td>';
}
if(data.phone) {
outTable += '<tr><td>Телефон</td><td>'+ data.phone +'</td>';
}
$(".conMess").click('on',function(e){
e.preventDefault();
e.stopPropagation();
$("#contact-info table").html(outTable);
$("#contact-info").modal('show');
console.log(data);
},
error: function (e, jqxhr) {
console.log(e);
}
});
});
$("#paymentfromSite").on('click',function(){
$("#paymentfromSite").on('click', function () {
var sum = $("#stageSumPay").val();
var stages = $("#stagesIds").val();
var orderId = $("#ordermodalId").val();
@ -185,31 +214,31 @@ $(function () {
},
dataType: 'json',
success: function (json) {
if(json.status == 'ok'){
if (json.status == 'ok') {
$("#reserve-stage-modal").modal('hide');
$("#orderBlock" + orderId).trigger('click');
}
},
error: function(e, jqxhr){
error: function (e, jqxhr) {
console.log(e);
}
})
});
//Удаление документа
$('.tab-content').on('click','.remove-document', function(e){
$('.tab-content').on('click', '.remove-document', function (e) {
e.preventDefault();
var dataId = $(this).attr('data-id');
var _this = $(this);
$.ajax({
url: '/api/documents/' + dataId +'/',
url: '/api/documents/' + dataId + '/',
type: 'PATCH',
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
},
data: {is_delete:true},
data: {is_delete: true},
dataType: 'json',
success: function(json){
success: function (json) {
_this.parent().remove();
console.log(json);
},
@ -234,7 +263,7 @@ $(function () {
var sumSenderRecipent = parseInt(userId) + parseInt(contactId);
$("#message-chat-space").removeClass().addClass("contact-space" + sumSenderRecipent);
$(".contact-count-"+ sumSenderRecipent).text(0);
$(".contact-count-" + sumSenderRecipent).text(0);
var docList = document.getElementById('documentSpace');
inbox.innerHTML = '';
docList.innerHTML = '';
@ -256,7 +285,7 @@ $(function () {
console.log(json);
$.each(json.results, function (i, v) {
docList.innerHTML += '<li style="word-break: break-all;"><a class="file-link" href="'+ v.file_url +'">' + v.file + '</a><div class="remove-document" data-id="'+ v.id+'" style="right:-10px;"></div></li>';
docList.innerHTML += '<li style="word-break: break-all;"><a class="file-link" href="/chat/download/' + v.file + '">' + v.file + '</a><div class="remove-document" data-id="' + v.id + '" style="right:-10px;"></div></li>';
});
},
error: function (e) {
@ -343,7 +372,6 @@ $(function () {
});
});
$('#add-note-contractor').on('click', function (e) {
e.preventDefault();
$.ajax({
@ -366,6 +394,50 @@ $(function () {
});
});
//Добавить заметку.
$('#add-note-button').on('click', function (e) {
e.preventDefault();
$.ajax({
url: '/api/note/',
type: 'POST',
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
},
data: $("#add-form-order-note").serialize(),
dataType: 'json',
success: function (json) {
$("<li>"+ json.text +"</li>").appendTo(".order-notes-block");
$("#add-form-order-note #chat2").val("");
},
error: function (e) {
console.log('error');
console.log(e);
}
});
});
//Добавить заметку.
$('#add-team-note-button').on('click', function (e) {
e.preventDefault();
$.ajax({
url: '/api/note/',
type: 'POST',
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
},
data: $("#add-form-team-note").serialize(),
dataType: 'json',
success: function (json) {
$("<li>"+ json.text +"</li>").appendTo(".team-notes-block");
$("#add-form-team-note #chat2").val("");
},
error: function (e) {
console.log('error');
console.log(e);
}
});
});
// Добавление сообщения для заказа.
$('#order-chat-add-message').on('click', function (e) {
e.preventDefault();
@ -377,7 +449,7 @@ $(function () {
if (chatMessage) {
var sendLinks = $("#document-send-order a");
var sendLinkIds = "";
$.each(sendLinks, function(i, v){
$.each(sendLinks, function (i, v) {
sendLinkIds += $(this).attr('data-id') + ';';
});
socket.add_contact_message({
@ -409,7 +481,7 @@ $(function () {
$("#contact-chat-form .errorEmptyMessage").hide();
var sendLinks = $("#document-send-contact a");
var sendLinkIds = "";
$.each(sendLinks, function(i, v){
$.each(sendLinks, function (i, v) {
sendLinkIds += $(this).attr('data-id') + ';';
});
console.log(sendLinkIds);
@ -509,10 +581,10 @@ $(function () {
dataType: 'json',
done: function (e, data) {
$.each(data.result.files, function (index, file) {
// var currentValue = '';
// currentValue += file.id + ';';
// var currentValue = '';
// currentValue += file.id + ';';
//$("#documentSendIds").val(currentValue);
var htmlImg = '<a href="'+ file.url+'" class="send-doc" data-id="'+ file.id +'">' + file.name + '</a><br />';
var htmlImg = '<a href="' + file.url + '" class="send-doc" data-id="' + file.id + '">' + file.name + '</a><br />';
var document_send = $(htmlImg).appendTo("#document-send-order");
});
},
@ -555,7 +627,7 @@ $(function () {
dataType: 'json',
done: function (e, data) {
$.each(data.result.files, function (index, file) {
var htmlImg = '<a href="'+ file.url+'" class="send-doc" data-id="'+ file.id +'">' + file.name + '</a>';
var htmlImg = '<a href="' + file.url + '" class="send-doc" data-id="' + file.id + '">' + file.name + '</a>';
var document_send = $(htmlImg).appendTo("#document-send-contact");
});
},

@ -0,0 +1,568 @@
$(function () {
var form = document.getElementById('message_form');
setTimeout(function () {
$(".team-order-block").first().trigger('click');
}, 1000);
var url = '/chat/create/';
$("#upload-document-team").bind('fileuploadsubmit', function (e, data) {
data.formData = {
sender: $("#team-chat-form #senderTeamId").val(),
recipent: $("#team-chat-form #recipentTeamId").val(),
order: $("#team-chat-form #orderTeamId").val(),
team: $("#team-chat-form #teamId").val(),
}
console.log(data.formData);
});
//Загрузка документов
$('#upload-document-team').fileupload({
url: url,
crossDomain: false,
beforeSend: function (xhr, settings) {
$('#progress .progress-bar').css(
'width',
'0%'
);
if (!csrfSafeMethod(settings.type)) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
},
dataType: 'json',
done: function (e, data) {
$.each(data.result.files, function (index, file) {
var currentValue = $("#documentSendIds").val();
currentValue += file.id + ';';
$("#documentSendIds").val(currentValue);
var htmlImg = '<a href="' + file.url + '" class="send-doc" data-id="' + file.id + '">' + file.name + '</a>';
var document_send = $(htmlImg).appendTo("#document-send");
});
},
fail: function (e) {
console.log(e);
},
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#progress .progress-bar').css(
'width',
progress + '%'
);
}
}).prop('disabled', !$.support.fileInput)
.parent().addClass($.support.fileInput ? undefined : 'disabled');
// Согласование этапов
$("#order-stages").on('click', "#approve-stages", function (e) {
e.preventDefault();
$(".stage-block-approve").each(function () {
var stageId = $(this).attr('data-id');
$.ajax({
url: '/api/stages/' + stageId + '/',
type: 'PATCH',
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
},
data: "status=in_process",
dataType: 'json',
success: function (json) {
console.log(json);
},
error: function (e) {
console.log('error');
console.log(e);
}
});
});
var orderId = $(this).attr('data-order-id');
socket.send_stages_approve({
"format_type": "approve_stages",
"data": {
"sender_id": $(this).attr('data-sender-id'),
"recipent_id": $(this).attr('data-recipent-id'),
"order_id": orderId,
"msg": "Исполнитель согласовал этапы для заказа " + orderId,
}
});
});
// Согласование этапов
$("#order-stages").on('click', "#cancel-stages", function (e) {
e.preventDefault();
$(".stage-block-approve").each(function () {
var stageId = $(this).attr('data-id');
$.ajax({
url: '/api/stages/' + stageId + '/',
type: 'PATCH',
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
},
data: "status=cancel_approve",
dataType: 'json',
success: function (json) {
console.log(json);
},
error: function (e) {
console.log('error');
console.log(e);
}
});
});
var orderId = $(this).attr('data-order-id');
socket.send_stages_approve({
"format_type": "approve_stages",
"data": {
"sender_id": $(this).attr('data-sender-id'),
"recipent_id": $(this).attr('data-recipent-id'),
"order_id": orderId,
"msg": "Исполнитель отказался от текущих этапов " + orderId,
}
});
});
$(".team-chat-user").on('click', function (e) {
e.stopPropagation();
var recipentId = $(this).attr('data-id');
$("#team-chat-form #recipentTeamId").val(recipentId);
});
$(".team-order-block").on('click', function () {
$('.team-order-block, .team-block').each(function () {
$(this).removeClass('orAct');
});
$(this).addClass('orAct');
var teamId = $(this).attr('data-team-id');
var orderId = $(this).attr('data-order-id');
$("#team-chat-form #teamId").val(teamId);
$("#team-chat-form #orderTeamId").val(orderId);
$("#add-form-team-note #teamNote").val(teamId);
$("#add-form-team-note #orderNote").val(orderId);
var inbox = document.getElementById('message-chat-team-space');
inbox.innerHTML = '';
var docList = document.getElementById('documentTeamSpace');
docList.innerHTML = '';
$.ajax({
url: '/api/message',
type: 'GET',
data: {csrfmiddlewaretoken: csrftoken, 'team': teamId, 'order': orderId},
dataType: 'json',
success: function (json) {
$.each(json.results, function (i, v) {
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>';
});
var height = inbox.scrollHeight;
inbox.scrollTop = height;
}
});
$.ajax({
url: '/api/documents',
type: 'GET',
data: {
csrfmiddlewaretoken: csrftoken,
'order': orderId,
'team': teamId,
'is_delete': false,
'is_send': true,
},
dataType: 'json',
success: function (json) {
$.each(json.results, function (i, v) {
docList.innerHTML += '<li style="word-break: break-all;"><a class="file-link" href="/chat/download/' + v.file + '">' + v.file + '</a><div class="remove-document" data-id="' + v.id + '" style="right:-10px;"></div></li>';
});
},
error: function (e) {
console.log(e);
}
});
$.ajax({
url: '/api/note/',
type: 'GET',
data: {csrfmiddlewaretoken: csrftoken, 'order': orderId, 'team': teamId},
dataType: 'json',
success: function (json) {
console.log(json.results);
var noteHtmlInbox = '';
$.each(json.results, function (i, v) {
noteHtmlInbox += '<li>' + v.text + '<li>';
});
$(".team-notes-block").html(noteHtmlInbox);
}
});
});
$('.team-block').on('click', function () {
$('.team-order-block, .team-block').each(function () {
$(this).removeClass('orAct');
});
$(this).addClass('orAct');
var inbox = document.getElementById('message-chat-team-space');
inbox.innerHTML = '';
var docList = document.getElementById('documentTeamSpace');
docList.innerHTML = '';
var teamId = $(this).attr('data-team-id');
$("#team-chat-form #teamId").val(teamId);
$("#add-form-team-note #teamNote").val(teamId);
$("#team-chat-form #orderTeamId").val("");
$("#add-form-team-note #orderNote").val("");
$.ajax({
url: '/api/message',
type: 'GET',
data: {csrfmiddlewaretoken: csrftoken, 'team': teamId, 'order__isnull': 'true'},
dataType: 'json',
success: function (json) {
$.each(json.results, function (i, v) {
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>';
});
var height = inbox.scrollHeight;
inbox.scrollTop = height;
}
});
$.ajax({
url: '/api/documents',
type: 'GET',
data: {
csrfmiddlewaretoken: csrftoken,
'team': teamId,
'is_delete': false,
'is_send': true,
},
dataType: 'json',
success: function (json) {
$.each(json.results, function (i, v) {
docList.innerHTML += '<li style="word-break: break-all;"><a class="file-link" href="/chat/download/' + v.file + '">' + v.file + '</a><div class="remove-document" data-id="' + v.id + '" style="right:-10px;"></div></li>';
});
},
error: function (e) {
console.log(e);
}
});
$.ajax({
url: '/api/note/',
type: 'GET',
data: {csrfmiddlewaretoken: csrftoken, 'team': teamId},
dataType: 'json',
success: function (json) {
console.log(json.results);
var noteHtmlInbox = '';
$.each(json.results, function (i, v) {
noteHtmlInbox += '<li>' + v.text + '<li>';
});
$(".team-notes-block").html(noteHtmlInbox);
}
});
});
// Вытащить сообщения для чата заказа
$('.order-block').on('click', function () {
$('.order-block').each(function () {
$(this).removeClass('orAct');
});
$(this).addClass('orAct');
var orderId = $(this).attr('data-id');
var recipentId = $(this).attr('data-recipent-id');
var projectId = $(this).attr('data-project-id');
$("#chat-order-add #orderId").val(orderId);
$("#add-form-order-note #orderNote").val(orderId);
$("#orderArbitrationId").val(orderId);
$("#projectReviewId").val(projectId);
$("#chat-order-add #recipentId").val(recipentId);
$("#targetCustomerId").val(recipentId);
$("#add-form-order-note #recipentNote").val(recipentId);
var docList = document.getElementById('documentOrderSpace');
var inbox = document.getElementById('message-chat-order-space');
inbox.innerHTML = '';
docList.innerHTML = '';
$.ajax({
url: '/api/message',
type: 'GET',
data: {csrfmiddlewaretoken: csrftoken, 'order': orderId, 'team__isnull': 'true'},
dataType: 'json',
success: function (json) {
$.each(json.results, function (i, v) {
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>';
});
var height = inbox.scrollHeight;
inbox.scrollTop = height;
}
});
$.ajax({
url: '/api/documents',
type: 'GET',
data: {
csrfmiddlewaretoken: csrftoken,
'order': orderId,
'is_delete': false,
'is_send': true,
},
dataType: 'json',
success: function (json) {
$.each(json.results, function (i, v) {
docList.innerHTML += '<li style="word-break: break-all;"><a class="file-link" href="/chat/download/' + v.file + '">' + v.file + '</a><div class="remove-document" data-id="' + v.id + '" style="right:-10px;"></div></li>';
});
},
error: function (e) {
console.log(e);
}
});
$.ajax({
url: '/api/note/',
type: 'GET',
data: {csrfmiddlewaretoken: csrftoken, 'order': orderId},
dataType: 'json',
success: function (json) {
console.log(json.results);
var noteHtmlInbox = '';
$.each(json.results, function (i, v) {
noteHtmlInbox += '<li>' + v.text + '<li>';
});
$(".order-notes-block").html(noteHtmlInbox);
}
});
$.ajax({
url: '/api/orders/' + orderId + '/',
type: 'GET',
data: {csrfmiddlewaretoken: csrftoken},
dataType: 'json',
}).then(function (data) {
var htmlInbox = "";
var stagesReservedHtml = "";
var stagesPaidProcess = [];
var stagesInWork = [];
var stagesResults = data.stages;
var statusNotAgreed = false;
var stagesCompleted = [];
if (stagesResults.length > 0) {
$.each(stagesResults, function (i, v) {
if (v.status == "completed") {
stagesCompleted.push(v);
}
if (v.status == "not_agreed" || v.status == "send_approve") {
statusNotAgreed = true;
}
if (!data.secure) {
if (v.status == "in_process") {
stagesInWork.push(v);
}
} else if ((v.status == "in_process") && (v.is_paid)) {
stagesPaidProcess.push(v);
stagesInWork.push(v);
}
if (data.secure) {
if (v.is_paid) {
stagesReservedHtml += '<li class="reserved">Сумма за этап ' + v.pos + '.Зарезервирована.</li>';
} else {
stagesReservedHtml += '<li class="unreserved">Сумма за этап ' + v.pos + '.Не зарезервирована.</li>';
}
}
var statusName = '';
switch (v.status) {
case 'not_agreed':
statusName = 'Не согласован';
break;
case 'send_approve':
statusName = 'На согласовании';
break;
case 'cancel_approve':
statusName = 'Исполнитель отказался';
break;
case 'in_process':
statusName = 'В процессе';
break;
case 'completed':
statusName = 'Завершен';
break;
}
if (v.status == 'completed') {
statusName = 'Завершен';
}
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="textNumStepp">Результаты этапа:' + v.result + '</p><div>' +
'<p> до ' + v.term + '</p><span>' + v.cost + ' <i class="fa fa-rub"></i></span></div><div><p>' + statusName + '</p></div></div></div>';
});
if (statusNotAgreed) {
htmlInbox += '<div class="textAreaBlock2 FFD box-sizing disTab">' +
'<a id="approve-stages" data-sender-id="{{ request.user.pk }}" data-recipent-id="' + recipentId + '"' +
' data-order-id="' + orderId + '" href="#">согласовать</a>' +
'<a id="cancel-stages" data-sender-id="{{ request.user.pk }}" data-recipent-id="' + recipentId + '"' +
' data-order-id="' + orderId + '" href="#">отказаться</a>' +
'</div>';
}
}
$("#order-stages").html(htmlInbox);
$(".stages-paid").html(stagesReservedHtml);
if (data.secure) {
$("#reserveSpace").show();
} else {
$("#reserveSpace").hide();
}
if (stagesInWork.length > 0) {
$("#completeWork").show();
var stage = stagesInWork[0];
var stageWork = '<div class="numberStepp box-sizing">' +
'<div class="insetNumStepp"><div><p>В работе ' + stage.name + '</p></div>' +
'<div><p>Результат этапа : ' + stage.result + '</p></div>' +
'<div><p>Срок сдачи ' + stage.term + ' <span>' + stage.cost + '<i class="fa fa-rub"></i></span></p></div></div></div>';
if (!stage.close_contractor) {
stageWork += '<div class="textAreaBlock2 FFD box-sizing disTab"><a href="#" class="closeStage" data-sender-id="{{ request.user.pk }}" data-recipent-id="' + recipentId + '"' +
' data-order-id="' + data.id + '" data-stage-id="' + stage.id + '">Завершить этап</a></div>';
} else {
stageWork += '<div><p>Этап ожидает завершения статуса от заказчика</p><div>';
}
if (data.secure) {
stageWork += '<div class="textAreaBlock2 FFD box-sizing disTab"><a href="#" data-toggle="modal" data-target="#arbitration-add">Обратитьсяв арбитраж</a></div>';
}
$("#stagesWork").html(stageWork);
} else {
$("#completeWork").hide();
}
if (stagesCompleted.length == stagesResults.length && stagesCompleted.length > 0) {
$("#leaveReview").show();
}
if (data.status == 'completed') {
$("#leaveReview").hide();
}
});
});
$('#tab2').on('click', '.closeStage', function (e) {
e.preventDefault();
var stageId = $(this).attr('data-stage-id');
var _this = $(this);
$.ajax({
url: '/api/stages/' + stageId + '/',
type: 'PATCH',
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
},
data: "close_contractor=True",
dataType: 'json',
success: function (json) {
socket.send_stages_approve({
"format_type": "approve_stages",
"data": {
"sender_id": _this.attr('data-sender-id'),
"recipent_id": _this.attr('data-recipent-id'),
"order_id": _this.attr('data-order-id'),
"msg": "Исполнитель завершил этап " + json.name,
}
});
console.log(json);
},
error: function (e) {
console.log('error');
console.log(e);
}
});
});
//Добавить сообщение для исполнителей в группе
$("#add-team-chat-message").on('click', function (e) {
e.preventDefault();
var chatMessage = $("#team-chat-form #chatText").val();
var recipentId = $("#team-chat-form #recipentTeamId").val();
var senderId = $("#team-chat-form #senderTeamId").val();
var teamId = $("#team-chat-form #teamId").val();
var orderId = $("#team-chat-form #orderTeamId").val();
var documentSendIds = $("#documentSendIds").val();
if (chatMessage) {
var sendLinks = $("#document-send a");
var sendLinkIds = "";
$.each(sendLinks, function (i, v) {
sendLinkIds += $(this).attr('data-id') + ';';
});
socket.add_team_message({
"format_type": "add_message_team",
"data": {
"sender_id": senderId,
"recipent_id": recipentId,
"chat_message": chatMessage,
"team_id": teamId,
"order_id": orderId,
"document_send_links": sendLinkIds,
}
});
$("#team-chat-form #chatText").val("");
$("#document-send").html("");
$("#documentSendIds").val("");
}
});
});

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-09-07 08:01
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('users', '0015_user_phone2'),
('chat', '0011_documents_is_delete'),
]
operations = [
migrations.AddField(
model_name='notes',
name='team',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notes', to='users.Team'),
),
]

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-09-07 12:56
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 = [
('chat', '0012_notes_team'),
]
operations = [
migrations.AlterField(
model_name='notes',
name='recipent',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='recipent_notes', to=settings.AUTH_USER_MODEL),
),
]

@ -28,8 +28,9 @@ class Notes(models.Model):
text = models.TextField()
created = models.DateTimeField(default=timezone.now)
sender = models.ForeignKey(User, related_name='sender_notes')
recipent = models.ForeignKey(User, related_name='recipent_notes')
recipent = models.ForeignKey(User, related_name='recipent_notes', null=True, blank=True)
order = models.ForeignKey(Order, related_name='notes', null=True, blank=True)
team = models.ForeignKey(Team, related_name='notes', null=True, blank=True)
def __str__(self):
return self.text

@ -62,8 +62,8 @@ class MessageSerializer(ModelSerializer):
out = obj.text
documents = obj.documents.all()
if len(documents)>0:
documents_str = '<br />'.join(['<a target="_blank" href="'+doc.file.url+'">' + doc.file.name + '</a>' for doc in documents])
out += '<br />' + documents_str
documents_str = '<br>'.join(['Входящий файл: <br><a target="_blank" href="/chat/download/' + doc.file.name + '">' + doc.file.name + '</a>' for doc in documents])
out += '<br><br>' + documents_str
return out
@ -78,4 +78,5 @@ class NoteSerializer(ModelSerializer):
'order',
'sender',
'recipent',
'team',
)

@ -55,7 +55,7 @@
<div><a href="{{ contact_url }}" style="color:black;">{{ contact.username }}</a></div>
</p>
<a href="#" class="conMess">Контакты</a>
<a href="#" data-id="{{ contact.id }}" class="conMess">Контакты</a>
<span class="contact-count-{{ contact.pk|add:request.user.pk }}">0</span>
<a href="#" class="deleteMess" data-recipent-id="{{ contact.pk }}">
@ -213,14 +213,14 @@
</div>
<div class="textAreaBlock2 box-sizing disTab">
<ul class="notes-block">
<ul class="order-notes-block">
</ul>
<p>Для заметок</p>
<form id="add-form-order-note">
<textarea id="chat2" name="text"></textarea>
<input type="hidden" name="order" id="orderNote" value=""/>
<input type="hidden" name="sender" id="senderNote" value="{{ request.user.pk }}"/>
<input type="hidden" name="recipent" id="recipentNote" value=""/>
<input type="hidden" name="order" id="orderNote" value="">
<input type="hidden" name="sender" id="senderNote" value="{{ request.user.pk }}">
<input type="hidden" name="recipent" id="recipentNote" value="">
<a href="#" id="add-note-button">сохранить</a>
</form>
</div>
@ -336,16 +336,18 @@
</div>
<div class="textAreaBlock2 box-sizing disTab">
<ul class="notes-block">
<ul class="team-notes-block">
</ul>
<p>Для заметок</p>
<form id="add-form-team-note">
<textarea id="chat2" name="text"></textarea>
<input type="hidden" name="order" id="orderNote" value=""/>
<input type="hidden" name="order" id="orderNote">
<input type="hidden" name="sender" id="senderNote" value="{{ request.user.pk }}"/>
<input type="hidden" name="recipent" id="recipentNote" value=""/>
<a href="#" id="add-note-button">сохранить</a>
<input type="hidden" name="recipent" id="recipentNote">
<input type="hidden" name="team" id="teamNote">
<a href="#" id="add-team-note-button">сохранить</a>
</form>
</div>
</div>
</div>
@ -370,553 +372,5 @@
</script>
<script type="text/javascript" src='{% static "js/chat.js" %}'></script>
<script type="text/javascript">
$(function () {
var currentChatUser = {{ request.user.pk }};
var form = document.getElementById('message_form');
setTimeout(function () {
$(".team-order-block").first().trigger('click');
}, 1000);
var url = '/chat/create/';
$("#upload-document-team").bind('fileuploadsubmit', function (e, data) {
data.formData = {
sender: $("#team-chat-form #senderTeamId").val(),
recipent: $("#team-chat-form #recipentTeamId").val(),
order: $("#team-chat-form #orderTeamId").val(),
team: $("#team-chat-form #teamId").val(),
}
console.log(data.formData);
});
//Загрузка документов
$('#upload-document-team').fileupload({
url: url,
crossDomain: false,
beforeSend: function (xhr, settings) {
$('#progress .progress-bar').css(
'width',
'0%'
);
if (!csrfSafeMethod(settings.type)) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
},
dataType: 'json',
done: function (e, data) {
$.each(data.result.files, function (index, file) {
var currentValue = $("#documentSendIds").val();
currentValue += file.id + ';';
$("#documentSendIds").val(currentValue);
var htmlImg = '<a href="'+ file.url+'" class="send-doc" data-id="'+ file.id +'">' + file.name + '</a>';
var document_send = $(htmlImg).appendTo("#document-send");
});
},
fail: function(e){
console.log(e);
},
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#progress .progress-bar').css(
'width',
progress + '%'
);
}
}).prop('disabled', !$.support.fileInput)
.parent().addClass($.support.fileInput ? undefined : 'disabled');
// Согласование этапов
$("#order-stages").on('click', "#approve-stages", function (e) {
e.preventDefault();
$(".stage-block-approve").each(function () {
var stageId = $(this).attr('data-id');
$.ajax({
url: '/api/stages/' + stageId + '/',
type: 'PATCH',
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
},
data: "status=in_process",
dataType: 'json',
success: function (json) {
console.log(json);
},
error: function (e) {
console.log('error');
console.log(e);
}
});
});
var orderId = $(this).attr('data-order-id');
socket.send_stages_approve({
"format_type": "approve_stages",
"data": {
"sender_id": $(this).attr('data-sender-id'),
"recipent_id": $(this).attr('data-recipent-id'),
"order_id": orderId,
"msg": "Исполнитель согласовал этапы для заказа " + orderId,
}
});
});
// Согласование этапов
$("#order-stages").on('click', "#cancel-stages", function (e) {
e.preventDefault();
$(".stage-block-approve").each(function () {
var stageId = $(this).attr('data-id');
$.ajax({
url: '/api/stages/' + stageId + '/',
type: 'PATCH',
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
},
data: "status=cancel_approve",
dataType: 'json',
success: function (json) {
console.log(json);
},
error: function (e) {
console.log('error');
console.log(e);
}
});
});
var orderId = $(this).attr('data-order-id');
socket.send_stages_approve({
"format_type": "approve_stages",
"data": {
"sender_id": $(this).attr('data-sender-id'),
"recipent_id": $(this).attr('data-recipent-id'),
"order_id": orderId,
"msg": "Исполнитель отказался от текущих этапов " + orderId,
}
});
});
$(".team-chat-user").on('click', function (e) {
e.stopPropagation();
var recipentId = $(this).attr('data-id');
$("#team-chat-form #recipentTeamId").val(recipentId);
});
$(".team-order-block").on('click', function () {
$('.team-order-block, .team-block').each(function () {
$(this).removeClass('orAct');
});
$(this).addClass('orAct');
var teamId = $(this).attr('data-team-id');
var orderId = $(this).attr('data-order-id');
$("#team-chat-form #teamId").val(teamId);
$("#team-chat-form #orderTeamId").val(orderId);
var inbox = document.getElementById('message-chat-team-space');
inbox.innerHTML = '';
var docList = document.getElementById('documentTeamSpace');
docList.innerHTML = '';
$.ajax({
url: '/api/message',
type: 'GET',
data: {csrfmiddlewaretoken: csrftoken, 'team': teamId, '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"><div class="topCommChat">' +
'<p class="nameCommChat">' + senderName + '</p> <span>' + v.created + '</span></div>' +
'<p class="textCommChat">' + v.text + '</p></div>';
});
var height = inbox.scrollHeight;
inbox.scrollTop = height;
}
});
$.ajax({
url:'/api/documents',
type: 'GET',
data:{
csrfmiddlewaretoken: csrftoken,
'order': orderId,
'team': teamId,
'is_delete': false,
'is_send': true,
},
dataType: 'json',
success: function (json){
$.each(json.results, function (i, v) {
docList.innerHTML += '<li style="word-break: break-all;"><a class="file-link" href="'+ v.file_url +'">'+ v.file+'</a><div class="remove-document" data-id="'+ v.id+'" style="right:-10px;"></div></li>';
});
},
error: function(e){
console.log(e);
}
});
$.ajax({
url: '/api/note/',
type: 'GET',
data: {csrfmiddlewaretoken: csrftoken, 'order': orderId,'team':teamId},
dataType: 'json',
success: function (json) {
console.log(json.results);
var noteHtmlInbox = '';
$.each(json.results, function (i, v) {
noteHtmlInbox += '<li>' + v.text + '<li>';
});
$(".notes-block").html(noteHtmlInbox);
}
});
});
$('.team-block').on('click',function(){
$('.team-order-block, .team-block').each(function () {
$(this).removeClass('orAct');
});
$(this).addClass('orAct');
var inbox = document.getElementById('message-chat-team-space');
inbox.innerHTML = '';
var teamId = $(this).attr('data-team-id');
$("#team-chat-form #teamId").val(teamId);
$("#team-chat-form #orderTeamId").val("");
$.ajax({
url: '/api/message',
type: 'GET',
data: {csrfmiddlewaretoken: csrftoken, 'team': teamId, 'order__isnull':'true'},
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"><div class="topCommChat">' +
'<p class="nameCommChat">' + senderName + '</p> <span>' + v.created + '</span></div>' +
'<p class="textCommChat">' + v.text + '</p></div>';
});
var height = inbox.scrollHeight;
inbox.scrollTop = height;
}
});
});
// Вытащить сообщения для чата заказа
$('.order-block').on('click', function () {
$('.order-block').each(function () {
$(this).removeClass('orAct');
});
$(this).addClass('orAct');
var orderId = $(this).attr('data-id');
var recipentId = $(this).attr('data-recipent-id');
var projectId = $(this).attr('data-project-id');
$("#chat-order-add #orderId").val(orderId);
$("#add-form-order-note #orderNote").val(orderId);
$("#orderArbitrationId").val(orderId);
$("#projectReviewId").val(projectId);
$("#chat-order-add #recipentId").val(recipentId);
$("#targetCustomerId").val(recipentId);
$("#add-form-order-note #recipentNote").val(recipentId);
var docList = document.getElementById('documentOrderSpace');
var inbox = document.getElementById('message-chat-order-space');
inbox.innerHTML = '';
docList.innerHTML = '';
$.ajax({
url: '/api/message',
type: 'GET',
data: {csrfmiddlewaretoken: csrftoken, 'order': orderId, 'team__isnull': 'true'},
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"><div class="topCommChat">' +
'<p class="nameCommChat">' + senderName + '</p> <span>' + v.created + '</span></div>' +
'<p class="textCommChat">' + v.text + '</p></div>';
});
var height = inbox.scrollHeight;
inbox.scrollTop = height;
}
});
$.ajax({
url:'/api/documents',
type: 'GET',
data:{
csrfmiddlewaretoken: csrftoken,
'order': orderId,
'is_delete': false,
'is_send': true,
},
dataType: 'json',
success: function (json){
$.each(json.results, function (i, v) {
docList.innerHTML += '<li style="word-break: break-all;"><a class="file-link" href="'+ v.file_url +'">'+ v.file+'</a><div class="remove-document" data-id="'+ v.id+'" style="right:-10px;"></div></li>';
});
},
error: function(e){
console.log(e);
}
});
$.ajax({
url: '/api/note/',
type: 'GET',
data: {csrfmiddlewaretoken: csrftoken, 'order': orderId},
dataType: 'json',
success: function (json) {
console.log(json.results);
var noteHtmlInbox = '';
$.each(json.results, function (i, v) {
noteHtmlInbox += '<li>' + v.text + '<li>';
});
$(".notes-block").html(noteHtmlInbox);
}
});
$.ajax({
url:'/api/orders/' + orderId + '/',
type: 'GET',
data:{csrfmiddlewaretoken: csrftoken},
dataType: 'json',
}).then(function(data){
var htmlInbox = "";
var stagesReservedHtml = "";
var stagesPaidProcess = [];
var stagesInWork = [];
var stagesResults = data.stages;
var statusNotAgreed = false;
var stagesCompleted = [];
if (stagesResults.length > 0) {
$.each(stagesResults, function (i, v) {
if (v.status == "completed"){
stagesCompleted.push(v);
}
if(v.status == "not_agreed" || v.status == "send_approve"){
statusNotAgreed = true;
}
if(!data.secure){
if(v.status == "in_process"){
stagesInWork.push(v);
}
} else if ((v.status == "in_process") && (v.is_paid)){
stagesPaidProcess.push(v);
stagesInWork.push(v);
}
if(data.secure) {
if (v.is_paid) {
stagesReservedHtml += '<li class="reserved">Сумма за этап ' + v.pos + '.Зарезервирована.</li>';
} else {
stagesReservedHtml += '<li class="unreserved">Сумма за этап ' + v.pos + '.Не зарезервирована.</li>';
}
}
var statusName = '';
switch(v.status){
case 'not_agreed':
statusName = 'Не согласован';
break;
case 'send_approve':
statusName = 'На согласовании';
break;
case 'cancel_approve':
statusName = 'Исполнитель отказался';
break;
case 'in_process':
statusName = 'В процессе';
break;
case 'completed':
statusName = 'Завершен';
break;
}
if (v.status == 'completed'){
statusName = 'Завершен';
}
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="textNumStepp">Результаты этапа:' + v.result + '</p><div>' +
'<p> до ' + v.term + '</p><span>' + v.cost + ' <i class="fa fa-rub"></i></span></div><div><p>'+ statusName +'</p></div></div></div>';
});
if (statusNotAgreed) {
htmlInbox += '<div class="textAreaBlock2 FFD box-sizing disTab">' +
'<a id="approve-stages" data-sender-id="{{ request.user.pk }}" data-recipent-id="' + recipentId + '"' +
' data-order-id="' + orderId + '" href="#">согласовать</a>' +
'<a id="cancel-stages" data-sender-id="{{ request.user.pk }}" data-recipent-id="' + recipentId + '"' +
' data-order-id="' + orderId + '" href="#">отказаться</a>' +
'</div>';
}
}
$("#order-stages").html(htmlInbox);
$(".stages-paid").html(stagesReservedHtml);
if(data.secure) {
$("#reserveSpace").show();
} else {
$("#reserveSpace").hide();
}
if (stagesInWork.length > 0){
$("#completeWork").show();
var stage = stagesInWork[0];
var stageWork = '<div class="numberStepp box-sizing">' +
'<div class="insetNumStepp"><div><p>В работе '+ stage.name +'</p></div>' +
'<div><p>Результат этапа : '+ stage.result +'</p></div>' +
'<div><p>Срок сдачи '+ stage.term +' <span>' + stage.cost + '<i class="fa fa-rub"></i></span></p></div></div></div>';
if(!stage.close_contractor){
stageWork += '<div class="textAreaBlock2 FFD box-sizing disTab"><a href="#" class="closeStage" data-sender-id="{{ request.user.pk }}" data-recipent-id="'+ recipentId+'"' +
' data-order-id="'+ data.id +'" data-stage-id="'+ stage.id +'">Завершить этап</a></div>';
}else{
stageWork += '<div><p>Этап ожидает завершения статуса от заказчика</p><div>';
}
if (data.secure) {
stageWork += '<div class="textAreaBlock2 FFD box-sizing disTab"><a href="#" data-toggle="modal" data-target="#arbitration-add">Обратитьсяв арбитраж</a></div>';
}
$("#stagesWork").html(stageWork);
}else{
$("#completeWork").hide();
}
if(stagesCompleted.length == stagesResults.length && stagesCompleted.length>0){
$("#leaveReview").show();
}
if (data.status == 'completed'){
$("#leaveReview").hide();
}
});
});
//Добавить заметку.
$('#add-note-button').on('click', function (e) {
e.preventDefault();
$.ajax({
url: '/api/note/',
type: 'POST',
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
},
data: $("#add-form-order-note").serialize(),
dataType: 'json',
success: function (json) {
console.log(json);
$("#add-form-order-note #chat2").val("");
},
error: function (e) {
console.log('error');
console.log(e);
}
});
});
$('#tab2').on('click','.closeStage', function(e){
e.preventDefault();
var stageId = $(this).attr('data-stage-id');
var _this = $(this);
$.ajax({
url: '/api/stages/' + stageId + '/',
type: 'PATCH',
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
},
data: "close_contractor=True",
dataType: 'json',
success: function (json) {
socket.send_stages_approve({
"format_type": "approve_stages",
"data": {
"sender_id": _this.attr('data-sender-id'),
"recipent_id": _this.attr('data-recipent-id'),
"order_id": _this.attr('data-order-id'),
"msg": "Исполнитель завершил этап " + json.name,
}
});
console.log(json);
},
error: function (e) {
console.log('error');
console.log(e);
}
});
});
//Добавить сообщение для исполнителей в группе
$("#add-team-chat-message").on('click', function (e) {
e.preventDefault();
var chatMessage = $("#team-chat-form #chatText").val();
var recipentId = $("#team-chat-form #recipentTeamId").val();
var senderId = $("#team-chat-form #senderTeamId").val();
var teamId = $("#team-chat-form #teamId").val();
var orderId = $("#team-chat-form #orderTeamId").val();
var documentSendIds = $("#documentSendIds").val();
if(chatMessage) {
var sendLinks = $("#document-send a");
var sendLinkIds = "";
$.each(sendLinks, function(i, v){
sendLinkIds += $(this).attr('data-id') + ';';
});
socket.add_team_message({
"format_type": "add_message_team",
"data": {
"sender_id": senderId,
"recipent_id": recipentId,
"chat_message": chatMessage,
"team_id": teamId,
"order_id": orderId,
"document_send_links": sendLinkIds,
}
});
$("#team-chat-form #chatText").val("");
$("#document-send").html("");
$("#documentSendIds").val("");
}
});
});
</script>
<script type="text/javascript" src='{% static "js/chat_contractor.js" %}'></script>
{% endblock %}

@ -49,7 +49,7 @@
<div><a href="{{ contact_url }}">{{ contact.username }}</a></div>
</p>
<a href="#" class="conMess">Контакты</a>
<a href="#" data-id="{{ contact.id }}" class="conMess">Контакты</a>
<span class="contact-count-{{ contact.pk|add:request.user.pk }}">0</span>
<a href="#" class="deleteMess" data-recipent-id="{{ contact.pk }}">
@ -214,9 +214,16 @@
</div>
<div class="textAreaBlock2 box-sizing disTab">
<ul class="order-notes-block">
</ul>
<p>Для заметок</p>
<textarea id="chat2"></textarea>
<a href="#">сохранить</a>
<form id="add-form-order-note">
<textarea id="chat2" name="text"></textarea>
<input type="hidden" name="order" id="orderNote" value=""/>
<input type="hidden" name="sender" id="senderNote" value="{{ request.user.pk }}"/>
<input type="hidden" name="recipent" id="recipentNote" value=""/>
<a href="#" id="add-note-button">сохранить</a>
</form>
</div>
<!-- Review add -->
@ -401,6 +408,17 @@
statusNotAgreed = false;
htmlInboxStage = "";
var statusName = "";
switch (v.status){
case 'completed':
statusName = 'Завершен';
break;
case 'in_process':
statusName = 'Согласовано';
break;
default:
statusName = '';
break;
}
if (v.status == 'completed'){
statusName = 'Завершен';
}
@ -633,7 +651,6 @@
}
});
// Для заказов все вытащить
$('.order-block').on('click', function () {
$("#chat-order-add").css("display", "block");
@ -650,11 +667,13 @@
var secureOrder = $(this).attr('data-secure-deal');
secureOrder = Boolean(secureOrder);
$("#chat-order-add #orderId").val(orderId);
$("#add-form-order-note #orderNote").val(orderId);
$("#orderArbitrationId").val(orderId);
$("#projectReviewId").val(projectId);
$("#reserve-button").attr('data-order-id', orderId);
$("#targetContractorId").val(recipentId);
$("#chat-order-add #recipentId").val(recipentId);
$("#add-form-order-note #recipentNote").val(recipentId);
$(".orderStagesInput").val(orderId);
var inbox = document.getElementById('message-chat-order-space');
var docList = document.getElementById('documentOrderSpace');
@ -673,7 +692,7 @@
dataType: 'json',
success: function (json){
$.each(json.results, function (i, v) {
docList.innerHTML += '<li style="word-break: break-all;"><a class="file-link" href="'+ v.file_url +'">'+ v.file+'</a><div class="remove-document" data-id="'+ v.id+'" style="right:-10px;"></div></li>';
docList.innerHTML += '<li style="word-break: break-all;"><a class="file-link" href="/chat/download/' + v.file + '">' + v.file+'</a><div class="remove-document" data-id="'+ v.id+'" style="right:-10px;"></div></li>';
});
},
error: function(e){
@ -704,6 +723,23 @@
inbox.scrollTop = height;
}
});
$.ajax({
url: '/api/note/',
type: 'GET',
data: {
csrfmiddlewaretoken: csrftoken,
'order': orderId,
},
dataType: 'json',
success: function (json) {
console.log(json.results);
var noteHtmlInbox = '';
$.each(json.results, function (i, v) {
noteHtmlInbox += '<li>' + v.text + '<li>';
});
$(".order-notes-block").html(noteHtmlInbox);
}
});
getStages(orderId,userId,recipentId, secureOrder);
});

@ -7,12 +7,7 @@
<h4 class="modal-title">Контакты</h4>
</div>
<div class="modal-body">
<table class="table">
<tr>
<td>Ф.И.О.</td>
<td></td>
</tr>
<table class="table table-bordered">
</table>
</div>
<div class="modal-footer"></div>

@ -7,7 +7,7 @@
<h4 class="modal-title">Полное описапие заказа</h4>
</div>
<div class="modal-body">
<table class="table"></table>
<table class="table table-bordered"></table>
</div>
<div class="modal-footer"></div>
</div>

@ -4,6 +4,7 @@ from .views import (
ChatUserView,
DocumentCreateView,
messages_delete,
download_file,
)
app_name = 'chat'
@ -12,4 +13,6 @@ urlpatterns = [
urls.url(r'^$', ChatUserView.as_view(), name='chat-user'),
urls.url(r'^messages_delete/$', messages_delete, name='chat-messages_delete'),
urls.url(r'^create/$', DocumentCreateView.as_view()),
urls.url(r'^download/(?P<file_name>.+)', download_file),
]

@ -5,6 +5,7 @@ from django.views.generic import View,CreateView
from django.http import HttpResponse, Http404
from django.db.models import Q
from django.contrib.auth.mixins import LoginRequiredMixin
from wsgiref.util import FileWrapper
from .response import JSONResponse, response_mimetype
from .utils import serialize
@ -111,3 +112,15 @@ def messages_delete(request):
return HttpResponse(json.dumps(data), content_type='application/json')
else:
raise Http404
def download_file(request,file_name):
try:
document = Documents.objects.get(file=file_name)
except Documents.DoesNotExist:
document = None
file_name = document.file
response = HttpResponse(FileWrapper(file_name), content_type='application/force-download')
response['Content-Disposition'] = 'attachment; filename=' + file_name.name
return response

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-09-07 08:01
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('common', '0013_liveimageupload'),
]
operations = [
migrations.AlterModelOptions(
name='liveimageupload',
options={'verbose_name': 'Живая загрузка изображений', 'verbose_name_plural': 'Живая загрузка изображений'},
),
]

@ -35,6 +35,7 @@ class ContractorResumeFilesSerializer(ModelSerializer):
class UserSerializer(ModelSerializer):
_type = SerializerMethodField() # Distinguish when used with generic serializers
id = ReadOnlyField()
fio = SerializerMethodField()
class Meta:
model = User
@ -60,11 +61,16 @@ class UserSerializer(ModelSerializer):
'skype',
'username',
'website',
'phone',
'fio',
)
def get__type(self, obj):
return 'User'
def get_fio(self, obj):
return obj.get_full_name()
# def create(self, validated_data):
# return User.objects.create(**validated_data)

@ -103,21 +103,30 @@
<!-- Arbitration add -->
{% include 'arbitration_modal.html' %}
<!-- -->
<div class="col-lg-12 documentsChat">
<p>Прикрепленные документы</p>
<ul id="documentOrderSpace"></ul>
<a href="{% url 'common:create' %}">
Распечатать с помощью ресурса
</a>
</div>
<div class="textAreaBlock2 box-sizing disTab">
<ul class="notes-block">
<ul class="order-notes-block">
</ul>
<p>Для заметок</p>
<form id="add-form-order-note">
<textarea id="chat2" name="text"></textarea>
<input type="hidden" name="order" id="orderNote" value=""/>
<input type="hidden" name="sender" id="senderNote" value="{{ request.user.pk }}"/>
<input type="hidden" name="recipent" id="recipentNote" value=""/>
<input type="hidden" name="order" id="orderNote" value="">
<input type="hidden" name="sender" id="senderNote" value="{{ request.user.pk }}">
<input type="hidden" name="recipent" id="recipentNote" value="">
<a href="#" id="add-note-button">сохранить</a>
</form>
</div>
</div>
</div>
<!-- End block Tab2-->
{% include 'order_info.html' %}
</div>
@ -137,377 +146,5 @@
</script>
<script type="text/javascript" src='{% static "js/chat.js" %}'></script>
<script type="text/javascript">
$(function () {
var currentChatUser = {{ request.user.pk }};
var form = document.getElementById('message_form');
setTimeout(function () {
$(".team-order-block").first().trigger('click');
}, 1000);
var url = '/chat/create/';
//Загрузка документов
$('#upload-document-team').fileupload({
url: url,
formData: {
sender: $("#team-chat-form #senderId").val(),
recipent: $("#team-chat-form #recipentId").val(),
team: $("#team-chat-form #teamId").val(),
order: $("#team-chat-form #orderId").val(),
},
crossDomain: false,
beforeSend: function (xhr, settings) {
$('#progress .progress-bar').css(
'width',
'0%'
);
if (!csrfSafeMethod(settings.type)) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
},
dataType: 'json',
done: function (e, data) {
$.each(data.result.files, function (index, file) {
var currentValue = $("#documentSendIds").val();
currentValue += file.id + ';';
$("#documentSendIds").val(currentValue);
var htmlImg = '<p>' + file.name + '</p>';
var document_send = $(htmlImg).appendTo("#document-send");
});
},
fail: function(e){
console.log(e);
},
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#progress .progress-bar').css(
'width',
progress + '%'
);
}
}).prop('disabled', !$.support.fileInput)
.parent().addClass($.support.fileInput ? undefined : 'disabled');
// Согласование этапов
$("#order-stages").on('click', "#approve-stages", function (e) {
e.preventDefault();
$(".stage-block-approve").each(function () {
var stageId = $(this).attr('data-id');
$.ajax({
url: '/api/stages/' + stageId + '/',
type: 'PATCH',
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
},
data: "status=in_process",
dataType: 'json',
success: function (json) {
console.log(json);
},
error: function (e) {
console.log('error');
console.log(e);
}
});
});
var orderId = $(this).attr('data-order-id');
socket.send_stages_approve({
"format_type": "approve_stages",
"data": {
"sender_id": $(this).attr('data-sender-id'),
"recipent_id": $(this).attr('data-recipent-id'),
"order_id": orderId,
"msg": "Исполнитель согласовал этапы для заказа " + orderId,
}
});
});
$(".team-chat-user").on('click', function (e) {
e.stopPropagation();
var recipentId = $(this).attr('data-id');
$("#team-chat-form #recipentId").val(recipentId);
});
$(".team-order-block").on('click', function () {
$('.team-order-block').each(function () {
$(this).removeClass('orAct');
});
$(this).addClass('orAct');
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);
var inbox = document.getElementById('message-chat-team-space');
inbox.innerHTML = '';
$.ajax({
url: '/api/message',
type: 'GET',
data: {csrfmiddlewaretoken: csrftoken, 'team': teamId, '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"><div class="topCommChat">' +
'<p class="nameCommChat">' + senderName + '</p> <span>' + v.created + '</span></div>' +
'<p class="textCommChat">' + v.text + '</p></div>';
});
}
});
});
// Вытащить сообщения для чата заказа
$('.order-block').on('click', function () {
$('.order-block').each(function () {
$(this).removeClass('orAct');
});
$(this).addClass('orAct');
var orderId = $(this).attr('data-id');
var recipentId = $(this).attr('data-recipent-id');
var projectId = $(this).attr('data-project-id');
$("#chat-order-add #orderId").val(orderId);
$("#add-form-order-note #orderNote").val(orderId);
$("#orderArbitrationId").val(orderId);
$("#projectReviewId").val(projectId);
$("#chat-order-add #recipentId").val(recipentId);
$("#targetCustomerId").val(recipentId);
$("#add-form-order-note #recipentNote").val(recipentId);
var inbox = document.getElementById('message-chat-order-space');
inbox.innerHTML = '';
$.ajax({
url: '/api/message',
type: 'GET',
data: {csrfmiddlewaretoken: csrftoken, 'order': orderId, 'team__isnull': 'true'},
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"><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, 'order': orderId},
dataType: 'json',
success: function (json) {
console.log(json.results);
var noteHtmlInbox = '';
$.each(json.results, function (i, v) {
noteHtmlInbox += '<li>' + v.text + '<li>';
});
$(".notes-block").html(noteHtmlInbox);
}
});
$.ajax({
url:'/api/orders/' + orderId + '/',
type: 'GET',
data:{csrfmiddlewaretoken: csrftoken},
dataType: 'json',
}).then(function(data){
var htmlInbox = "";
var stagesReservedHtml = "";
var stagesPaidProcess = [];
var stagesInWork = [];
var stagesResults = data.stages;
var statusNotAgreed = false;
var stagesCompleted = [];
if (stagesResults.length > 0) {
$.each(stagesResults, function (i, v) {
if (v.status == "completed"){
stagesCompleted.push(v);
}
if(v.status == "not_agreed"){
statusNotAgreed = true;
}
if(!data.secure){
if(v.status == "in_process"){
stagesInWork.push(v);
}
} else if ((v.status == "in_process") && (v.is_paid)){
stagesPaidProcess.push(v);
stagesInWork.push(v);
}
if(data.secure) {
if (v.is_paid) {
stagesReservedHtml += '<li class="reserved">Сумма за этап ' + v.pos + '.Зарезервирована.</li>';
} else {
stagesReservedHtml += '<li class="unreserved">Сумма за этап ' + v.pos + '.Не зарезервирована.</li>';
}
}
var statusName = '';
if (v.status == 'completed'){
statusName = 'Завершен';
}
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="textNumStepp">Результаты этапа:' + v.result + '</p><div>' +
'<p> до ' + v.term + '</p><span>' + v.cost + ' <i class="fa fa-rub"></i></span></div><div><p>'+ statusName +'</p></div></div></div>';
});
if (statusNotAgreed) {
htmlInbox += '<div class="textAreaBlock2 FFD box-sizing disTab">' +
'<a id="approve-stages" data-sender-id="{{ request.user.pk }}" data-recipent-id="' + recipentId + '"' +
' data-order-id="' + orderId + '" href="#">согласовать</a></div>';
}
}
$("#order-stages").html(htmlInbox);
$(".stages-paid").html(stagesReservedHtml);
if(data.secure) {
$("#reserveSpace").show();
} else {
$("#reserveSpace").hide();
}
if (stagesInWork.length > 0){
$("#completeWork").show();
var stage = stagesInWork[0];
var stageWork = '<div class="numberStepp box-sizing">' +
'<div class="insetNumStepp"><div><p>В работе '+ stage.name +'</p></div>' +
'<div><p>Результат этапа : '+ stage.result +'</p></div>' +
'<div><p>Срок сдачи '+ stage.term +' <span>' + stage.cost + '<i class="fa fa-rub"></i></span></p></div></div></div>';
if(!stage.close_contractor){
stageWork += '<div class="textAreaBlock2 FFD box-sizing disTab"><a href="#" class="closeStage" data-sender-id="{{ request.user.pk }}" data-recipent-id="'+ recipentId+'"' +
' data-order-id="'+ data.id +'" data-stage-id="'+ stage.id +'">Завершить этап</a></div>';
}else{
stageWork += '<div><p>Этап ожидает завершения статуса от заказчика</p><div>';
}
if (data.secure) {
stageWork += '<div class="textAreaBlock2 FFD box-sizing disTab"><a href="#" data-toggle="modal" data-target="#arbitration-add">Обратитьсяв арбитраж</a></div>';
}
$("#stagesWork").html(stageWork);
}else{
$("#completeWork").hide();
}
if(stagesCompleted.length == stagesResults.length && stagesCompleted.length>0){
$("#leaveReview").show();
}
if (data.status == 'completed'){
$("#leaveReview").hide();
}
});
});
//Добавить заметку.
$('#add-note-button').on('click', function (e) {
e.preventDefault();
$.ajax({
url: '/api/note/',
type: 'POST',
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
},
data: $("#add-form-order-note").serialize(),
dataType: 'json',
success: function (json) {
console.log(json);
$("#add-form-order-note #chat2").val("");
},
error: function (e) {
console.log('error');
console.log(e);
}
});
});
$('#tab2').on('click','.closeStage', function(e){
e.preventDefault();
var stageId = $(this).attr('data-stage-id');
var _this = $(this);
$.ajax({
url: '/api/stages/' + stageId + '/',
type: 'PATCH',
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
},
data: "close_contractor=True",
dataType: 'json',
success: function (json) {
socket.send_stages_approve({
"format_type": "approve_stages",
"data": {
"sender_id": _this.attr('data-sender-id'),
"recipent_id": _this.attr('data-recipent-id'),
"order_id": _this.attr('data-order-id'),
"msg": "Исполнитель завершил этап " + json.name,
}
});
console.log(json);
},
error: function (e) {
console.log('error');
console.log(e);
}
});
});
//Добавить сообщение для исполнителей в группе
$("#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();
var orderId = $("#team-chat-form #orderId").val();
var documentSendIds = $("#documentSendIds").val();
console.log(documentSendIds);
var teamDocumentIds = documentSendIds.split(';');
teamDocumentIds.pop();
console.log(teamDocumentIds);
socket.add_team_message({
"format_type": "add_message_team",
"data": {
"sender_id": senderId,
"recipent_id": recipentId,
"chat_message": chatMessage,
"team_id": teamId,
"order_id": orderId,
}
});
$("#team-chat-form #chatText").val("");
$("#document-send").html("");
});
});
</script>
<script type="text/javascript" src='{% static "js/chat_contractor.js" %}'></script>
{% endblock %}

Loading…
Cancel
Save