#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/
archilance/settings/local.py
media/
chat/settings.py
todo/

@ -19,10 +19,10 @@ var SocketHandler = function () {
inbox = document.getElementById('message-chat-order-space');
} else if (message.answer_type == 'add_message_team') {
inbox = document.getElementById('message-chat-team-space');
}else if (message.answer_type == 'approve_stages') {
} else if (message.answer_type == 'approve_stages') {
alert('approve stages');
}
if(inbox) {
if (inbox) {
inbox.innerHTML += '<div class="col-lg-12 insetCommChat"><div class="topCommChat">' +
'<p class="nameCommChat">ВЫ</p> <span>Сейчас</span></div>' +
'<p class="textCommChat">' + message.msg + '</p></div>';
@ -39,7 +39,7 @@ var SocketHandler = function () {
console.log(data);
};
this.send_stages_approve = function(data){
this.send_stages_approve = function (data) {
sock.send(JSON.stringify(data));
console.log(data);
};
@ -84,26 +84,56 @@ function csrfSafeMethod(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) {
e.preventDefault();
$.ajax({
url: '/api/note/',
type: 'POST',
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
},
data: $("#add-form-contractor-note").serialize(),
dataType: 'json',
success: function (json) {
console.log(json);
$("#add-form-contractor-note #chat2").val("");
$('<li>' + json.text + '</li>').appendTo(".contractor-notes-block");
},
error: function (e) {
console.log('error');
console.log(e);
}
type: 'POST',
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'))
},
data: $("#add-form-contractor-note").serialize(),
dataType: 'json',
success: function (json) {
console.log(json);
$("#add-form-contractor-note #chat2").val("");
$('<li>' + json.text + '</li>').appendTo(".contractor-notes-block");
},
error: function (e) {
console.log('error');
console.log(e);
}
});
});
});

@ -3,22 +3,12 @@ from tornado import gen, web, websocket, escape, options
from tornado.ioloop import IOLoop
from tornado.httpserver import HTTPServer
from tornado.options import parse_command_line
from settings import settings, PORT, DATABASE_DSN
import psycopg2
import momoko
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):
@property
@ -105,7 +95,7 @@ if __name__ == '__main__':
ioloop = IOLoop.instance()
application.db = momoko.Pool(
dsn='dbname=archilance user=postgres password=postgres host=localhost',
dsn=DATABASE_DSN,
size=1,
ioloop=ioloop,
)
@ -115,5 +105,5 @@ if __name__ == '__main__':
future.result()
http_server = HTTPServer(application)
http_server.listen(8888, 'localhost')
http_server.listen(PORT, 'localhost')
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>
<span>0</span>
<a href="javascript:void(0)" class="deleteMess">
<a href="#" class="deleteMess" data-recipent-id="{{ contact.pk }}">
Удалить контакт
</a>
</div>
@ -450,9 +450,9 @@
$.each(json.results, function (i, v) {
if (v.is_paid) {
stagesReservedHtml += '<li class="reserved">Сумма за этап ' + i + '.Зарезервирована.</li>';
stagesReservedHtml += '<li class="reserved">Сумма за этап ' + v.pos + '.Зарезервирована.</li>';
} 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">' +
'<p class="titleNumStepp"><span>Этап ' + v.pos + '</span>' + v.name + '</p>' +

@ -48,7 +48,7 @@
class="conMess">Контакты</a>
<span>0</span>
<a href="javascript:void(0)" class="deleteMess">
<a href="#" class="deleteMess" data-recipent-id="{{ contact.pk }}">
Удалить контакт
</a>
</div>
@ -159,37 +159,14 @@
</p>
<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 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">
<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>
<!-- Конец блока -->
{% include 'reverse_stage_modal.html' %}
<!-- Конец блока -->
<div class="stepssBlock box-sizing disTab">
<p class="titleStepss">3 / Выполнение работы</p>
@ -290,6 +267,20 @@
var form = document.getElementById('message_form');
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) {
$.ajax({
@ -318,6 +309,7 @@
'<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="result" type="text" />' +
'<label for="">Позиция</label><input class="form-control" name="pos" value="1" type="text" />' +
'</form></div>';
}
var statusNotAgreed = true;
@ -337,7 +329,7 @@
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>до 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){
for(var jj=currentCountStage; jj<countStage;jj++){
var pos = jj + 1;
var lastFormStage = $(".numberStepp").last();
var orderId = lastFormStage.find('.orderStagesInput').val();
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="cost" type="text" />' +
'<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="result" type="text" />' +
'<label for="">Позиция</label><input class="form-control" name="pos" value="'+ pos +'" type="text" />'
'</form></div>';
lastFormStage.after(addFormTemplate);
@ -481,6 +475,7 @@
var recipentId = $(this).attr('data-recipent-id');
$("#chat-order-add #orderId").val(orderId);
$("#projectReviewId").val(orderId);
$("#reserve-button").attr('data-order-id', orderId);
$("#targetContractorId").val(recipentId);
$("#chat-order-add #recipentId").val(recipentId);
$(".orderStagesInput").val(orderId);
@ -550,7 +545,6 @@
});
$('#contact-chat-add-message').on('click', function () {
var chatMessage = $("#chat").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 (
ChatUserView,
messages_delete,
)
app_name = 'chat'
urlpatterns = [
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.views.generic import View
from django.http import HttpResponse, Http404
from django.db.models import Q
from django.forms import formset_factory
from django.contrib.auth.mixins import LoginRequiredMixin
from .models import Message
from .forms import ArticleForm
from reviews.forms import Review
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 .models import InvoiceHistory, WithDraw
from .models import InvoiceHistory, WithDraw, Transaction
class InvoiceHistoryAdmin(admin.ModelAdmin):
@ -11,5 +11,10 @@ class WithDrawAdmin(admin.ModelAdmin):
list_display = ('sum','created','user',)
class TransactionAdmin(admin.ModelAdmin):
list_display = ('customer','complete',)
admin.site.register(InvoiceHistory, InvoiceHistoryAdmin)
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):
comment = models.TextField(blank=True)
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.template.loader import get_template, render_to_string
from .models import WithDraw, InvoiceHistory
from .models import WithDraw, InvoiceHistory, Transaction
@receiver(post_save, sender=WithDraw)
@ -20,3 +20,19 @@ def send_for_accountant(sender, instance, created, **kwargs):
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