callback, invoice and its docs

remotes/origin/yandex
Bachurin Sergey 12 years ago
parent d2c989df2d
commit dd78e62b47
  1. 0
      project/callback/__init__.py
  2. 23
      project/callback/admin.py
  3. 8
      project/callback/context_processors.py
  4. 31
      project/callback/forms.py
  5. 44
      project/callback/migrations/0001_initial.py
  6. 73
      project/callback/migrations/0002_auto__add_field_reqavail_user.py
  7. 0
      project/callback/migrations/__init__.py
  8. 45
      project/callback/models.py
  9. 8
      project/callback/urls.py
  10. 61
      project/callback/views.py
  11. 1
      project/docs/consts.py
  12. 9
      project/docs/models/invoice.py
  13. 12
      project/settings.py
  14. 2
      project/static/css/style.css
  15. 22
      project/static/js/callback.js
  16. 1
      project/static/js/commons.js
  17. 4
      project/static/js/dialogs.js
  18. 6
      project/templates/admin/callback/callback_change.html
  19. 11
      project/templates/base.html
  20. 1
      project/templates/callback/callback_btn.html
  21. 16
      project/templates/callback/callback_form.html
  22. 4
      project/templates/callback/req_avail_done.txt
  23. 14
      project/templates/callback/req_avail_new.txt
  24. 1
      project/templates/customer/index.html
  25. 23
      project/templates/docs/parts/invoice_create_docs.html
  26. 1
      project/urls.py

@ -0,0 +1,23 @@
from django.contrib import admin
from.models import ReqAvail
def user_name(obj):
if obj.user:
if obj.user.profile:
return obj.user.profile
else:
return obj.user.email
else:
return None
user_name.short_description = 'email'
class ReqAvailAdmin(admin.ModelAdmin):
change_form_template = 'admin/callback/callback_change.html'
list_display = (user_name, 'created_at', 'updated_at')
exclude = ('user',)
admin.site.register(ReqAvail, ReqAvailAdmin)

@ -0,0 +1,8 @@
# -*- coding: utf-8 -*-
from .forms import ReqAvailForm
def add_forms(request):
return {
'reqf': ReqAvailForm(request.GET or None),
}

@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
from django import forms
from . import models
class ReqAvailForm(forms.ModelForm):
"""Форма заказа товара."""
class Meta:
model = models.ReqAvail
fields = ('name', 'phone', 'message')
def __init__(self, *args, **kwargs):
super(ReqAvailForm, self).__init__(*args, **kwargs)
self.fields['name'].label = u'Ваше имя'
self.fields['name'].widget.attrs['placeholder'] = u'Ваше имя, отчество'
self.fields['phone'].widget.attrs['placeholder'] = u'Ваш номер телефона или e-mail'
self.fields['name'].widget.attrs['width'] = u'Ваше имя, отчество'
def clean(self):
super(ReqAvailForm, self).clean()
name = self.cleaned_data.get('name', '').strip()
phone = self.cleaned_data.get('phone', '').strip()
if not name:
raise forms.ValidationError(u'Укажите Ваше имя.')
if not phone:
raise forms.ValidationError(u'Укажите Ваш телефон.')
return self.cleaned_data

@ -0,0 +1,44 @@
# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'ReqAvail'
db.create_table(u'callback_reqavail', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('name', self.gf('django.db.models.fields.CharField')(max_length=100)),
('phone', self.gf('django.db.models.fields.CharField')(max_length=50)),
('message', self.gf('django.db.models.fields.TextField')()),
('status', self.gf('django.db.models.fields.PositiveSmallIntegerField')(default=0)),
('status_changed', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),
('created_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
('updated_at', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)),
))
db.send_create_signal(u'callback', ['ReqAvail'])
def backwards(self, orm):
# Deleting model 'ReqAvail'
db.delete_table(u'callback_reqavail')
models = {
u'callback.reqavail': {
'Meta': {'ordering': "['-created_at']", 'object_name': 'ReqAvail'},
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'message': ('django.db.models.fields.TextField', [], {}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'phone': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'status': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '0'}),
'status_changed': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
}
}
complete_apps = ['callback']

@ -0,0 +1,73 @@
# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding field 'ReqAvail.user'
db.add_column(u'callback_reqavail', 'user',
self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='messages', null=True, to=orm['auth.User']),
keep_default=False)
def backwards(self, orm):
# Deleting field 'ReqAvail.user'
db.delete_column(u'callback_reqavail', 'user_id')
models = {
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'callback.reqavail': {
'Meta': {'ordering': "['-created_at']", 'object_name': 'ReqAvail'},
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'message': ('django.db.models.fields.TextField', [], {}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'phone': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'status': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '0'}),
'status_changed': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'messages'", 'null': 'True', 'to': u"orm['auth.User']"})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
}
}
complete_apps = ['callback']

@ -0,0 +1,45 @@
# -*- coding: utf-8 -*-
import os.path
from django.db import models
from django.db.models import Q
from django.contrib.auth.models import User
class ReqAvail(models.Model):
"""Заказ товара."""
NEW_STATUS = 0
DONE_STATUS = 1
STATUS_CHOICES = (
(NEW_STATUS, u'Новый'),
(DONE_STATUS, u'Обработан'),
)
name = models.CharField(u'Имя клиента', max_length=100)
phone = models.CharField(u'Телефон или e-mail', max_length=50)
message = models.TextField(u'Текст сообщения')
user = models.ForeignKey(User, related_name='messages', null=True, blank=True)
# email = models.EmailField(u'E-mail', default='', blank=True)
# region = models.ForeignKey(Region, verbose_name=u"Регион", blank=False, null=False, default='')
#good = models.ForeignKey(CatalogItem, verbose_name=u'Товар', null=True, blank=True)
status = models.PositiveSmallIntegerField(u'Статус', choices=STATUS_CHOICES, default=NEW_STATUS)
status_changed = models.DateTimeField(u'Статус изменен', null=True, blank=True, editable=False)
created_at = models.DateTimeField(u'Дата заказа', auto_now_add=True)
updated_at = models.DateTimeField(u'Изменен', auto_now=True)
class Meta:
verbose_name = u'Обратная связь'
verbose_name_plural = u'Обратная связь'
ordering = ['-created_at',]
def __unicode__(self):
return u'Сообщение %s от %s' % (
#self.good if self.good_id else u'(Ничего)',
self.name[:20],
self.created_at.strftime("%d.%m.%Y %H:%M"),
)

@ -0,0 +1,8 @@
# -*- coding: utf-8 -*-
from django.conf.urls.defaults import patterns, url
from .views import req_avail
urlpatterns = patterns('',
url(r'^send/$', req_avail, name='callback-send-message'),
url(r'^send/(?P<id>\d+)/$', req_avail, name='callback-request-item'),
)

@ -0,0 +1,61 @@
# -*- coding: utf-8 -*-
import json
from django.http import HttpResponseBadRequest, HttpResponse
from django.views.decorators.http import require_POST, require_GET
from django.views.decorators.csrf import csrf_protect
from django.template.loader import render_to_string
from django.core.mail import send_mail
from django.conf import settings
from .models import ReqAvail
from .forms import ReqAvailForm
CALLBACK_SETTINGS = getattr(settings, 'CALLBACK_SETTINGS')
@require_POST
@csrf_protect
def req_avail(request, id=None):
"""Отправить сообщение или обработать запрос наличия товара на складе - AJAX."""
if not request.is_ajax():
return HttpResponseBadRequest()
if id:
good = get_object_or_404(CatalogItem, pk=id)
else:
good = None
form = ReqAvailForm(data=request.POST)
if form.is_valid():
if request.user.is_authenticated():
user = request.user
else:
user = None
req = ReqAvail.objects.create(
name=form.cleaned_data['name'].strip(),
phone=form.cleaned_data['phone'].strip(),
user=user,
#good=good,
)
# отправить письма менеджерам
subject = CALLBACK_SETTINGS['NEW_REQ_AVAIL_EMAIL_SUBJ']
sender = CALLBACK_SETTINGS['EMAIL_SENDER']
recipients = CALLBACK_SETTINGS['MANAGERS_EMAILS']
message = render_to_string('callback/req_avail_new.txt', {'req': req, })
send_mail(subject, message, sender, recipients)
data = {
'success': form.is_valid(),
# 'field_errors': form.errors, # ошибки полей
'form_errors': form.non_field_errors(), # ошибки формы
}
if form.is_valid():
data['message'] = {
'title': u'Сообщение',
'msg': u'Ваша Сообщение отправлено!<br />Скоро с Вами свяжется наш менеджер.',
}
return HttpResponse(json.dumps(data), mimetype='application/json')

@ -144,3 +144,4 @@ TAX_TYPE = (
(u'ИШ', u'ИШ - иные штрафы, установленные соответствующими нормативными актами'),
( u'0', u'0 - Конкретное значение указать невозможно'),
)

@ -20,6 +20,15 @@ class Invoice(BaseInvoiceModel):
paid_status = models.PositiveSmallIntegerField(u'Оплачен?', choices=PAID_CHOICES, default=UNPAID)
closed_status = models.BooleanField(u'Закрыт?', choices=consts.BOOL_CHOICES, default=False)
def docs_for_invoice(self):
doc_list = ['Faktura', 'Nakladn', 'AktRabot', ]
client_docs = {}
for doc in doc_list:
docs = models.get_model('docs', doc).objects.filter(invoice=self)
if docs:
client_docs[doc] = docs
return client_docs
class Meta(BaseInvoiceModel.Meta):
verbose_name = u'Счёт'
verbose_name_plural = u'Счета'

@ -129,6 +129,7 @@ TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.static',
'cms.context_processors.cms_settings',
'sekizai.context_processors.sekizai',
'project.callback.context_processors.add_forms',
)
@ -161,6 +162,7 @@ INSTALLED_APPS = (
'mptt', # utilities for implementing a modified pre-order traversal tree
'menus', # helper for model independent hierarchical website navigation
'sekizai', # for javascript and css management
'captcha',
#'robokassa',
'djangocms_admin_style', # for the admin skin. You **must** add 'djangocms_admin_style' in the list before 'django.contrib.admin'.
'django.contrib.messages', # to enable messages framework (see :ref:`Enable messages <enable-messages>`)
@ -183,6 +185,7 @@ INSTALLED_APPS = (
'project.customer',
'project.docs',
'project.pages',
'project.callback',
# keep it last
'south',
@ -252,6 +255,15 @@ ROBOKASSA_TEST_MODE = True
from datetime import timedelta
CALLBACK_SETTINGS = {
'EMAIL_SENDER': 'whosondutytoday@yandex.ru',
'CHIEF_EMAILS': ['chkur@mailinator.com',],
'MANAGERS_EMAILS': ['chkur@mailinator.com',],
'NEW_REQ_AVAIL_EMAIL_SUBJ': u'Вопрос',
'DONE_REQ_AVAIL_EMAIL_SUBJ': u'Сообщение обработано менеджером',
}
CELERYBEAT_SCHEDULE = {
'check-license': {
'task': 'project.customer.tasks.check_license',

@ -222,3 +222,5 @@ div.blockMsg { width: 100%; height: 100%; top: 0; left: 0; text-align: center; }
tr.doc-row:hover {cursor:pointer;}
#clients tr:nth-child(odd) {background: #f5f5f5;}
#req-avail-form {display:none;}

@ -0,0 +1,22 @@
$(document).ready(function() {
var form = $('#req-avail-form');
form.dialog({
dialogClass: "white-dlg",
modal: true,
autoOpen: false,
Width: 324,
resizable: false,
beforeClose: function(event, ui) {
clear_form_errors(form);
}
});
})
function show_req_avail_form(action) {
var form = $('#req-avail-form');
form.attr('action', action);
form.dialog();
form.dialog('open');
return false;
}

@ -30,3 +30,4 @@ function getUrlVars() {
}
return vars;
}

@ -8,11 +8,11 @@ $(document).ready(function() {
dataType: 'json',
timeout: 30000,
beforeSubmit: function() {
$('input', form).attr('disabled', 'disabled');
$(':input', form).attr('disabled', 'disabled');
$('button', form).attr('disabled', 'disabled');
},
complete: function(data) {
$('input', form).removeAttr('disabled');
$(':input', form).removeAttr('disabled');
$('button', form).removeAttr('disabled');
},

@ -0,0 +1,6 @@
{% extends "admin/change_form.html" %}
{% block field_sets %}
{% if original.user %}<p>{{ original.user.profile }}</p>{% endif %}
{{ block.super }}
{% endblock %}

@ -25,14 +25,17 @@
<div style="margin: 10px 0; height: 30px;">
<div style="float: left; font-weight: bold; font-size: 22px;">
<a href="/">Документор</a>
</div>
<div class='right'>
<span>{% static_placeholder "header_phone" %}</span>
<span>{% static_placeholder "header_address" %}</span>
<a href="#" onclick="return show_req_avail_form('{% url 'callback-send-message' %}');">Оставить сообщение</a>
</div>
<div class='clear'></div>
<div id="menu">
<ul>
<ul style='float:left;width:500px;'>
{% show_menu 0 100 100 100 "cms/menu/main.html" %}
</ul>
</div>
{% if user.is_authenticated %}
<div style="float: right; margin-right: 10px;">
@ -48,6 +51,7 @@
</div>
{% endif %}
</div>
</div>
<div class="clear"></div>
@ -59,8 +63,10 @@
<div id="dialogs">
{% block dialogs %}{% endblock %}
{% include "callback/callback_form.html" %}
</div>
<div id="dialog-message"></div>
{% block common_js %}
@ -77,6 +83,7 @@
<script src="{{ STATIC_URL }}js/commons.js"></script>
<script src="{{ STATIC_URL }}js/dialogs.js"></script>
<script src="{{ STATIC_URL }}js/callback.js"></script>
{% include 'autocomplete_light/static.html' %}
{% endblock %}

@ -0,0 +1 @@
<a href="#" onclick="return show_req_avail_form('{% url 'catalog-req-avail-no-id' %}');">Заказать обратный звонок</a>

@ -0,0 +1,16 @@
<form id="req-avail-form" action="" method="post" title="Заказ обратного звонка">
{% csrf_token %}
<div class='grey-box'>
<div style="margin: 0px 0px 20px 0px;">Оставьте свои контакты и мы перезвоним вам, ответим на все ваши вопросы</div>
<p>{{ reqf.name }}</p>
<p>{{ reqf.phone }}</p>
<p>{{ reqf.message }}</p>
<p>{{ reqf.captcha }}</p>
<div class='c'></div>
<div class="errors-layout"></div>
<div class='c'></div>
<div class="buttons">
<button type="submit" role="submit" class='green-btn2' name="submit">Перезвоните мне!</button>
</div>
</div>
</form>

@ -0,0 +1,4 @@
{% load url from future %}
Сообщение обработано
Ссылка на сообщение: http://dokumentor.ru{% url 'admin:callback_reqavail_change' req.pk %}

@ -0,0 +1,14 @@
{% load url from future %}
Заказ товара с сайта
Имя клиента: {{ req.name }}
Телефон/E-mail: {{ req.phone }}
{% if req.good %}
Название: {{ req.good }}
{% else %}
По общим вопросам
{{ req.message }}
{% endif %}
Ссылка на эту заявку: http://dokumentor.ru{% url "admin:callback_reqavail_change" req.pk %}

@ -15,7 +15,6 @@
<div style="float:left; margin-left: 40px; border-left: 1px solid; padding-left: 20px;">
<h2>Документы</h2>
<br />
{% include "docs/docs.html" %}
</div>
{% endblock %}

@ -1,8 +1,25 @@
{% url 'docs_aktrabot_add_by_invoice' invoice_id=obj.pk as url_aktrabot_by_invoice %}
{% url 'docs_nakladn_add_by_invoice' invoice_id=obj.pk as url_nakladn_by_invoice %}
{% url 'docs_faktura_add_by_invoice' invoice_id=obj.pk as url_faktura_by_invoice %}
<a href="{{ url_aktrabot_by_invoice }}" title="Акт по счёту">Акт по счёту</a><br />
<a href="{{ url_aktrabot_by_invoice }}" title="Акт по счёту"><b>Акт по счёту</b></a><br />
{% if obj.docs_for_invoice.AktRabot %}
{% for akt in obj.docs_for_invoice.AktRabot %}
<a href="{% url 'docs_aktrabot_img' akt.id %}">{{ akt }}</a>
{% endfor %}
{% endif %}
<br />
<a href="{{ url_nakladn_by_invoice }}" title="Накладную">Накладную</a><br />
<br />
<a href="{{ url_faktura_by_invoice }}" title="Счёт-фактуру">Счёт-фактуру</a> <br />
<a href="{{ url_nakladn_by_invoice }}" title="Накладную"><b>Накладную</b></a><br />
{% if obj.docs_for_invoice.Nakladn %}
{% for nakladn in obj.docs_for_invoice.Nakladn %}
<a href="{% url 'docs_nakladn_img' nakladn.id %}">{{ nakladn }}</a>
{% endfor %}
{% endif %}
<br />
<br />
<a href="{{ url_faktura_by_invoice }}" title="Счёт-фактуру"><b>Счёт-фактуру</b></a> <br />
{% if obj.docs_for_invoice.Faktura %}
{% for faktura in obj.docs_for_invoice.Faktura %}
<a href="{% url 'docs_faktura_img' faktura.id %}">{{ faktura }}</a>
{% endfor %}
{% endif %}

@ -25,6 +25,7 @@ urlpatterns = patterns('',
url(r'^my/', include('project.customer.urls')),
url(r'^my/docs/', include('project.docs.urls')),
url(r'^my/callback/', include('project.callback.urls')),
url(r'^user/', include('project.myauth.urls')),
url(r'^', include('cms.urls')),

Loading…
Cancel
Save