remotes/origin/PR-39
Mukhtar 9 years ago
parent 3b3b61bbbc
commit 0c4ae1ae97
  1. 1
      api/views.py
  2. 25
      assets/css/extra.css
  3. 15
      assets/css/main.css
  4. 150
      assets/js/chat.js
  5. 166
      assets/js/chat_contractor.js
  6. 523
      assets/js/chat_customer.js
  7. 525
      chat/templates/chat_customer.html
  8. 2
      chat/urls.py
  9. 24
      chat/views.py
  10. 10
      projects/models.py
  11. 6
      projects/validators.py

@ -91,6 +91,7 @@ class ProjectViewSet(ModelViewSet):
queryset = Project.objects.all() queryset = Project.objects.all()
serializer_class = ProjectSerializer serializer_class = ProjectSerializer
filter_class = ProjectFilterSet filter_class = ProjectFilterSet
# permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
class NoteViewSet(ModelViewSet): class NoteViewSet(ModelViewSet):

@ -164,3 +164,28 @@
top: 1px; top: 1px;
} }
.deleteOrder:after {
content: '';
position: absolute;
width: 13px;
height: 13px;
background: url('../img/btn3.png') no-repeat center;
background-size: cover;
left: -30px;
top: 2px;
}
.deleteOrder, .deleteOrder:link, .deleteOrder:visited {
color: #5a5a5a;
font-size: 14px;
font-family: Arial, Verdana, Helvetica, sans-serif;
text-decoration: underline;
position: relative;
float: left;
margin: 0 0 0 35px;
font-style: italic;
}

@ -3416,6 +3416,19 @@ input[type="checkbox"]:checked + span {
margin: 10px 0 20px 0; margin: 10px 0 20px 0;
} }
.textAreaBlock2 a, .textAreaBlock2 a:link, .textAreaBlock2 a:visited {
border: 1px solid #bebebe;
border-radius: 40px;
color: #373737;
display: inline-block;
font-family: "pfdintextcomppro-regular",sans-serif;
font-size: 15px;
letter-spacing: 2px;
margin-bottom: 20px;
padding: 12px 30px;
text-transform: uppercase;
}
.textAreaBlock2 a:not(.cke_button, .cke_combo_button, .cke_path_item), .textAreaBlock2 a:not(.cke_button, .cke_combo_button, .cke_path_item),
.textAreaBlock2 a:link:not(.cke_button, .cke_combo_button, .cke_path_item), .textAreaBlock2 a:link:not(.cke_button, .cke_combo_button, .cke_path_item),
.textAreaBlock2 a:visited:not(.cke_button, .cke_combo_button, .cke_path_item) { .textAreaBlock2 a:visited:not(.cke_button, .cke_combo_button, .cke_path_item) {
@ -3692,7 +3705,7 @@ input[type="checkbox"]:checked + span {
top: 0; top: 0;
} }
.documentsChat ul li div { .documentsChat ul li div , .remove-document{
position: absolute; position: absolute;
width: 11px; width: 11px;
height: 11px; height: 11px;

@ -1,3 +1,34 @@
window.confirm = function (message, callback, caption) {
caption = caption || ''
$(document.createElement('div')).attr({
title: caption,
'class': 'dialog'
}).html(message).dialog({
modal: true,
resizable: false,
height: "auto",
width: 400,
buttons: {
"Отмена": function () {
$(this).dialog('close');
return false;
},
"OK": function () {
$(this).dialog('close');
callback()
return true;
}
},
close: function () {
$(this).remove();
},
});
};
var SocketHandler = function () { var SocketHandler = function () {
domain = domain.replace(':' + port, ''); domain = domain.replace(':' + port, '');
var url = 'ws://' + domain + '/chat/' + userId + '/'; var url = 'ws://' + domain + '/chat/' + userId + '/';
@ -78,30 +109,47 @@ var socket = new SocketHandler();
var csrftoken = getCookie('csrftoken'); var csrftoken = getCookie('csrftoken');
function test_dialog(message){
var resStatus;
$("#dialog_delete .modal-title").html(message);
$("#dialog_delete").modal('show');
$("#btnYes").click(function (e) {
$("#dialog_delete").modal('hide');
resStatus = true;
});
$("#btnNot").click(function (e) {
$("#dialog_delete").modal('hide');
resStatus = false;
});
return resStatus;
}
$(function () { $(function () {
function dialog(message, yesCallback, notCallback) { function dialog (message, yesCallback, notCallback) {
$("#dialog_delete .modal-title").html(message); $("#dialog_delete .modal-title").html(message);
var dialog = $("#dialog_delete").modal('show'); $("#dialog_delete").modal('show');
$("#btnYes").click(function () { $("#btnYes").click(function (e) {
e.preventDefault();
yesCallback(); yesCallback();
$("#dialog_delete").modal('hide'); $("#dialog_delete").modal('hide');
}); });
$("#btnNot").click(function () { $("#btnNot").click(function (e) {
e.preventDefault();
notCallback(); notCallback();
$("#dialog_delete").modal('hide'); $("#dialog_delete").modal('hide');
}); });
} }
var currentHash = URI(location.href).hash(); var currentHash = URI(location.href).hash();
$('a[data-toggle="tab"]').on('show.bs.tab', function (e) { $('a[data-toggle="tab"]').on('show.bs.tab', function (e) {
var activeTab = $(this).attr('href').substring(1); var activeTab = $(this).attr('href').substring(1);
var liveHash = URI(location.href).hash(); var liveHash = URI(location.href).hash();
switch(activeTab){ switch (activeTab) {
case 'tab1': case 'tab1':
setTimeout(function () { setTimeout(function () {
if(liveHash.indexOf("#user") == 0) { if (liveHash.indexOf("#user") == 0) {
var userHashId = liveHash.replace("#user", ""); var userHashId = liveHash.replace("#user", "");
$("#userBlock" + userHashId).trigger('click'); $("#userBlock" + userHashId).trigger('click');
} else { } else {
@ -112,7 +160,7 @@ $(function () {
case 'tab2': case 'tab2':
setTimeout(function () { setTimeout(function () {
if(liveHash.indexOf("#order") == 0) { if (liveHash.indexOf("#order") == 0) {
var ordHashId = liveHash.replace("#order", ""); var ordHashId = liveHash.replace("#order", "");
$("#orderBlock" + ordHashId).trigger('click'); $("#orderBlock" + ordHashId).trigger('click');
} else { } else {
@ -123,18 +171,18 @@ $(function () {
case 'tab3': case 'tab3':
setTimeout(function () { setTimeout(function () {
if(liveHash.indexOf("#teamorder") == 0) { if (liveHash.indexOf("#teamorder") == 0) {
var teamHashId = liveHash.replace("#teamorder", ""); var teamHashId = liveHash.replace("#teamorder", "");
$("#teamOrderBlock" + teamHashId).trigger('click'); $("#teamOrderBlock" + teamHashId).trigger('click');
} else if(liveHash.indexOf("#myteam") == 0){ } else if (liveHash.indexOf("#myteam") == 0) {
var teamHashId = liveHash.replace("#myteam", ""); var teamHashId = liveHash.replace("#myteam", "");
$("#teamMyBlock" + teamHashId).trigger('click'); $("#teamMyBlock" + teamHashId).trigger('click');
} else { } else {
var firstTeamBlock = $(".team-block").first(); var firstTeamBlock = $(".team-block").first();
var firstTeamOrder = $(".team-order-block").first(); var firstTeamOrder = $(".team-order-block").first();
if (firstTeamOrder.length == 1){ if (firstTeamOrder.length == 1) {
firstTeamOrder.trigger('click'); firstTeamOrder.trigger('click');
} else if(firstTeamBlock.length == 1){ } else if (firstTeamBlock.length == 1) {
firstTeamBlock.trigger('click'); firstTeamBlock.trigger('click');
} }
} }
@ -146,7 +194,7 @@ $(function () {
if (currentHash.indexOf("#order") == 0) { if (currentHash.indexOf("#order") == 0) {
$("a[href='#tab2']").trigger('click'); $("a[href='#tab2']").trigger('click');
} else if(currentHash.indexOf("#user") == 0){ } else if (currentHash.indexOf("#user") == 0) {
$("a[href='#tab1']").trigger('click'); $("a[href='#tab1']").trigger('click');
} else if (currentHash.indexOf("#teamorder") == 0 || currentHash.indexOf("#myteam") == 0) { } else if (currentHash.indexOf("#teamorder") == 0 || currentHash.indexOf("#myteam") == 0) {
$("a[href='#tab3']").trigger('click'); $("a[href='#tab3']").trigger('click');
@ -154,6 +202,33 @@ $(function () {
$("a[href='#tab1']").trigger('click'); $("a[href='#tab1']").trigger('click');
} }
$("#trashed-button").on('click',function(e){
e.preventDefault();
var trashedOrderHtml = "";
$.ajax({
url: '/api/orders/',
type: 'GET',
dataType: 'json',
success: function(json){
console.log(json.results);
$.each(json.results, function(i, v){
var temp = '<div class="orderBlock box-sizing"><span class="dimovChat"></span>' +
'<p class="titleOB">'+ v.project.name +'</p><div class="hideOBB"><p class="pOB">' +
'<span>Исполнитель:</span> </p>' +
'<a href="#" class="linkChat11 full-order-info">' +
'<span class="glyphicon glyphicon-info-sign" aria-hidden="true">' +
'</span>Полное описание заказа </a></div></div>';
trashedOrderHtml += temp;
});
$("#trashed-orders").html(trashedOrderHtml);
},
error: function(e, jqxhr){
console.log(e);
}
})
});
// Информация о заказе // Информация о заказе
$(".full-order-info").click('on', function (e) { $(".full-order-info").click('on', function (e) {
e.preventDefault(); e.preventDefault();
@ -251,7 +326,7 @@ $(function () {
$("#reserve-stage-modal").modal('hide'); $("#reserve-stage-modal").modal('hide');
$("#orderBlock" + orderId).trigger('click'); $("#orderBlock" + orderId).trigger('click');
}else if(json.status == 'error'){ } else if (json.status == 'error') {
alert(json.message_error); alert(json.message_error);
} }
}, },
@ -390,8 +465,8 @@ $(function () {
var _this = $(this); var _this = $(this);
dialog("Вы действительно хотите удалить сообщения этого пользователя?", dialog("Вы действительно хотите удалить сообщения этого пользователя?",
function(){ function () {
$.ajax({ $.ajax({
url: '/chat/messages_delete/', url: '/chat/messages_delete/',
type: 'POST', type: 'POST',
beforeSend: function (xhr) { beforeSend: function (xhr) {
@ -412,11 +487,48 @@ $(function () {
console.log(e); console.log(e);
} }
}); });
}.bind(null, senderId, recipentId, _this), }.bind(null, senderId, recipentId, _this),
function () { function () {
}); });
});
$('.deleteOrder').on('click', function (e) {
e.preventDefault();
e.stopPropagation();
var senderId = userId;
var projectId = $(this).attr('data-project-id');
var _this = $(this);
dialog("Вы действительно хотите удалить этот заказ?",
function () {
$.ajax({
url: '/chat/project/trashed/',
type: 'POST',
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
},
data: {'project_id': projectId},
dataType: 'json',
success: function (json) {
if (json.status == 'ok') {
_this.parent().parent().remove();
$("#message-chat-space").html("");
}
},
error: function (e) {
console.log('error');
console.log(e);
}
});
}.bind(null, senderId, projectId),
function () {
});
}); });
$('#add-note-contractor').on('click', function (e) { $('#add-note-contractor').on('click', function (e) {
@ -649,7 +761,7 @@ $(function () {
dataType: 'json', dataType: 'json',
done: function (e, data) { done: function (e, data) {
$.each(data.result.files, function (index, file) { $.each(data.result.files, function (index, file) {
var htmlImg = '<a href="/chat/download/' + file.name + '" class="send-doc" data-id="' + file.id + '">' + file.name + '</a><br />'; var htmlImg = '<a href="/chat/download/' + file.name + '" class="send-doc" data-id="' + file.id + '">' + file.name + '</a><div class="remove-document" data-id="'+ file.id+'" style="right:-10px;"></div><br />';
var document_send = $(htmlImg).appendTo("#document-send-order"); var document_send = $(htmlImg).appendTo("#document-send-order");
}); });
}, },

@ -1,4 +1,20 @@
$(function () { $(function () {
function dialog(message, yesCallback, notCallback) {
$("#dialog_delete .modal-title").html(message);
$("#dialog_delete").modal('show');
$("#btnYes").click(function (e) {
e.preventDefault();
yesCallback();
$("#dialog_delete").modal('hide');
});
$("#btnNot").click(function (e) {
e.preventDefault();
notCallback();
$("#dialog_delete").modal('hide');
});
}
var form = document.getElementById('message_form'); var form = document.getElementById('message_form');
var url = '/chat/create/'; var url = '/chat/create/';
@ -52,74 +68,91 @@ $(function () {
// Согласование этапов // Согласование этапов
$("#order-stages").on('click', "#approve-stages", function (e) { $("#order-stages").on('click', "#approve-stages", function (e) {
e.preventDefault(); e.preventDefault();
$(".stage-block-approve").each(function () { var orderId = $(this).attr('data-order-id');
var stageId = $(this).attr('data-id'); var senderId = $(this).attr('data-sender-id');
$.ajax({ var recipentId = $(this).attr('data-recipent-id');
url: '/api/stages/' + stageId + '/', var caption = "Вы действительно хотите согласовать этапы?";
type: 'PATCH',
beforeSend: function (xhr) { confirm(caption, function () {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken')) $(".stage-block-approve").each(function () {
}, var stageId = $(this).attr('data-id');
data: "status=in_process", $.ajax({
dataType: 'json', url: '/api/stages/' + stageId + '/',
success: function (json) { type: 'PATCH',
console.log(json); beforeSend: function (xhr) {
}, xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
error: function (e) { },
console.log('error'); //data: "status=in_process",
console.log(e); data: "status=send_approve",
dataType: 'json',
done: function (json) {
console.log(json);
},
fail: function (e) {
console.log('error');
console.log(e);
}
});
});
$('.btns-approve-stages').hide();
socket.send_stages_approve({
"format_type": "approve_stages",
"data": {
"sender_id": senderId,
"recipent_id": recipentId,
"order_id": orderId,
"msg": "Исполнитель согласовал этапы для заказа " + orderId,
} }
}); });
}); }.bind(orderId, senderId, recipentId), caption);
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) { $("#order-stages").on('click', "#cancel-stages", function (e) {
e.preventDefault(); e.preventDefault();
$(".stage-block-approve").each(function () { var senderId = $(this).attr('data-sender-id');
var stageId = $(this).attr('data-id'); var recipentId = $(this).attr('data-recipent-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'); var orderId = $(this).attr('data-order-id');
var caption = "Вы действительно хотите отказаться от этапов?";
confirm(caption,function() {
$(".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",
data: "status=send_approve",
dataType: 'json',
done: function (json) {
console.log(json);
},
fail: function (e) {
console.log('error');
console.log(e);
}
});
socket.send_stages_approve({ });
"format_type": "approve_stages", $('.btns-approve-stages').hide();
"data": {
"sender_id": $(this).attr('data-sender-id'), socket.send_stages_approve({
"recipent_id": $(this).attr('data-recipent-id'), "format_type": "approve_stages",
"order_id": orderId, "data": {
"msg": "Исполнитель отказался от текущих этапов " + orderId, "sender_id": senderId,
} "recipent_id": recipentId,
}); "order_id": orderId,
"msg": "Исполнитель отказался от текущих этапов " + orderId,
}
});
}.bind(),caption);
}); });
@ -137,14 +170,14 @@ $(function () {
$(this).addClass('orAct'); $(this).addClass('orAct');
var teamIds = ''; var teamIds = '';
$.each($(this).find('.team-chat-user'), function(i,v){ $.each($(this).find('.team-chat-user'), function (i, v) {
teamIds += $(this).attr('data-id') + ";"; teamIds += $(this).attr('data-id') + ";";
}); });
$("#team-chat-form #teamIds").val(teamIds); $("#team-chat-form #teamIds").val(teamIds);
var teamId = $(this).attr('data-team-id'); var teamId = $(this).attr('data-team-id');
var orderId = $(this).attr('data-order-id'); var orderId = $(this).attr('data-order-id');
location.hash = '#teamorder' + orderId; location.hash = '#teamorder' + orderId;
$("#team-chat-form #teamId").val(teamId); $("#team-chat-form #teamId").val(teamId);
$("#team-chat-form #recipentTeamId").val(""); $("#team-chat-form #recipentTeamId").val("");
$("#team-chat-form #orderTeamId").val(orderId); $("#team-chat-form #orderTeamId").val(orderId);
@ -226,7 +259,7 @@ $(function () {
$(this).addClass('orAct'); $(this).addClass('orAct');
var teamIds = ''; var teamIds = '';
$.each($(this).find('.team-chat-user'), function(i,v){ $.each($(this).find('.team-chat-user'), function (i, v) {
teamIds += $(this).attr('data-id') + ";"; teamIds += $(this).attr('data-id') + ";";
}); });
$("#team-chat-form #teamIds").val(teamIds); $("#team-chat-form #teamIds").val(teamIds);
@ -401,6 +434,7 @@ $(function () {
var stagesInWork = []; var stagesInWork = [];
var stagesResults = data.stages; var stagesResults = data.stages;
var statusNotAgreed = false; var statusNotAgreed = false;
var statusSendApprove = false;
var stagesCompleted = []; var stagesCompleted = [];
if (stagesResults.length > 0) { if (stagesResults.length > 0) {
$.each(stagesResults, function (i, v) { $.each(stagesResults, function (i, v) {
@ -460,10 +494,10 @@ $(function () {
if (statusNotAgreed) { if (statusNotAgreed) {
htmlInbox += '<div class="textAreaBlock2 FFD box-sizing disTab">' + htmlInbox += '<div class="textAreaBlock2 FFD box-sizing disTab btns-approve-stages">' +
'<a id="approve-stages" data-sender-id="'+ userId +'" data-recipent-id="' + recipentId + '"' + '<a id="approve-stages" data-sender-id="' + userId + '" data-recipent-id="' + recipentId + '"' +
' data-order-id="' + orderId + '" href="#">согласовать</a>' + ' data-order-id="' + orderId + '" href="#">согласовать</a>' +
'<a id="cancel-stages" data-sender-id="'+ userId +'" data-recipent-id="' + recipentId + '"' + '<a id="cancel-stages" data-sender-id="' + userId + '" data-recipent-id="' + recipentId + '"' +
' data-order-id="' + orderId + '" href="#">отказаться</a>' + ' data-order-id="' + orderId + '" href="#">отказаться</a>' +
'</div>'; '</div>';
} }
@ -487,7 +521,7 @@ $(function () {
'<div><p>Срок сдачи ' + stage.term + ' <span>' + stage.cost + '<i class="fa fa-rub"></i></span></p></div></div></div>'; '<div><p>Срок сдачи ' + stage.term + ' <span>' + stage.cost + '<i class="fa fa-rub"></i></span></p></div></div></div>';
if (!stage.close_contractor) { if (!stage.close_contractor) {
stageWork += '<div class="textAreaBlock2 FFD box-sizing disTab"><a href="#" class="closeStage" data-sender-id="'+ userId +'" data-recipent-id="' + recipentId + '"' + stageWork += '<div class="textAreaBlock2 FFD box-sizing disTab"><a href="#" class="closeStage" data-sender-id="' + userId + '" data-recipent-id="' + recipentId + '"' +
' data-order-id="' + data.id + '" data-stage-id="' + stage.id + '">Завершить этап</a></div>'; ' data-order-id="' + data.id + '" data-stage-id="' + stage.id + '">Завершить этап</a></div>';
} else { } else {
stageWork += '<div><p>Этап ожидает завершения статуса от заказчика</p><div>'; stageWork += '<div><p>Этап ожидает завершения статуса от заказчика</p><div>';
@ -563,7 +597,7 @@ $(function () {
var documentAttachFiles = ""; var documentAttachFiles = "";
$.each(sendLinks, function (i, v) { $.each(sendLinks, function (i, v) {
sendLinkIds += $(this).attr('data-id') + ';'; sendLinkIds += $(this).attr('data-id') + ';';
documentLinks += 'Входящий файл: <br> <a href="'+ $(this).attr('href') + '">'+ $(this).text() +'</a><br>'; documentLinks += 'Входящий файл: <br> <a href="' + $(this).attr('href') + '">' + $(this).text() + '</a><br>';
documentAttachFiles += '<li style="word-break: break-all;">' + documentAttachFiles += '<li style="word-break: break-all;">' +
'<a class="file-link" href="' + $(this).attr('href') + '">' + $(this).text() + '</a>' + '<a class="file-link" href="' + $(this).attr('href') + '">' + $(this).text() + '</a>' +
'<div class="remove-document" data-id="' + $(this).attr('data-id') + '" style="right:-10px;"></div></li>'; '<div class="remove-document" data-id="' + $(this).attr('data-id') + '" style="right:-10px;"></div></li>';

@ -0,0 +1,523 @@
$(function () {
var form = document.getElementById('message_form');
$('body').on('focus', ".term-picker", function () {
$(this).datepicker({
minDate: 0,
});
})
$("#reserve-button").on("click", function (e) {
e.preventDefault();
$("#reserve-stage-modal").modal('show');
var orderId = $(this).attr('data-order-id');
$.ajax({
url: '/api/stages/',
type: 'GET',
data: {csrfmiddlewaretoken: csrftoken, 'order': orderId},
dataType: 'json',
success: function (json) {
var outputValues = '';
var totalSum = 0;
var stagesIds = '';
var notPaidCount = 0;
$.each(json.results, function (i, v) {
if ((v.status == 'in_process') && (!v.is_paid)) {
totalSum += parseInt(v.cost);
notPaidCount += 1;
outputValues += '<option data-stage-sum="' + v.cost + '" value="' + v.id + '">' + v.name + '</option>';
stagesIds += v.id + ';'
}
});
$("#stagesSelect").html(outputValues);
$(".totalSum").text(totalSum);
if (json.results.length > notPaidCount && notPaidCount > 0) {
$("#choiceWayOrder").hide();
}
$("#choiceWayOrder").val(totalSum);
$("#ordermodalId").val(orderId);
$("#stages-pay-form #stageSumPay").val(totalSum);
$("#stages-pay-form #stagesIds").val(stagesIds);
$("#choiceWayOrder").attr('data-stages-ids', stagesIds);
}
});
});
$("#tab2").on("change", "input[name=choice_way]:radio", function (e) {
var sumStage = $("#stagesSelect").find('option:selected').attr('data-stage-sum');
var currIdStage = $("#stagesSelect").find('option:selected').val();
$("#choiceWayStage").val(sumStage);
var currValue = $(this).val();
$("#stages-pay-form #stageSumPay").val(currValue);
var selectId = ($(this).attr('id'));
if (selectId == 'choiceWayOrder') {
$("#stages-pay-form #stagesIds").val($(this).attr('data-stages-ids'));
$("#stagesSelect").prop('disabled', 'disabled');
} else {
$("#stages-pay-form #stagesIds").val(currIdStage);
$("#stagesSelect").prop('disabled', false);
}
});
$("#tab2").on("change", "#stagesSelect", function (e) {
var sumStage = $(this).find('option:selected').attr("data-stage-sum");
$("#choiceWayStage").val(sumStage);
$("#stages-pay-form #stageSumPay").val(sumStage);
$(".stageSum").text(sumStage);
$("#stages-pay-form #stagesIds").val($(this).val());
});
//Получить заказы
function getStages(orderId, senderId, recipentId, secureOrder) {
$.ajax({
url: '/api/orders/' + orderId + '/',
type: 'GET',
data: {csrfmiddlewaretoken: csrftoken},
dataType: 'json',
}).then(function (data) {
var isReviewLeave = data.has_user_review;
var stagesResults = data.stages;
var stageCount = stagesResults.length;
if (stageCount == 0) {
$("#reserveSpace").hide();
stageCountVal = 1;
} else {
stageCountVal = stageCount;
}
var htmlInbox = "";
var htmlInboxStage = '<p class="textStepss">Какое кол-во этапов подразумевает работа? ' +
'<input type="text" id="countStage" value="' + stageCountVal + '"size="3"/></p>';
if (stageCount == 0) {
htmlInboxStage += '<div class="numberStepp box-sizing" id="stage1">' +
'<p>Этап <span class="stage-span-id">1</span></p><form class="new-stages-form" id="stage-form">' +
'<label for="">Название</label><input class="form-control" name="name" 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" type="hidden" name="status" value="send_approve">' +
'<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">' +
'<input class="form-control" name="pos" value="1" type="hidden">' +
'</form></div>';
}
var statusNotAgreed = true;
var stagesInWork = [];
var stagesPaidProcess = [];
var stagesCompleted = [];
var stagePaidCount = 0;
var stagesReservedHtml = "";
$.each(stagesResults, function (i, v) {
if (v.status == "completed") {
stagesCompleted.push(v);
}
if (!data.secure) {
if (v.status == "in_process") {
stagesInWork.push(v);
}
} else if ((v.status == "in_process") && (v.is_paid)) {
stagesInWork.push(v);
stagesPaidProcess.push(v);
}
if (v.is_paid) {
stagePaidCount += 1;
}
if (v.status == "not_agreed" || v.status == 'cancel_approve' || v.status == 'send_approve') {
htmlInbox += '<div class="numberStepp box-sizing">' +
'<p>Этап</p><form class="update-stages-form" data-stage-id="' + v.id + '" id="stage-form-' + v.pos + '">' +
'<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 + '" >' +
'<input class="form-control orderStagesInput" type="hidden" name="order" value="' + v.order + '">' +
'<input class="form-control" type="hidden" name="status" value="send_approve">' +
'<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 + '" >' +
'</form></div>';
} else {
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 = 'Завершен';
}
htmlInbox += '<div class="numberStepp box-sizing"><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>' +
'<p>Cрок заказа рассчитывается с момента резервирования средств</p>' +
'</div><div><p style="font-color:red;">' + statusName + '</p></div></div></div>';
}
if (data.secure) {
if (v.is_paid) {
stagesReservedHtml += '<li class="reserved">Сумма за этап ' + v.pos + '.Зарезервирована.</li>';
} else {
stagesReservedHtml += '<li class="unreserved">Сумма за этап ' + v.pos + '.Не зарезервирована.</li>';
}
}
});
if (stagesResults.length == stagePaidCount && data.secure) {
$("#reserve-button").parent().hide();
} else {
$("#reserve-button").parent().show();
}
if (statusNotAgreed) {
if (!data.secure) {
htmlInbox += '<div class="box-sizing disTab">' +
'<div class="checkbox"><input name="secure" id="secureOrder" type="checkbox" style="opacity:1">' +
'Перейти в режим безопасной сделки</div></div>';
}
htmlInbox += '<div class="textAreaBlock2 box-sizing disTab">' +
'<a href="#" data-sender-id="' + senderId + '" ' +
'data-recipent-id="' + recipentId + '" data-order-id="' + orderId + '" ' +
'id="addStagesForm">отправить на согласование</a> </div>';
} else if ((stagesResults.length > 0) && (data.secure)) {
$("#reserveSpace").show();
}
htmlInbox = htmlInboxStage + htmlInbox;
$("#order-stages").html(htmlInbox);
$("#completeWork").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 + '</p><span>' + stage.cost + '<i class="fa fa-rub"></i></span></div>' +
'</div></div>';
if (stage.close_contractor) {
stageWork += '<div class="textAreaBlock2 FFD box-sizing disTab"><a href="#" class="closeStage" data-order-id="' + orderId + '" data-sender-id="{{ request.user.pk }}"' +
' data-recipent-id="' + recipentId + '" data-stage-id="' + stage.id + '">Закрыть этап ' + stage.pos + '</a></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);
}
if (!data.secure) {
$("#reserveSpace").hide();
}
if ((stagesCompleted.length == stagesResults.length) && (stagesCompleted.length > 0) && (!isReviewLeave)) {
$("#leaveReview").show();
} else {
$("#leaveReview").hide();
}
$(".stages-paid").html(stagesReservedHtml);
});
}
//Закрыть этап
$('#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_customer: true, status: 'completed'},
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);
}
});
});
// Добавление этапов
$("#order-stages").on('click', "#addStagesForm", function (e) {
e.preventDefault();
var currentOrderId = $(this).attr('data-order-id');
var secureOrderEl = $("#secureOrder");
if (secureOrderEl.length > 0) {
var secOrderVal = false;
if (secureOrderEl.prop('checked')) {
secOrderVal = true;
}
$.ajax({
url: '/api/orders/' + currentOrderId + '/',
type: 'PATCH',
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
},
data: {secure: secOrderVal},
dataType: 'json',
success: function (json) {
},
error: function (e) {
console.log(e);
}
});
}
var callbacks = [];
$(".new-stages-form").each(function (i, v) {
var _this = $(this);
callbacks.push($.ajax({
url: '/api/stages/',
type: 'POST',
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
},
data: $(this).serialize(),
dataType: 'json',
done: function (json) {
_this.removeClass('new-stages-form').addClass('update-stages-form');
console.log(json);
},
fail: function (xhr, errorMsg,error) {
$.each(xhr.responseJSON, function(i,v){
console.log(v);
console.log(i);
});
},
}));
});
//$.when(callbacks).then(function(x){
// console.log(x);
// $.each(x,function(i,v){
// console.log(v);
// });
// alert("Запросы успешно выполнились");
//}, function(){
// alert("Произошла ошибка в запросах");
//});
$(".update-stages-form").each(function (i, v) {
var currentStageId = parseInt($(this).attr('data-stage-id'));
$.ajax({
url: '/api/stages/' + currentStageId + '/',
type: 'PUT',
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
},
data: $(this).serialize(),
dataType: 'json',
success: function (json) {
console.log(json);
},
error: function (e) {
console.log('error');
console.log(e);
}
});
});
var currentRecipentId = $(this).attr('data-recipent-id');
var secureOrder = true
//socket.send_stages_approve({
// "format_type": "approve_stages",
// "data": {
// "sender_id": userId,
// "recipent_id": currentRecipentId,
// "order_id": currentOrderId,
// "msg": "Этапы для заказа " + currentOrderId + " изменены",
// }
//});
});
//Изменение счетчика
$('#order-stages-tab').on('change', '#countStage', function () {
var countStage = parseInt($(this).val());
var currentCountStage = $("#order-stages .numberStepp").length;
if ((countStage < 1) || isNaN(countStage)) {
countStage = 1;
$('#order-stages-tab #countStage').val(currentCountStage);
} else {
if (countStage > currentCountStage) {
for (var jj = currentCountStage; jj < countStage; jj++) {
var pos = jj + 1;
var lastFormStage = $("#order-stages .numberStepp").last();
var orderId = lastFormStage.find('.orderStagesInput').val();
var addFormTemplate = '<div class="numberStepp box-sizing" id="stage1">' +
'<p>Этап <span class="stage-span-id">' + pos + '</span></p><form class="new-stages-form" id="stage-form">' +
'<label for="">Название</label><input class="form-control" name="name" 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" type="hidden" name="status" value="send_approve">' +
'<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">' +
'<input class="form-control" name="pos" value="' + pos + '" type="hidden"></form></div>';
lastFormStage.after(addFormTemplate);
}
} else if (countStage < currentCountStage) {
var ii = currentCountStage;
$($("#order-stages .numberStepp").get().reverse()).each(function () {
var currenFormName = ($(this).find('form').attr('class'));
if (ii > countStage) {
$(this).remove();
}
ii--;
});
}
}
});
// Для заказов все вытащить
$('.order-block').on('click', function () {
$("#chat-order-add").css("display", "block");
$("#formsetStage").css("display", "block");
$('.order-block').each(function () {
$(this).removeClass('orAct');
});
$(this).addClass('orAct');
var orderId = $(this).attr('data-id');
location.hash = '#order' + orderId;
var projectId = $(this).attr('data-project-id');
var recipentId = $(this).attr('data-recipent-id');
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');
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/users/{{ request.user.pk }}/',
type: 'GET',
data: {
csrfmiddlewaretoken: csrftoken,
},
dataType: 'json',
success: function (json) {
var score = json.score;
$("#order-stages-tab").attr('data-score', score);
},
error: function (e, jqxhr) {
console.log(jqxhr);
}
})
$.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) {
var noteHtmlInbox = '';
$.each(json.results, function (i, v) {
noteHtmlInbox += '<li>' + v.text + '<li>';
});
$(".order-notes-block").html(noteHtmlInbox);
}
});
getStages(orderId, userId, recipentId, secureOrder);
});
});

@ -139,9 +139,21 @@
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
Полное описание заказа Полное описание заказа
</a> </a>
<a href="#" class="deleteOrder" data-project-id="{{ order.pk }}">
Удалить заказ
</a>
</div> </div>
</div> </div>
{% endfor %} {% endfor %}
<div class="textAreaBlock2 FFD box-sizing disTab">
<a href="#" id="trashed-button">Показать архивные заказы</a>
</div>
<p>Архивные заказы</p>
<div id="trashed-orders"></div>
</div> </div>
</div> </div>
<div class="col-lg-6 commChat"> <div class="col-lg-6 commChat">
@ -265,516 +277,5 @@
</script> </script>
<script type="text/javascript" src='{% static "js/chat.js" %}'></script> <script type="text/javascript" src='{% static "js/chat.js" %}'></script>
<script type="text/javascript"> <script type="text/javascript" src='{% static "js/chat_customer.js" %}'></script>
$(function () {
var currentChatUser = {{ request.user.pk }};
var form = document.getElementById('message_form');
$('body').on('focus',".term-picker", function(){
$(this).datepicker({
{# minDate: 0,#}
});
})
$("#reserve-button").on("click",function(e) {
e.preventDefault();
$("#reserve-stage-modal").modal('show');
var orderId = $(this).attr('data-order-id');
$.ajax({
url: '/api/stages/',
type: 'GET',
data: {csrfmiddlewaretoken: csrftoken, 'order': orderId},
dataType: 'json',
success: function (json) {
var outputValues = '';
var totalSum = 0;
var stagesIds = '';
var notPaidCount = 0;
$.each(json.results, function (i, v) {
if((v.status == 'in_process') && (!v.is_paid)) {
totalSum += parseInt(v.cost);
notPaidCount +=1;
outputValues += '<option data-stage-sum="' + v.cost + '" value="' + v.id + '">' + v.name + '</option>';
stagesIds += v.id + ';'
}
});
$("#stagesSelect").html(outputValues);
$(".totalSum").text(totalSum);
if(json.results.length>notPaidCount && notPaidCount>0){
$("#choiceWayOrder").hide();
}
$("#choiceWayOrder").val(totalSum);
$("#ordermodalId").val(orderId);
$("#stages-pay-form #stageSumPay").val(totalSum);
$("#stages-pay-form #stagesIds").val(stagesIds);
$("#choiceWayOrder").attr('data-stages-ids',stagesIds);
}
});
});
$("#tab2").on("change","input[name=choice_way]:radio", function(e){
var sumStage = $("#stagesSelect").find('option:selected').attr('data-stage-sum');
var currIdStage = $("#stagesSelect").find('option:selected').val();
$("#choiceWayStage").val(sumStage);
var currValue = $(this).val();
$("#stages-pay-form #stageSumPay").val(currValue);
var selectId = ($(this).attr('id'));
if (selectId == 'choiceWayOrder'){
$("#stages-pay-form #stagesIds").val($(this).attr('data-stages-ids'));
$("#stagesSelect").prop('disabled', 'disabled');
}else {
$("#stages-pay-form #stagesIds").val(currIdStage);
$("#stagesSelect").prop('disabled', false);
}
});
$("#tab2").on("change","#stagesSelect", function(e){
var sumStage = $(this).find('option:selected').attr("data-stage-sum");
$("#choiceWayStage").val(sumStage);
$("#stages-pay-form #stageSumPay").val(sumStage);
$(".stageSum").text(sumStage);
$("#stages-pay-form #stagesIds").val($(this).val());
});
//Получить заказы
function getStages(orderId, senderId, recipentId, secureOrder) {
$.ajax({
url:'/api/orders/' + orderId + '/',
type: 'GET',
data:{csrfmiddlewaretoken: csrftoken},
dataType: 'json',
}).then(function(data){
var isReviewLeave = data.has_user_review;
var stagesResults = data.stages;
var stageCount = stagesResults.length;
if (stageCount == 0) {
$("#reserveSpace").hide();
stageCountVal = 1;
} else {
stageCountVal = stageCount;
}
var htmlInbox = "";
var htmlInboxStage = '<p class="textStepss">Какое кол-во этапов подразумевает работа? ' +
'<input type="text" id="countStage" value="' + stageCountVal + '"size="3"/></p>';
if (stageCount == 0) {
htmlInboxStage += '<div class="numberStepp box-sizing" id="stage1">' +
'<p>Этап <span class="stage-span-id">1</span></p><form class="new-stages-form" id="stage-form">' +
'<label for="">Название</label><input class="form-control" name="name" 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" type="hidden" name="status" value="send_approve">' +
'<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">' +
'<input class="form-control" name="pos" value="1" type="hidden">' +
'</form></div>';
}
var statusNotAgreed = true;
var stagesInWork = [];
var stagesPaidProcess = [];
var stagesCompleted = [];
var stagePaidCount = 0;
var stagesReservedHtml = "";
$.each(stagesResults, function (i, v) {
if (v.status == "completed"){
stagesCompleted.push(v);
}
if(!data.secure){
if(v.status == "in_process") {
stagesInWork.push(v);
}
}else if ((v.status == "in_process") && (v.is_paid)){
stagesInWork.push(v);
stagesPaidProcess.push(v);
}
if(v.is_paid){
stagePaidCount +=1;
}
if (v.status == "not_agreed" || v.status == 'cancel_approve' || v.status == 'send_approve') {
htmlInbox += '<div class="numberStepp box-sizing">' +
'<p>Этап</p><form class="update-stages-form" data-stage-id="' + v.id + '" id="stage-form-' + v.pos + '">' +
'<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 + '" >' +
'<input class="form-control orderStagesInput" type="hidden" name="order" value="' + v.order + '">' +
'<input class="form-control" type="hidden" name="status" value="send_approve">' +
'<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 + '" >' +
'</form></div>';
} else {
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 = 'Завершен';
}
htmlInbox += '<div class="numberStepp box-sizing"><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>' +
'<p>Cрок заказа рассчитывается с момента резервирования средств</p>' +
'</div><div><p style="font-color:red;">'+ statusName +'</p></div></div></div>';
}
if(data.secure) {
if (v.is_paid) {
stagesReservedHtml += '<li class="reserved">Сумма за этап ' + v.pos + '.Зарезервирована.</li>';
} else {
stagesReservedHtml += '<li class="unreserved">Сумма за этап ' + v.pos + '.Не зарезервирована.</li>';
}
}
});
if (stagesResults.length == stagePaidCount && data.secure){
$("#reserve-button").parent().hide();
}else {
$("#reserve-button").parent().show();
}
if (statusNotAgreed) {
if(!data.secure) {
htmlInbox += '<div class="box-sizing disTab">' +
'<div class="checkbox"><input name="secure" id="secureOrder" type="checkbox" style="opacity:1">' +
'Перейти в режим безопасной сделки</div></div>';
}
htmlInbox +='<div class="textAreaBlock2 box-sizing disTab">' +
'<a href="#" data-sender-id="' + senderId +'" ' +
'data-recipent-id="' + recipentId +'" data-order-id="' + orderId + '" ' +
'id="addStagesForm">отправить на согласование</a> </div>';
}else if((stagesResults.length>0) && (data.secure)){
$("#reserveSpace").show();
}
htmlInbox = htmlInboxStage + htmlInbox;
$("#order-stages").html(htmlInbox);
$("#completeWork").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 +'</p><span>' + stage.cost + '<i class="fa fa-rub"></i></span></div>' +
'</div></div>';
if (stage.close_contractor){
stageWork += '<div class="textAreaBlock2 FFD box-sizing disTab"><a href="#" class="closeStage" data-order-id="'+ orderId + '" data-sender-id="{{ request.user.pk }}"' +
' data-recipent-id="'+ recipentId + '" data-stage-id="'+ stage.id+'">Закрыть этап '+ stage.pos +'</a></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);
}
if (!data.secure){
$("#reserveSpace").hide();
}
if((stagesCompleted.length == stagesResults.length) && (stagesCompleted.length > 0) && (!isReviewLeave)){
$("#leaveReview").show();
}else {
$("#leaveReview").hide();
}
$(".stages-paid").html(stagesReservedHtml);
});
}
//Закрыть этап
$('#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_customer: true, status: 'completed'},
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);
}
});
});
// Добавление этапов
$("#order-stages").on('click', "#addStagesForm", function (e) {
e.preventDefault();
var currentOrderId = $(this).attr('data-order-id');
var secureOrderEl = $("#secureOrder");
if(secureOrderEl.length > 0) {
var secOrderVal = false;
if (secureOrderEl.prop('checked')) {
secOrderVal = true;
}
$.ajax({
url: '/api/orders/' + currentOrderId + '/',
type: 'PATCH',
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
},
data: {secure: secOrderVal},
dataType: 'json',
success: function (json){
},
error: function(e){
console.log(e);
}
});
}
$(".new-stages-form").each(function (i, v) {
var _this = $(this);
$.ajax({
url: '/api/stages/',
type: 'POST',
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
},
data: $(this).serialize(),
dataType: 'json',
success: function (json) {
_this.removeClass('new-stages-form').addClass('update-stages-form');
console.log(json);
},
error: function (e) {
console.log('error');
console.log(e);
}
});
});
$(".update-stages-form").each(function (i, v) {
var currentStageId = parseInt($(this).attr('data-stage-id'));
$.ajax({
url: '/api/stages/' + currentStageId + '/',
type: 'PUT',
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
},
data: $(this).serialize(),
dataType: 'json',
success: function (json) {
console.log(json);
},
error: function (e) {
console.log('error');
console.log(e);
}
});
});
var currentRecipentId = $(this).attr('data-recipent-id');
var secureOrder = true
socket.send_stages_approve({
"format_type": "approve_stages",
"data": {
"sender_id": userId,
"recipent_id": currentRecipentId,
"order_id": currentOrderId,
"msg": "Этапы для заказа "+ currentOrderId +" изменены",
}
});
});
//Изменение счетчика
$('#order-stages-tab').on('change', '#countStage', function () {
var countStage = parseInt($(this).val());
var currentCountStage = $("#order-stages .numberStepp").length;
if ((countStage<1) || isNaN(countStage)) {
countStage = 1;
$('#order-stages-tab #countStage').val(currentCountStage);
}else {
if (countStage > currentCountStage) {
for (var jj = currentCountStage; jj < countStage; jj++) {
var pos = jj + 1;
var lastFormStage = $("#order-stages .numberStepp").last();
var orderId = lastFormStage.find('.orderStagesInput').val();
var addFormTemplate = '<div class="numberStepp box-sizing" id="stage1">' +
'<p>Этап <span class="stage-span-id">' + pos + '</span></p><form class="new-stages-form" id="stage-form">' +
'<label for="">Название</label><input class="form-control" name="name" 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" type="hidden" name="status" value="send_approve">' +
'<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">' +
'<input class="form-control" name="pos" value="' + pos + '" type="hidden"></form></div>';
lastFormStage.after(addFormTemplate);
}
} else if (countStage < currentCountStage) {
var ii = currentCountStage;
$($("#order-stages .numberStepp").get().reverse()).each(function () {
var currenFormName = ($(this).find('form').attr('class'));
if (ii > countStage) {
$(this).remove();
}
ii--;
});
}
}
});
// Для заказов все вытащить
$('.order-block').on('click', function () {
$("#chat-order-add").css("display", "block");
$("#formsetStage").css("display", "block");
$('.order-block').each(function () {
$(this).removeClass('orAct');
});
$(this).addClass('orAct');
var orderId = $(this).attr('data-id');
location.hash = '#order' + orderId;
var projectId = $(this).attr('data-project-id');
var recipentId = $(this).attr('data-recipent-id');
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');
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 ' + 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/users/{{ request.user.pk }}/',
type: 'GET',
data: {
csrfmiddlewaretoken: csrftoken,
},
dataType:'json',
success: function(json){
var score = json.score;
$("#order-stages-tab").attr('data-score', score);
},
error: function(e,jqxhr){
console.log(jqxhr);
}
})
$.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) {
var noteHtmlInbox = '';
$.each(json.results, function (i, v) {
noteHtmlInbox += '<li>' + v.text + '<li>';
});
$(".order-notes-block").html(noteHtmlInbox);
}
});
getStages(orderId,userId,recipentId, secureOrder);
});
});
var userId = '{{ request.user.pk }}';
</script>
{% endblock %} {% endblock %}

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

@ -10,7 +10,7 @@ from wsgiref.util import FileWrapper
from .response import JSONResponse, response_mimetype from .response import JSONResponse, response_mimetype
from .utils import serialize from .utils import serialize
from .models import Message, Documents from .models import Message, Documents
from projects.models import Order from projects.models import Order, Project
from wallets.models import Transaction from wallets.models import Transaction
from users.models import User, Team from users.models import User, Team
@ -56,7 +56,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.customer_projects.select_related('order').exclude(order__contractor__isnull=True, order__team__isnull=True) orders = request.user.customer_projects.select_related('order').filter(state='active').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,
@ -75,7 +75,7 @@ class ChatUserView(LoginRequiredMixin, View):
teams = Team.objects.filter(contractors__id=request.user.pk).all() 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() 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() orders = Order.objects.filter(Q(contractor=request.user) | Q(team_id__in=team_ids)).filter(project__state='active').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)).\ Q(recipent_id=request.user.pk) | Q(sender_id=request.user.pk)).filter(Q(team_id=None)).\
filter(is_delete=False).distinct() filter(is_delete=False).distinct()
@ -115,6 +115,24 @@ def messages_delete(request):
raise Http404 raise Http404
def project_delete(request):
if request.is_ajax():
project_id = request.POST.get('project_id')
try:
project = Project.objects.get(pk=project_id,customer=request.user)
except Documents.DoesNotExist:
project = None
if project:
project.state = 'trashed'
project.save()
data = {'status': 'ok'}
else:
data = {'status': 'error'}
return HttpResponse(json.dumps(data), content_type='application/json')
else:
raise Http404
def download_file(request,file_name): def download_file(request,file_name):
try: try:
document = Documents.objects.get(file=file_name) document = Documents.objects.get(file=file_name)

@ -254,6 +254,7 @@ STATUSES = (
('completed', 'Завершен'), ('completed', 'Завершен'),
) )
from .validators import validate_term
class Stage(models.Model): class Stage(models.Model):
cost = models.DecimalField(max_digits=10, decimal_places=0) cost = models.DecimalField(max_digits=10, decimal_places=0)
@ -261,7 +262,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.DateField() term = models.DateField(validators=[validate_term])
term_type = models.CharField(max_length=10, choices=TERM_TYPES, default='hour') term_type = models.CharField(max_length=10, choices=TERM_TYPES, 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)
@ -274,6 +275,13 @@ class Stage(models.Model):
def __str__(self): def __str__(self):
return self.name return self.name
# def clean(self, *args, **kwargs):
# super().clean(*args, **kwargs)
#
# def save(self, *args, **kwargs):
# # self.full_clean()
# super().save(*args, **kwargs)
class Meta: class Meta:
ordering = ['pos'] ordering = ['pos']
verbose_name = 'Этап' verbose_name = 'Этап'

@ -0,0 +1,6 @@
from django.core.exceptions import ValidationError
def validate_term(date):
if date.weekday() != 0:
raise ValidationError("Это не ваш день")
Loading…
Cancel
Save