diff --git a/requirements/local.txt b/requirements/local.txt index 89d51be..5aebb6b 100644 --- a/requirements/local.txt +++ b/requirements/local.txt @@ -2,3 +2,6 @@ ipython==2.1.0 django-debug-toolbar==1.4 django-eml-email-backend==0.1 +ipdb==0.10.3 +ptpython==0.39 +ipython==2.1.0 diff --git a/src/commons/pdf_tools.py b/src/commons/pdf_tools.py index c549e2a..8370e87 100644 --- a/src/commons/pdf_tools.py +++ b/src/commons/pdf_tools.py @@ -8,13 +8,11 @@ from django.template import RequestContext from django.http import HttpResponse -def pdf_to_response(content, filename=None, filename_encode='windows-1251'): +def pdf_to_response(content, filename=None): """Выводит content в django.http.HttpResponse, который и возвращает.""" response = HttpResponse(content, content_type='application/pdf') if filename: - if filename_encode: - filename = filename.encode(filename_encode) - response['Content-Disposition'] = ('attachment; filename="%s"' % filename.replace('"', "''")) + response['Content-Disposition'] = ('attachment; filename="{}"'.format(filename)) return response @@ -22,7 +20,6 @@ def render_pdf_to_string(request, template_name, dictionary=None): """Рендерит html шаблон в pdf. Возвращает строку, в которой содержится сгенерированный pdf.""" context_instance = RequestContext(request) html = render_to_string(template_name, dictionary, context_instance) - #return HttpResponse(html) # для отладки result = BytesIO() pdf = pisa.pisaDocument(BytesIO(html.encode('utf-8')), result, encoding='utf-8') pdf_content = result.getvalue() diff --git a/src/customer/models.py b/src/customer/models.py index 6824ddf..5783b34 100644 --- a/src/customer/models.py +++ b/src/customer/models.py @@ -46,20 +46,6 @@ class UploadAndRename(object): return os.path.join(self.path, profile_dir, filename) -# def upload_to(path, new_filename=None): -# """Куда и под каким именем сохранить загруженный файл.""" -# -# def get_upload_path(instance, filename): -# filename = new_filename or filename -# try: -# profile_dir = instance.get_first_user().username -# except: -# profile_dir = 'NoUser' -# return os.path.join(path, profile_dir, filename) -# -# return get_upload_path - - class UserProfile(models.Model): """Профиль пользователя.""" profile_type = models.PositiveSmallIntegerField(u'Тип профиля', choices=consts.PROFILE_TYPES) @@ -116,13 +102,13 @@ class UserProfile(models.Model): # подписи, печать и логотип boss_sign = models.ImageField(u'Подпись руководителя', blank=True, default='', - upload_to=UploadAndRename(PROFILE_IMAGES_UPLOAD_DIR, 'boss_sign.bmp')) + upload_to=UploadAndRename(PROFILE_IMAGES_UPLOAD_DIR, 'boss_sign.png')) glavbuh_sign = models.ImageField(u'Подпись бухгалтера', blank=True, default='', - upload_to=UploadAndRename(PROFILE_IMAGES_UPLOAD_DIR, 'glavbuh_sign.bmp')) + upload_to=UploadAndRename(PROFILE_IMAGES_UPLOAD_DIR, 'glavbuh_sign.png')) stamp = models.ImageField(u'Печать', blank=True, default='', - upload_to=UploadAndRename(PROFILE_IMAGES_UPLOAD_DIR, 'stamp.bmp')) + upload_to=UploadAndRename(PROFILE_IMAGES_UPLOAD_DIR, 'stamp.png')) logo = models.ImageField(u'Логотип', blank=True, default='', - upload_to=UploadAndRename(PROFILE_IMAGES_UPLOAD_DIR, 'logo.bmp')) + upload_to=UploadAndRename(PROFILE_IMAGES_UPLOAD_DIR, 'logo.png')) created_at = models.DateTimeField(u'Создан', auto_now_add=True) updated_at = models.DateTimeField(u'Изменен', auto_now=True) @@ -130,7 +116,7 @@ class UserProfile(models.Model): confirmed = models.BooleanField(u'Подтверждён', default=False) user_session_key = models.CharField(u'Ключ сессии (служебная информация)', max_length=256, blank=True, default='', - help_text=u'Руками не тро...') + help_text=u'Руками не трогать...') objects = managers.UserProfileManager() @@ -151,13 +137,14 @@ class UserProfile(models.Model): self.kpp = only_numerics(self.kpp) def process_img(orig_img, size): + # TODO http://stackoverflow.com/questions/9166400/convert-rgba-png-to-rgb-with-pil w = orig_img.width h = orig_img.height if w > size[0] or h > size[1]: filename = str(orig_img.path) - img = Image.open(filename).convert("RGB") + img = Image.open(filename) img.thumbnail(size, Image.ANTIALIAS) - img.save(filename, 'BMP') + img.save(filename, 'PNG') super(UserProfile, self).save(*args, **kwargs) diff --git a/src/customer/urls.py b/src/customer/urls.py index 7baf3a9..30b4921 100644 --- a/src/customer/urls.py +++ b/src/customer/urls.py @@ -6,13 +6,12 @@ from customer.views import profile, profile_ajax, license, documents from customer.views import bank_accounts, bank_accounts_ajax from customer.views import clients, clients_ajax - urlpatterns = patterns('', # личный кабинет - url(r'^$', views.customer_index, name='customer_index'), + url(r'^$', views.customer_index, name='customer_index'), # --- профиль - url(r'^profile/$', profile.profile_view, name='customer_profile_view'), + url(r'^profile/$', profile.profile_view, name='customer_profile_view'), url(r'^profile/edit/$', profile.profile_edit, name='customer_profile_edit'), url(r'^profile/email/$', profile.profile_email, name='customer_profile_email'), url(r'^license/$', license.order_license, name='customer_order_license'), @@ -26,38 +25,48 @@ urlpatterns = patterns('', url(r'^paid_list/$', license.paid_list, name='customer_paid_list'), # --- профиль AJAX - url(r'^profile/filters/edit/ajax/$', profile_ajax.profile_filters_edit_ajax, name='customer_profile_filters_edit_ajax'), - url(r'^profile/email/ajax/$', profile_ajax.profile_email_ajax, name='customer_profile_email_ajax'), + url(r'^profile/filters/edit/ajax/$', profile_ajax.profile_filters_edit_ajax, + name='customer_profile_filters_edit_ajax'), + url(r'^profile/email/ajax/$', profile_ajax.profile_email_ajax, + name='customer_profile_email_ajax'), # --- расчетные счета - url(r'^bank-accounts/$', bank_accounts.bank_accounts_list, name='customer_bank_accounts_list'), - url(r'^bank-accounts/page/(?P[0-9]+)/$', bank_accounts.bank_accounts_list, name='customer_bank_accounts_list'), + url(r'^bank-accounts/$', bank_accounts.bank_accounts_list, name='customer_bank_accounts_list'), + url(r'^bank-accounts/page/(?P[0-9]+)/$', bank_accounts.bank_accounts_list, + name='customer_bank_accounts_list'), url(r'^bank-accounts/add/$', bank_accounts.bank_accounts_add, name='customer_bank_accounts_add'), - url(r'^bank-accounts/(?P\d+)/edit/$', bank_accounts.bank_accounts_edit, name='customer_bank_accounts_edit'), - url(r'^bank-accounts/(?P\d+)/delete/$', bank_accounts.bank_accounts_delete, name='customer_bank_accounts_delete'), + url(r'^bank-accounts/(?P\d+)/edit/$', bank_accounts.bank_accounts_edit, + name='customer_bank_accounts_edit'), + url(r'^bank-accounts/(?P\d+)/delete/$', bank_accounts.bank_accounts_delete, + name='customer_bank_accounts_delete'), # --- расчетные счета AJAX - url(r'^bank-accounts/ajax/$', bank_accounts_ajax.bank_accounts_list_ajax, name='customer_bank_accounts_list_ajax'), + url(r'^bank-accounts/ajax/$', bank_accounts_ajax.bank_accounts_list_ajax, + name='customer_bank_accounts_list_ajax'), url(r'^bank-accounts/(?P\d+)/get/ajax/$', bank_accounts_ajax.bank_accounts_get_ajax, - name='customer_bank_accounts_get_ajax'), - url(r'^bank-accounts/add/ajax/$', bank_accounts_ajax.bank_accounts_add_ajax, name='customer_bank_accounts_add_ajax'), + name='customer_bank_accounts_get_ajax'), + url(r'^bank-accounts/add/ajax/$', bank_accounts_ajax.bank_accounts_add_ajax, + name='customer_bank_accounts_add_ajax'), url(r'^bank-accounts/(?P\d+)/edit/ajax/$', bank_accounts_ajax.bank_accounts_edit_ajax, - name='customer_bank_accounts_edit_ajax'), + name='customer_bank_accounts_edit_ajax'), url(r'^bank-accounts/(?P\d+)/delete/ajax/$', bank_accounts_ajax.bank_accounts_delete_ajax, - name='customer_bank_accounts_delete_ajax'), + name='customer_bank_accounts_delete_ajax'), # --- контрагенты - url(r'^clients/$', clients.clients_list, name='customer_clients_list'), + url(r'^clients/$', clients.clients_list, name='customer_clients_list'), url(r'^clients/page/(?P[0-9]+)/$', clients.clients_list, name='customer_clients_list'), url(r'^clients/add/$', clients.clients_add, name='customer_clients_add'), url(r'^clients/(?P\d+)/edit/$', clients.clients_edit, name='customer_clients_edit'), url(r'^clients/(?P\d+)/delete/$', clients.clients_delete, name='customer_clients_delete'), # --- контрагенты AJAX - url(r'^clients/(?P\d+)/get/ajax/$', clients_ajax.clients_get_ajax, name='customer_clients_get_ajax'), + url(r'^clients/(?P\d+)/get/ajax/$', clients_ajax.clients_get_ajax, + name='customer_clients_get_ajax'), url(r'^clients/add/ajax/$', clients_ajax.clients_add_ajax, name='customer_clients_add_ajax'), - url(r'^clients/(?P\d+)/edit/ajax/$', clients_ajax.clients_edit_ajax, name='customer_clients_edit_ajax'), - url(r'^clients/(?P\d+)/delete/ajax/$', clients_ajax.clients_delete_ajax, name='customer_clients_delete_ajax'), + url(r'^clients/(?P\d+)/edit/ajax/$', clients_ajax.clients_edit_ajax, + name='customer_clients_edit_ajax'), + url(r'^clients/(?P\d+)/delete/ajax/$', clients_ajax.clients_delete_ajax, + name='customer_clients_delete_ajax'), url(r'^tmp_upload/ajax/$', profile.tmp_upload, name='upload_tmp_file'), ) diff --git a/src/customer/views/profile.py b/src/customer/views/profile.py index f8c466d..2ca221f 100644 --- a/src/customer/views/profile.py +++ b/src/customer/views/profile.py @@ -23,7 +23,6 @@ from customer import models, forms from customer.decorators import license_required from customer.utils import raise_if_no_profile - PDF_PROFILE_NAME = u'Реквизиты.pdf' SUPPORT_EMAIL = getattr(settings, 'SUPPORT_EMAIL', '') @@ -51,12 +50,12 @@ def profile_view(request): filters = filters_form.save() if 'download-pdf' in request.POST: - #return _profile_get_pdf(request, profile, filters.bank_account, filters) # для отладки + # return _profile_get_pdf(request, profile, filters.bank_account, filters) # для отладки return profile_as_pdf(request, profile, filters.bank_account, filters) elif 'email-pdf' in request.POST: return redirect('customer_profile_email') - return redirect('customer_profile_view') # редирект на себя, чтобы не сабмитили форму по F5 + return redirect('customer_profile_view') # редирект на себя, чтобы не сабмитили форму по F5 else: filters_form = filters_form_class(instance=filters, label_suffix='', profile=profile, accounts=accounts) @@ -91,17 +90,22 @@ def profile_edit(request): if request.method == 'POST': form = form_class(data=request.POST, files=request.FILES, instance=profile) + if form.is_valid(): item = form.save(commit=False) + for img_url in ('tmb_logo', 'tmb_boss_sign', 'tmb_glavbuh_sign', 'tmb_stamp'): if form.cleaned_data[img_url]: + # TODO ? chg_file = open(settings.MEDIA_ROOT + '/cache/imgs/' + \ - form.cleaned_data[img_url]) + form.cleaned_data[img_url], mode='rb+') item_attr = img_url[4:] + getattr(item, item_attr).save('%s.%s' % \ (item_attr, form.cleaned_data[img_url].split('.')[-1]), File(chg_file)) chg_file.close() + # elif form.cleaned_data: pass item.save() @@ -120,21 +124,22 @@ def profile_edit(request): def tmp_upload(request): - SIZES = {'id_boss_sign': (170, 65), 'id_glavbuh_sign': (170, 65), 'id_stamp': (170, 170), 'id_logo': (170, 170)} + key = '' + SIZES = {'id_boss_sign': (170, 65), + 'id_glavbuh_sign': (170, 65), + 'id_stamp': (170, 170), + 'id_logo': (170, 170)} elm_id = request.REQUEST['elm_id'] - file_ = request.FILES.values()[0] + for k in request.FILES.keys(): + key = k + file_ = request.FILES.get(key) if not file_.content_type.startswith('image'): return {'res': 'bad'} - - if not os.path.exists(settings.MEDIA_ROOT + - '/cache/imgs/'): - os.makedirs(settings.MEDIA_ROOT + - '/cache/imgs/') - - tmp_dir = tempfile.mkdtemp('img_tmp', settings.MEDIA_ROOT + - '/cache/imgs/') + if not os.path.exists(settings.MEDIA_ROOT + '/cache/imgs/'): + os.makedirs(settings.MEDIA_ROOT + '/cache/imgs/') + tmp_dir = tempfile.mkdtemp('img_tmp', settings.MEDIA_ROOT + '/cache/imgs/') os.chmod(tmp_dir, 755) - open(tmp_dir + '/' + file_.name, "w").write(file_.read()) + open(tmp_dir + '/' + file_.name, "wb+").write(file_.read()) tmp_url_partial = os.path.basename(tmp_dir) + '/' + file_.name thumbnailer = get_thumbnailer(tmp_dir + '/' + file_.name) # im = get_thumbnail(tmp_dir + '/' + file_.name, SIZES[elm_id], quality=75) @@ -146,6 +151,7 @@ def tmp_upload(request): return HttpResponse(json.dumps(data), content_type='application/json') +# TODO ? def del_tmp_photo(request, article_pk): # wedding, wedding_guests = get_wedding_n_guests(request) try: @@ -156,6 +162,7 @@ def del_tmp_photo(request, article_pk): return {'res': 'bad'} return {'res': 'ok'} +# @login_required @@ -186,7 +193,7 @@ def _send_profile_email(subject, to, body, pdf_content): subject=subject, to=(to,), body=email_body, - attachments = [(smart_str(Header(PDF_PROFILE_NAME, 'cp1251')), pdf_content, 'application/pdf'),] + attachments=[(smart_str(Header(PDF_PROFILE_NAME, 'cp1251')), pdf_content, 'application/pdf'), ] ) return email.send() @@ -214,21 +221,20 @@ def profile_email(request): form = form_class(data=request.POST) if form.is_valid(): _send_profile_email( - subject = u'Реквизиты %s' % profile.get_company_name(), - to = form.cleaned_data['to'], - body = form.cleaned_data['body'], - pdf_content = _profile_get_pdf(request, profile, filters.bank_account, filters) + subject=u'Реквизиты %s' % profile.get_company_name(), + to=form.cleaned_data['to'], + body=form.cleaned_data['body'], + pdf_content=_profile_get_pdf(request, profile, filters.bank_account, filters) ) return redirect(success_url) else: form = form_class() - return render(request, template_name, {'form': form, 'profile': profile,}) - + return render(request, template_name, {'form': form, 'profile': profile, }) -#@login_required -#@csrf_protect -#def profile_settings(request): +# @login_required +# @csrf_protect +# def profile_settings(request): # """Редактировать настройки пользователя.""" # template_name='customer/profile/settings.html' # diff --git a/src/docs/views/base_views.py b/src/docs/views/base_views.py index 48fe1ea..dd1da86 100644 --- a/src/docs/views/base_views.py +++ b/src/docs/views/base_views.py @@ -404,7 +404,10 @@ class BaseViews(object): os.makedirs(tmp_media_dir) tmp_dir = tempfile.mkdtemp(dir=tmp_media_dir) - os.chmod(tmp_dir, 755) + + if not settings.DEBUG: + os.chmod(tmp_dir, 755) + tmp_dirname = os.path.split(tmp_dir)[1] f = open(filename, 'wb') @@ -419,7 +422,6 @@ class BaseViews(object): "-sOutputFile=%s" % os.path.join(tmp_dir, "page-%03d.png"), "-f", filename ] - # ghostscript.Ghostscript(*args) # TODO: check on ubuntu try: p = s.Popen(args=args, stdout=s.PIPE, stderr=s.PIPE) p.wait() diff --git a/src/dokumentor/static/js/commons.js b/src/dokumentor/static/js/commons.js index 9a19b96..c847c54 100644 --- a/src/dokumentor/static/js/commons.js +++ b/src/dokumentor/static/js/commons.js @@ -1,6 +1,6 @@ $(document).ready(function() { var show_cabinet = false; - $('.has-datepicker').datepicker({dateFormat: 'dd.mm.yy', showOn:"button", buttonImageOnly:true, buttonImage:"/s/img/icon-calendar.png"}); + $('.has-datepicker').datepicker({dateFormat: 'dd.mm.yy', showOn:"button", buttonImageOnly:true, buttonImage:"/static/img/icon-calendar.png"}); $('#reasons').mouseout(function(e){ $('.extended-block').removeClass('active'); $('.extended-block-more').hide(); @@ -39,13 +39,13 @@ $(document).ready(function() { $('#other_docs').mouseout(function(e){ $('.other_docs_menu').hide(); }); - $('.close-message').click(function(e){ + $('.close-message').click(function(e){ e.preventDefault(); $(this).closest('li').hide(); var close_action = $(this).data('close'); $.cookie(close_action, true, {path: '/'}); }); - // $('.return_to_index').click(function(e){ + // $('.return_to_index').click(function(e){ // e.preventDefault(); // window.location = '/'; // }); @@ -68,12 +68,12 @@ $(document).ready(function() { } }, 1000) } - $('#cabinet-show').click(function(e){ + $('#cabinet-show').click(function(e){ e.preventDefault(); $('#cabinet-popup').show(); show_overlay(); }); - $('#cabinet-show').mouseover(function(e){ + $('#cabinet-show').mouseover(function(e){ $(this).data('hover',1); $('#cabinet-popup').show(); show_overlay(); @@ -81,12 +81,12 @@ $(document).ready(function() { $('#cabinet-popup').mouseover(function(e){ $(this).data('hover',1); $('#cabinet-popup').show(); - }); + }); $('#cabinet-popup').mouseout(function(e){ $(this).data('hover',0); hide_popup(); - }); - $('#cabinet-show').mouseout(function(e){ + }); + $('#cabinet-show').mouseout(function(e){ $(this).data('hover',0); hide_popup(); }); diff --git a/src/dokumentor/templates/customer/profile/edit.html b/src/dokumentor/templates/customer/profile/edit.html index a081fdb..2d2c407 100644 --- a/src/dokumentor/templates/customer/profile/edit.html +++ b/src/dokumentor/templates/customer/profile/edit.html @@ -1,4 +1,5 @@ {% extends "base.html" %} +{% load static %} {% block title %}Редактирование реквизитов{% endblock %} @@ -25,9 +26,9 @@ Поля, отмеченные * используются для создания ваших документов, поэтому их нужно заполнить обязательно. Все остальные поля не обязательны к заполнению. Они требуются только для "Карточки компании", которую вы можете отправлять своим партнерам прямо из Документора.

- + - + {% if form.non_field_errors %}

{{ form.non_field_errors }}

@@ -230,14 +231,14 @@ {% endif %} - + {{ account.account }} в {{ account.name }} - [X] + [X] @@ -259,7 +260,7 @@ - [X] + [X] @@ -376,9 +377,9 @@ {% if form.boss_sign.value %} {# если уже есть картинка, показать ее #} {% else %} - + {% endif %} - +

Подпись руководителя

@@ -390,10 +391,10 @@ {% if form.glavbuh_sign.value %} {# если уже есть картинка, показать ее #} {% else %} - + {% endif %} - - + +

Подпись бухгалтера

@@ -414,7 +415,7 @@ {% if form.stamp.value %} {# если уже есть картинка, показать ее #} {% else %} - + {% endif %} @@ -422,7 +423,7 @@ @@ -442,7 +443,7 @@
- +
@@ -486,7 +487,7 @@ 'edit_id_prefix': "account_edit_link_", 'delete_id_prefix': "account_delete_link_", 'bank_id_prefix': "account_bank_name_" - } + }; $(function(){ $('.img_load img').on('click', function(e) { var this_id = $(this).closest('.img_load').attr('id'); @@ -494,14 +495,14 @@ $('#' + tmb_id).val(''); $('#id_' + this_id).click(); - }) + }); $('.img_load .del_image').on('click', function(e) { e.preventDefault(); var this_id = $(this).closest('.img_load').attr('id'); var tmb_id = 'id_tmb_' + this_id.substring(3); var dlg_msg = $('#dialog-message'); dlg_msg.dialog({ - title: 'Удалить изображение?', + title: 'Удалить изображение?', buttons:{'Да': function(){ $('#' + tmb_id).val(''); $('#' + this_id + ' img').attr('src', '{{ STATIC_URL }}/img/upload-' + this_id + '.png'); @@ -520,7 +521,7 @@ var getPic = function(data){ var elm_id = '#' + data['elm_id'].substring(3); var tmb_id = '#id_tmb_' + data['elm_id'].substring(3); - $(elm_id + ' img').attr('src', data['pic']) + $(elm_id + ' img').attr('src', data['pic']); $(tmb_id).val(data['full_pic']); $(elm_id + ' .del_image').show(); }; @@ -547,8 +548,8 @@ }) - - + + - - + + {% include 'hbs/bank-tpl.html' %} -{% endblock js %} \ No newline at end of file +{% endblock js %}