#ARC-16 add fixes

remotes/origin/PR-39
Mukhtar 10 years ago
parent 64de6a7711
commit 6ca840079a
  1. 1
      .gitignore
  2. 68
      assets/js/chat.js
  3. 16
      chat/chat.py
  4. 19
      chat/settings.example.py
  5. 6
      chat/templates/chat_contractor.html
  6. 54
      chat/templates/chat_customer.html
  7. 61
      chat/templates/reverse_stage_modal.html
  8. 2
      chat/urls.py
  9. 18
      chat/views.py
  10. 0
      common/management/commands/__init__.py
  11. 29
      common/management/commands/delete_old_files.py
  12. 37
      reviews/migrations/0005_auto_20160822_1600.py
  13. 7
      wallets/admin.py
  14. 25
      wallets/migrations/0008_wallet.py
  15. 8
      wallets/models.py
  16. 18
      wallets/signals.py

1
.gitignore vendored

@ -5,4 +5,5 @@ env/
ar/ ar/
archilance/settings/local.py archilance/settings/local.py
media/ media/
chat/settings.py
todo/ todo/

@ -19,10 +19,10 @@ var SocketHandler = function () {
inbox = document.getElementById('message-chat-order-space'); inbox = document.getElementById('message-chat-order-space');
} else if (message.answer_type == 'add_message_team') { } else if (message.answer_type == 'add_message_team') {
inbox = document.getElementById('message-chat-team-space'); inbox = document.getElementById('message-chat-team-space');
}else if (message.answer_type == 'approve_stages') { } else if (message.answer_type == 'approve_stages') {
alert('approve stages'); alert('approve stages');
} }
if(inbox) { if (inbox) {
inbox.innerHTML += '<div class="col-lg-12 insetCommChat"><div class="topCommChat">' + inbox.innerHTML += '<div class="col-lg-12 insetCommChat"><div class="topCommChat">' +
'<p class="nameCommChat">ВЫ</p> <span>Сейчас</span></div>' + '<p class="nameCommChat">ВЫ</p> <span>Сейчас</span></div>' +
'<p class="textCommChat">' + message.msg + '</p></div>'; '<p class="textCommChat">' + message.msg + '</p></div>';
@ -39,7 +39,7 @@ var SocketHandler = function () {
console.log(data); console.log(data);
}; };
this.send_stages_approve = function(data){ this.send_stages_approve = function (data) {
sock.send(JSON.stringify(data)); sock.send(JSON.stringify(data));
console.log(data); console.log(data);
}; };
@ -84,26 +84,56 @@ function csrfSafeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
} }
$(function(){ $(function () {
$('.deleteMess').on('click', function (e) {
e.preventDefault();
e.stopPropagation();
var senderId = userId;
var recipentId = $(this).attr('data-recipent-id');
var _this = $(this);
$.ajax({
url: '/chat/messages_delete/',
type: 'POST',
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
},
data: {'sender_id':senderId, 'recipent_id': recipentId},
dataType: 'json',
success: function (json) {
if (json.status == 'ok'){
_this.parent().remove();
$("#message-chat-space").html("");
}
},
error: function (e) {
console.log('error');
console.log(e);
}
});
});
$('#add-note-contractor').on('click', function (e) { $('#add-note-contractor').on('click', function (e) {
e.preventDefault(); e.preventDefault();
$.ajax({ $.ajax({
url: '/api/note/', url: '/api/note/',
type: 'POST', type: 'POST',
beforeSend: function (xhr) { beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken')) xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
}, },
data: $("#add-form-contractor-note").serialize(), data: $("#add-form-contractor-note").serialize(),
dataType: 'json', dataType: 'json',
success: function (json) { success: function (json) {
console.log(json); console.log(json);
$("#add-form-contractor-note #chat2").val(""); $("#add-form-contractor-note #chat2").val("");
$('<li>' + json.text + '</li>').appendTo(".contractor-notes-block"); $('<li>' + json.text + '</li>').appendTo(".contractor-notes-block");
}, },
error: function (e) { error: function (e) {
console.log('error'); console.log('error');
console.log(e); console.log(e);
} }
}); });
}); });
}); });

@ -3,22 +3,12 @@ from tornado import gen, web, websocket, escape, options
from tornado.ioloop import IOLoop from tornado.ioloop import IOLoop
from tornado.httpserver import HTTPServer from tornado.httpserver import HTTPServer
from tornado.options import parse_command_line from tornado.options import parse_command_line
from settings import settings, PORT, DATABASE_DSN
import psycopg2 import psycopg2
import momoko import momoko
import json import json
settings = {
'cookie_secret': '__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__',
'template_path': os.path.join(os.path.dirname(__file__), 'templates'),
'static_path': os.path.join(os.path.dirname(__file__), 'static'),
'login_url': '/login',
'xsrf_cookies': True,
'debug': True,
'autoreload': True,
'server_traceback': True,
}
class BaseHandler(web.RequestHandler): class BaseHandler(web.RequestHandler):
@property @property
@ -105,7 +95,7 @@ if __name__ == '__main__':
ioloop = IOLoop.instance() ioloop = IOLoop.instance()
application.db = momoko.Pool( application.db = momoko.Pool(
dsn='dbname=archilance user=postgres password=postgres host=localhost', dsn=DATABASE_DSN,
size=1, size=1,
ioloop=ioloop, ioloop=ioloop,
) )
@ -115,5 +105,5 @@ if __name__ == '__main__':
future.result() future.result()
http_server = HTTPServer(application) http_server = HTTPServer(application)
http_server.listen(8888, 'localhost') http_server.listen(PORT, 'localhost')
ioloop.start() ioloop.start()

@ -0,0 +1,19 @@
import os
PORT = 8888
settings = {
'cookie_secret': '__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__',
'template_path': os.path.join(os.path.dirname(__file__), 'templates'),
'static_path': os.path.join(os.path.dirname(__file__), 'static'),
'login_url': '/login',
'xsrf_cookies': True,
'debug': True,
'autoreload': True,
'server_traceback': True,
}
DATABASE_DSN = 'dbname=archilance user=postgres password=postgres host=localhost'

@ -53,7 +53,7 @@
<a href="#" class="conMess">Контакты</a> <a href="#" class="conMess">Контакты</a>
<span>0</span> <span>0</span>
<a href="javascript:void(0)" class="deleteMess"> <a href="#" class="deleteMess" data-recipent-id="{{ contact.pk }}">
Удалить контакт Удалить контакт
</a> </a>
</div> </div>
@ -450,9 +450,9 @@
$.each(json.results, function (i, v) { $.each(json.results, function (i, v) {
if (v.is_paid) { if (v.is_paid) {
stagesReservedHtml += '<li class="reserved">Сумма за этап ' + i + '.Зарезервирована.</li>'; stagesReservedHtml += '<li class="reserved">Сумма за этап ' + v.pos + '.Зарезервирована.</li>';
} else { } else {
stagesReservedHtml += '<li class="unreserved">Сумма за этап ' + i + '.Не зарезервирована.</li>'; stagesReservedHtml += '<li class="unreserved">Сумма за этап ' + v.pos + '.Не зарезервирована.</li>';
} }
htmlInbox += '<div data-id="' + v.id + '" class="numberStepp box-sizing stage-block-approve"><div class="insetNumStepp">' + htmlInbox += '<div data-id="' + v.id + '" class="numberStepp box-sizing stage-block-approve"><div class="insetNumStepp">' +
'<p class="titleNumStepp"><span>Этап ' + v.pos + '</span>' + v.name + '</p>' + '<p class="titleNumStepp"><span>Этап ' + v.pos + '</span>' + v.name + '</p>' +

@ -48,7 +48,7 @@
class="conMess">Контакты</a> class="conMess">Контакты</a>
<span>0</span> <span>0</span>
<a href="javascript:void(0)" class="deleteMess"> <a href="#" class="deleteMess" data-recipent-id="{{ contact.pk }}">
Удалить контакт Удалить контакт
</a> </a>
</div> </div>
@ -159,37 +159,14 @@
</p> </p>
<div class="textAreaBlock2 FFD box-sizing disTab"> <div class="textAreaBlock2 FFD box-sizing disTab">
<a href="#" data-toggle="modal" data-target="#reserve-stage-modal">Зарезирвировать</a> <a href="#" id="reserve-button" data-order-id="" data-toggle="modal" data-target="#reserve-stage-modal">Зарезирвировать</a>
</div> </div>
</div> </div>
<!-- Зарезервировать средства (модальное окно)--> <!-- Зарезервировать средства (модальное окно)-->
<div id="reserve-stage-modal" class="modal fade"> {% include 'reverse_stage_modal.html' %}
<div class="modal-dialog" style="width:900px;"> <!-- Конец блока -->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">Зарезервировать средства</h4>
</div>
<div class="modal-body">
<div class="textAreaBlock2 text-nn box-sizing disTab">
<input type="radio" name="choice_way" value="" />Сумма оплаты всего заказа
<input type="radio" name="choice_way" value="" /> Оплатить этап
</div>
<h2>Резервирование средств</h2>
<h5>Оплатить через яндекс</h5>
<div class="searchF1 polsF1 polsFF links-filter">
<input class="btn-submit-link" type="submit" value="Сохранить">
</div>
</div>
<div class="modal-footer"></div>
</div>
</div>
</div>
<!-- Конец блока -->
<div class="stepssBlock box-sizing disTab"> <div class="stepssBlock box-sizing disTab">
<p class="titleStepss">3 / Выполнение работы</p> <p class="titleStepss">3 / Выполнение работы</p>
@ -290,6 +267,20 @@
var form = document.getElementById('message_form'); var form = document.getElementById('message_form');
var csrftoken = getCookie('csrftoken'); var csrftoken = getCookie('csrftoken');
$("#reserve-button").on("click",function(e) {
e.preventDefault();
var orderId = $(this).attr('data-order-id');
$.ajax({
url: '/api/stages/',
type: 'GET',
data: {csrfmiddlewaretoken: csrftoken, 'order': orderId},
dataType: 'json',
success: function (json) {
console.log(json.results);
}
});
});
function getStages(orderId, senderId, recipentId) { function getStages(orderId, senderId, recipentId) {
$.ajax({ $.ajax({
@ -318,6 +309,7 @@
'<input class="form-control orderStagesInput" name="order" type="hidden" value="' + orderId + '"/>' + '<input class="form-control orderStagesInput" name="order" type="hidden" value="' + orderId + '"/>' +
'<label for="">Срок</label><input class="form-control" name="term" type="text" />' + '<label for="">Срок</label><input class="form-control" name="term" type="text" />' +
'<label for="">Результат</label><input class="form-control" name="result" type="text" />' + '<label for="">Результат</label><input class="form-control" name="result" type="text" />' +
'<label for="">Позиция</label><input class="form-control" name="pos" value="1" type="text" />' +
'</form></div>'; '</form></div>';
} }
var statusNotAgreed = true; var statusNotAgreed = true;
@ -337,7 +329,7 @@
htmlInbox += '<div class="numberStepp box-sizing"><div class="insetNumStepp">' + htmlInbox += '<div class="numberStepp box-sizing"><div class="insetNumStepp">' +
'<p class="titleNumStepp"><span>Этап ' + v.pos + '</span>' + v.name + '</p>' + '<p class="titleNumStepp"><span>Этап ' + v.pos + '</span>' + v.name + '</p>' +
'<p class="textNumStepp">Результаты этапа:' + v.result + '</p><div>' + '<p class="textNumStepp">Результаты этапа:' + v.result + '</p><div>' +
'<p>до 16.03.2015</p><span>' + v.cost + '<i class="fa fa-rub"></i></span></div></div></div>'; '<p>до Дата</p><span>' + v.cost + '<i class="fa fa-rub"></i></span></div></div></div>';
} }
}); });
@ -430,15 +422,17 @@
if (countStage > currentCountStage){ if (countStage > currentCountStage){
for(var jj=currentCountStage; jj<countStage;jj++){ for(var jj=currentCountStage; jj<countStage;jj++){
var pos = jj + 1;
var lastFormStage = $(".numberStepp").last(); var lastFormStage = $(".numberStepp").last();
var orderId = lastFormStage.find('.orderStagesInput').val(); var orderId = lastFormStage.find('.orderStagesInput').val();
var addFormTemplate = '<div class="numberStepp box-sizing" id="stage1">' + var addFormTemplate = '<div class="numberStepp box-sizing" id="stage1">' +
'<p>Этап <span class="stage-span-id">1</span></p><form class="new-stages-form" id="stage-form">' + '<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="name" type="text" />' +
'<label for="">Цена</label><input class="form-control" name="cost" type="text" />' + '<label for="">Цена</label><input class="form-control" name="cost" type="text" />' +
'<input class="form-control orderStagesInput" name="order" type="hidden" value="' + orderId + '" />' + '<input class="form-control orderStagesInput" name="order" type="hidden" value="' + orderId + '" />' +
'<label for="">Срок</label><input class="form-control" name="term" type="text" />' + '<label for="">Срок</label><input class="form-control" name="term" type="text" />' +
'<label for="">Результат</label><input class="form-control" name="result" type="text" />' + '<label for="">Результат</label><input class="form-control" name="result" type="text" />' +
'<label for="">Позиция</label><input class="form-control" name="pos" value="'+ pos +'" type="text" />'
'</form></div>'; '</form></div>';
lastFormStage.after(addFormTemplate); lastFormStage.after(addFormTemplate);
@ -481,6 +475,7 @@
var recipentId = $(this).attr('data-recipent-id'); var recipentId = $(this).attr('data-recipent-id');
$("#chat-order-add #orderId").val(orderId); $("#chat-order-add #orderId").val(orderId);
$("#projectReviewId").val(orderId); $("#projectReviewId").val(orderId);
$("#reserve-button").attr('data-order-id', orderId);
$("#targetContractorId").val(recipentId); $("#targetContractorId").val(recipentId);
$("#chat-order-add #recipentId").val(recipentId); $("#chat-order-add #recipentId").val(recipentId);
$(".orderStagesInput").val(orderId); $(".orderStagesInput").val(orderId);
@ -550,7 +545,6 @@
}); });
$('#contact-chat-add-message').on('click', function () { $('#contact-chat-add-message').on('click', function () {
var chatMessage = $("#chat").val(); var chatMessage = $("#chat").val();
var recipentId = $("#recipentId").val(); var recipentId = $("#recipentId").val();

@ -0,0 +1,61 @@
<div id="reserve-stage-modal" class="modal fade">
<div class="modal-dialog" style="width:900px;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">Зарезервировать средства</h4>
</div>
<div class="modal-body" style="height: 300px;">
<div class="searchF1 polsF1 polsFF radio-afer">
<div class="col-lg-6">
<label>
<input type="radio" name="choice_way" value="secure_deal">
<span></span>
</label>
<p class="text-afer">Сумма оплаты всего заказа</p>
<p class="des-afer">
Общий бюджет заказа: 300 р. <br />
Итого к оплате: 344 рубля
</p>
</div>
</div>
<div class="searchF1 polsF1 polsFF radio-afer">
<div class="col-lg-6">
<label>
<input type="radio" name="choice_way" value="choice_way">
<span></span>
</label>
<p class="text-afer">Оплатить этап</p><br />
<p class="des-afer">
Бюджет Этапа 1: 300 р.<br />
Итого к оплате: 344 р.
</p>
</div>
<div class="col-lg-6">
<select class="selectpicker">
<option>Этап1</option>
<option>Этап1</option>
<option>Этап1</option>
</select>
</div>
</div>
<div class="searchF1 polsF1 polsFF radio-afe" style="padding-top: 20px;padding-left: 50px;">
<p class="titleStepss">Резервирование средств</p>
</div>
</div>
<div class="modal-footer">
</div>
</div>
</div>
</div>

@ -2,10 +2,12 @@ from django.conf import urls
from .views import ( from .views import (
ChatUserView, ChatUserView,
messages_delete,
) )
app_name = 'chat' 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'),
] ]

@ -1,12 +1,11 @@
import json
from django.shortcuts import render from django.shortcuts import render
from django.views.generic import View from django.views.generic import View
from django.http import HttpResponse, Http404
from django.db.models import Q from django.db.models import Q
from django.forms import formset_factory
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from .models import Message from .models import Message
from .forms import ArticleForm
from reviews.forms import Review
from users.models import User from users.models import User
@ -68,5 +67,14 @@ class ChatUserView(LoginRequiredMixin, View):
}) })
def messages_delete(request):
if request.is_ajax():
sender = request.POST.get('sender_id')
recipent = request.POST.get('recipent_id')
queryset = Message.objects.all()
# queryset = queryset.filter(Q(sender__in=[sender,recipent]),Q(recipent__in=[sender,recipent]))
# queryset.delete()
data = {'status': 'ok'}
return HttpResponse(json.dumps(data), content_type='application/json')
else:
raise Http404

@ -0,0 +1,29 @@
import os
import datetime
from django.core.management import BaseCommand
from django.conf import settings
class Command(BaseCommand):
def handle(self, *args, **options):
days = 20
directory = os.path.join(settings.MEDIA_ROOT,'common/printdocuments')
files_list = []
date_now = datetime.datetime.now()
for root, subfolders, files in os.walk(directory):
for f in files:
files_list.append(os.path.join(root,f))
for f in files_list:
try:
date_modify = datetime.datetime.fromtimestamp(os.path.getmtime(f))
days_diff = (date_now-date_modify).days
if days_diff > days:
os.remove(f)
except OSError as e:
print(e.strerror + " " + e.filename)

@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-08-22 13:00
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 = [
('reviews', '0004_auto_20160811_1507'),
]
operations = [
migrations.AlterField(
model_name='review',
name='from_contractor',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='contractor_reviews', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='review',
name='from_customer',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='customer_reviews', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='review',
name='target_contractor',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='reviews_by_contractor', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='review',
name='target_customer',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='reviews_by_customer', to=settings.AUTH_USER_MODEL),
),
]

@ -1,6 +1,6 @@
from django.contrib import admin from django.contrib import admin
from .models import InvoiceHistory, WithDraw from .models import InvoiceHistory, WithDraw, Transaction
class InvoiceHistoryAdmin(admin.ModelAdmin): class InvoiceHistoryAdmin(admin.ModelAdmin):
@ -11,5 +11,10 @@ class WithDrawAdmin(admin.ModelAdmin):
list_display = ('sum','created','user',) list_display = ('sum','created','user',)
class TransactionAdmin(admin.ModelAdmin):
list_display = ('customer','complete',)
admin.site.register(InvoiceHistory, InvoiceHistoryAdmin) admin.site.register(InvoiceHistory, InvoiceHistoryAdmin)
admin.site.register(WithDraw, WithDrawAdmin) admin.site.register(WithDraw, WithDrawAdmin)
admin.site.register(Transaction, TransactionAdmin)

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-08-22 13:00
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 = [
('users', '0011_auto_20160819_1735'),
('wallets', '0007_auto_20160818_2131'),
]
operations = [
migrations.CreateModel(
name='Wallet',
fields=[
('customer', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to=settings.AUTH_USER_MODEL)),
('balance', models.DecimalField(decimal_places=0, default=0, max_digits=10)),
],
),
]

@ -11,6 +11,14 @@ TYPES = (
) )
class Wallet(models.Model):
customer = models.OneToOneField(User, on_delete=models.CASCADE,primary_key=True)
balance = models.DecimalField(max_digits=10, decimal_places=0, default=0)
def __str__(self):
return str(self.balance)
class InvoiceHistory(models.Model): class InvoiceHistory(models.Model):
comment = models.TextField(blank=True) comment = models.TextField(blank=True)
created = models.DateTimeField(default=timezone.now) created = models.DateTimeField(default=timezone.now)

@ -3,7 +3,7 @@ from django.dispatch import receiver
from django.core.mail import send_mail, EmailMultiAlternatives from django.core.mail import send_mail, EmailMultiAlternatives
from django.template.loader import get_template, render_to_string from django.template.loader import get_template, render_to_string
from .models import WithDraw, InvoiceHistory from .models import WithDraw, InvoiceHistory, Transaction
@receiver(post_save, sender=WithDraw) @receiver(post_save, sender=WithDraw)
@ -20,3 +20,19 @@ def send_for_accountant(sender, instance, created, **kwargs):
msg.send() msg.send()
@receiver(post_save, sender=Transaction)
def add_invoice_history(sender, instance,created, **kwargs):
if 'add' in instance.type:
inv_history = InvoiceHistory()
inv_history.comment = 'Пополнение счета'
inv_history.sum = instance.sum
inv_history.user = instance.user
inv_history.save()
@receiver(post_save, sender=Transaction)
def reserve_stages(sender, instance, created, **kwargs):
if 'reservation' in instance.type:
pass

Loading…
Cancel
Save