autocomplete plaseholder

feature/docker
Dmitriy Shesterkin 9 years ago
parent 6a3221d0cf
commit 0cbdece483
  1. 486
      src/customer/!!!del__forms.py
  2. 1
      src/customer/consts.py
  3. 2
      src/customer/context_processors.py
  4. 4
      src/customer/views/bank_accounts.py
  5. 8
      src/customer/views/profile_ajax.py
  6. 51
      src/docs/autocomplete_light_registry.py
  7. 4
      src/docs/forms/base_forms.py
  8. 2
      src/docs/forms/invoice.py
  9. 3
      src/docs/models/base_models.py
  10. 12
      src/dokumentor/static/js/lib/jquery.formset.js
  11. 133
      src/dokumentor/templates/docs/!!del__stub_js.html
  12. 14
      src/dokumentor/templates/docs/_base/base_list.html
  13. 8
      src/dokumentor/templates/docs/parts/form_tbl_items.html

@ -1,486 +0,0 @@
# -*- coding: utf-8 -*-
from django import forms
from django.utils.encoding import force_unicode
from django.utils.safestring import mark_safe
from django.conf import settings
from yandex_money.forms import PaymentForm
from commons.forms import MyBaseModelForm, set_field_error
from . import consts, models
FILE_UPLOAD_MAX_MEMORY_SIZE = getattr(settings, 'FILE_UPLOAD_MAX_MEMORY_SIZE ', 2621440) # default 2.5Mb
def get_profile_form_class(profile_type):
"""Возвращает класс формы редактирования профиля пользователя."""
if profile_type == consts.IP_PROFILE:
return IpUserProfileForm
elif profile_type == consts.ORG_PROFILE:
return OrgUserProfileForm
return None
def get_profile_filters_form_class(profile_type):
"""Возвращает класс формы фильтрации профиля пользователя."""
if profile_type == consts.IP_PROFILE:
return IpUserProfileFiltersForm
elif profile_type == consts.ORG_PROFILE:
return OrgUserProfileFiltersForm
return None
###
def _numeric(field):
real_maxlength = field.widget.attrs['maxlength']
return {
'maxlength': int(real_maxlength)*3, # set fake maxlength. otherwise browser would cut pasted values too early
'data-type': 'number', # used by jquery selector
'data-maxlength': real_maxlength, # save real maxlength
}
# -----------------------------------------------------------------------------
class UserProfileForm(MyBaseModelForm):
"""Общая форма редактирования профиля пользователя.
Специализированные формы для редактирования профилей ИП и Организаций -
ищи ниже в классах IpUserProfileForm и OrgUserProfileForm соответственно.
Форму для админки ищи ниже в классе UserProfileAdminForm.
"""
tmb_logo = forms.CharField(required=False, widget=forms.HiddenInput)
tmb_boss_sign = forms.CharField(required=False, widget=forms.HiddenInput)
tmb_glavbuh_sign = forms.CharField(required=False, widget=forms.HiddenInput)
tmb_stamp = forms.CharField(required=False, widget=forms.HiddenInput)
class Meta:
model = models.UserProfile
def __init__(self, *args, **kwargs):
super(UserProfileForm, self).__init__(*args, **kwargs)
if 'ip_reg_date' in self.fields:
self.fields['ip_reg_date'].widget.attrs['class'] = 'has-datepicker'
#
self.fields['inn'].widget.attrs.update(_numeric(self.fields['inn']))
self.fields['ogrn'].widget.attrs.update(_numeric(self.fields['ogrn']))
self.fields['okpo'].widget.attrs.update(_numeric(self.fields['okpo']))
if 'kpp' in self.fields:
self.fields['kpp'].widget.attrs.update(_numeric(self.fields['kpp']))
def _check_file_size(self, image):
"""Ограничить максимальный размер загружаемого файла."""
if image and image.size > FILE_UPLOAD_MAX_MEMORY_SIZE:
raise forms.ValidationError(
u'Размер изображения превышает %i Мб' % (FILE_UPLOAD_MAX_MEMORY_SIZE / (1024*1024)))
return image
def clean_boss_sign(self):
image = self.cleaned_data.get('boss_sign')
return self._check_file_size(image)
def clean_glavbuh_sign(self):
image = self.cleaned_data.get('glavbuh_sign')
return self._check_file_size(image)
def clean_stamp(self):
image = self.cleaned_data.get('stamp')
return self._check_file_size(image)
def clean_logo(self):
image = self.cleaned_data.get('logo')
return self._check_file_size(image)
class IpUserProfileForm(UserProfileForm):
"""Форма редактирования профиля - ИП."""
change_labels = {'ogrn': u'ОГРНИП'}
class Meta(UserProfileForm.Meta):
fields = (
# фио ип
'boss_surname', 'boss_name', 'boss_midname',
# инн, огрнип, окпо
'inn', 'ogrn', 'okpo',
# свид-во гос. регистрации и дата
'svid_gos_reg', 'ip_reg_date',
# фио главбуха
'glavbuh_surname', 'glavbuh_name', 'glavbuh_midname',
# контактная информация - адреса, телефон, факс, почта, сайт
'address', 'jur_address', 'real_address', 'phone_code', 'phone', 'fax_code', 'fax', 'email', 'site',
# подписи, печать и логотип
'boss_sign', 'glavbuh_sign', 'stamp', 'logo',
'tmb_logo', 'tmb_boss_sign', 'tmb_glavbuh_sign', 'tmb_stamp',
)
class OrgUserProfileForm(UserProfileForm):
"""Форма редактирования профиля - Организация."""
unset_required = {'ogrn': u'ОГРН'}
change_labels = {'ogrn': u'ОГРН'}
class Meta(UserProfileForm.Meta):
fields = (
# краткое и полное названия организации
'name', 'full_name',
# инн, кпп, огрн, окпо
'inn', 'kpp', 'ogrn', 'okpo',
# должность руководителя, его фио и на каком основании он действует
'boss_title', 'boss_surname', 'boss_name', 'boss_midname', 'na_osnovanii',
# фио главбуха
'glavbuh_surname', 'glavbuh_name', 'glavbuh_midname',
# контактная информация - адреса, телефон, факс, почта, сайт
'address', 'jur_address', 'real_address', 'phone_code', 'phone', 'fax_code', 'fax', 'email', 'site',
# подписи, печать и логотип
'boss_sign', 'glavbuh_sign', 'stamp', 'logo',
'tmb_logo', 'tmb_boss_sign', 'tmb_glavbuh_sign', 'tmb_stamp',
)
class UserProfileAdminForm(UserProfileForm):
"""Форма редактирования профиля - для админки."""
# условно-обязательные поля, проверять отдельно - могут быть обязательны в зависимости от типа профиля
unset_required = [
# для ИП
'kpp', 'name'
# для Организаций
]
def clean(self):
super(UserProfileAdminForm, self).clean()
cleaned_data = self.cleaned_data
# тип профиля - ИП или Организация
profile_type = cleaned_data.get('profile_type')
if profile_type == consts.IP_PROFILE: # поля, обязательные для ИП
pass
elif profile_type == consts.ORG_PROFILE: # поля, обязательные для Организаций
org_boss_name = cleaned_data.get('org_boss_name')
kpp = cleaned_data.get('kpp')
if not org_boss_name: set_field_error(self, 'org_boss_name')
if not kpp: set_field_error(self, 'kpp')
return cleaned_data
# -----------------------------------------------------------------------------
class BankAccountForm(forms.ModelForm):
"""Форма редактирования расчетных счетов."""
# search_bank = forms.CharField(label=u'Поиск банка', required=False, initial='')
class Meta:
model = models.BankAccount
# fields = ('search_bank', 'bik', 'name', 'short_name', 'korr_account', 'account', 'is_main', 'company')
fields = ('bik', 'name', 'short_name', 'korr_account', 'account', 'is_main', 'company')
_textarea = forms.Textarea(attrs={'cols': 80, 'rows': 3})
widgets = {
'bik': forms.HiddenInput(),
'name': forms.HiddenInput(),
'short_name': forms.HiddenInput(),
'korr_account': forms.HiddenInput(),
'company': forms.HiddenInput(),
}
def __init__(self, *args, **kwargs):
super(BankAccountForm, self).__init__(*args, **kwargs)
# self.fields['bik'].widget.attrs.update(_numeric(self.fields['bik']))
# self.fields['korr_account'].widget.attrs.update(_numeric(self.fields['korr_account']))
self.fields['account'].widget.attrs.update(_numeric(self.fields['account']))
# self.fields['search_bank'].widget.attrs['class'] = 'search-bank'
class BankAccountAdminForm(BankAccountForm):
"""Форма редактирования расчетных счетов - для админки."""
class Meta(BankAccountForm.Meta):
fields = None
exclude = ('address',)
class BankAccountListForm(forms.Form):
"""Форма со списком всех расчетных счетов пользователя."""
bank_account = forms.ModelChoiceField(queryset=models.BankAccount.objects.get_all(None),
empty_label=u'все контрагенты', required=False)
def __init__(self, user, *args, **kwargs):
super(BankAccountListForm, self).__init__(*args, **kwargs)
self.fields['bank_account'].queryset = models.BankAccount.objects.get_all(user.profile)
# -----------------------------------------------------------------------------
class ClientForm(forms.ModelForm):
"""Форма редактирования контрагентов."""
class Meta:
model = models.Client
fields = ('name', 'inn', 'kpp', 'ogrn', 'okpo', 'address',
# банковские реквизиты
'bank_bik', 'bank_name', 'bank_korr_account', 'bank_account',
# контакты
'contact_name', 'contact_email', 'contact_phone', 'contact_skype', 'contact_other',
)
_textarea = forms.Textarea(attrs={'cols': 80, 'rows': 3})
widgets = {
'bank_bik': forms.HiddenInput(),
'bank_name': forms.HiddenInput(),
'short_name': forms.HiddenInput(),
'bank_korr_account': forms.HiddenInput(),
}
def __init__(self, *args, **kwargs):
super(ClientForm, self).__init__(*args, **kwargs)
self.fields['inn'].widget.attrs.update(_numeric(self.fields['inn']))
self.fields['kpp'].widget.attrs.update(_numeric(self.fields['kpp']))
self.fields['ogrn'].widget.attrs.update(_numeric(self.fields['ogrn']))
self.fields['okpo'].widget.attrs.update(_numeric(self.fields['okpo']))
# self.fields['bank_bik'].widget.attrs.update(_numeric(self.fields['bank_bik']))
# self.fields['bank_korr_account'].widget.attrs.update(_numeric(self.fields['bank_korr_account']))
# self.fields['bank_account'].widget.attrs.update(_numeric(self.fields['bank_account']))
class ClientAdminForm(ClientForm):
"""Форма редактирования контрагентов - для админки."""
class Meta(ClientForm.Meta):
fields = None
exclude = ('bank_address',)
class ClientsListForm(forms.Form):
"""Форма со списком всех контрагентов пользователя."""
client = forms.ModelChoiceField(queryset=models.Client.objects.get_all(None), empty_label=u'все контрагенты',
required=False)
def __init__(self, user, *args, **kwargs):
super(ClientsListForm, self).__init__(*args, **kwargs)
self.fields['client'].queryset = models.Client.objects.get_all(user.profile)
# -----------------------------------------------------------------------------
class UserProfileFiltersForm(MyBaseModelForm):
"""Общая форма фильтрации реквизитов."""
_profile_type = None # задать в наследнике!
_is_admin = False
_user = None
class Meta:
model = models.UserProfileFilters
widgets = {
'bank_account': forms.RadioSelect(),
}
def __init__(self, profile=None, accounts=None, *args, **kwargs):
instance = kwargs.get('instance')
initial = kwargs.get('initial')
new_initial = {
# всегда включены
'show_ip_boss_fio': True,
'show_name': True,
}
# TODO 1. переписать проверки в стиле new_initial['show_inn'] = bool(profile.inn)
# TODO 2. загнать условия в словарь вида {'show_inn': 'inn'}. потом в цикле обработать
if profile:
# сбросить чекбоксы, если не заполнены определенные поля в профиле или нет расчетных счетов
if instance:
new_initial['show_inn'] = bool(profile.inn)
new_initial['show_ogrn'] = bool(profile.ogrn)
new_initial['show_okpo'] = bool(profile.okpo)
new_initial['show_glavbuh'] = bool(profile.get_glavbuh_fio())
new_initial['show_address'] = bool(profile.address)
new_initial['show_jur_address'] = bool(profile.jur_address)
new_initial['show_real_address'] = bool(profile.real_address)
new_initial['show_phone'] = bool(profile.get_full_phone())
new_initial['show_fax'] = bool(profile.get_full_fax())
new_initial['show_email'] = bool(profile.email)
new_initial['show_site'] = bool(profile.site)
new_initial['show_bank_account'] = bool(accounts)
new_initial['show_logo'] = bool(profile.logo)
if self._profile_type == consts.IP_PROFILE:
new_initial['show_svid_gos_reg'] = bool(profile.svid_gos_reg)
new_initial['show_ip_reg_date'] = bool(profile.ip_reg_date)
elif self._profile_type == consts.ORG_PROFILE:
new_initial['show_full_name'] = bool(profile.full_name)
new_initial['show_kpp'] = bool(profile.kpp)
new_initial['show_na_osnovanii'] = bool(profile.na_osnovanii)
else:
new_initial['show_inn'] = bool(profile.inn)
new_initial['show_ogrn'] = bool(profile.ogrn)
new_initial['show_okpo'] = bool(profile.okpo)
new_initial['show_glavbuh'] = bool(profile.get_glavbuh_fio())
new_initial['show_address'] = bool(profile.address)
new_initial['show_jur_address'] = bool(profile.jur_address)
new_initial['show_real_address'] = bool(profile.real_address)
new_initial['show_phone'] = bool(profile.get_full_phone())
new_initial['show_fax'] = bool(profile.get_full_fax())
new_initial['show_email'] = bool(profile.email)
new_initial['show_site'] = bool(profile.site)
new_initial['show_bank_account'] = bool(accounts)
new_initial['show_logo'] = bool(profile.logo)
if self._profile_type == consts.IP_PROFILE:
new_initial['show_svid_gos_reg'] = bool(profile.svid_gos_reg)
new_initial['show_ip_reg_date'] = bool(profile.ip_reg_date)
elif self._profile_type == consts.ORG_PROFILE:
new_initial['show_full_name'] = bool(profile.full_name)
new_initial['show_kpp'] = bool(profile.kpp)
new_initial['show_na_osnovanii'] = bool(profile.na_osnovanii)
if initial:
initial.update(new_initial)
else:
kwargs['initial'] = new_initial
super(UserProfileFiltersForm, self).__init__(*args, **kwargs)
# для админки
if self._is_admin:
# попробовать взять user из kwargs['instance'], а потом из self.data
try:
self._user = getattr(kwargs.get('instance'), 'user')
except AttributeError:
self._user = self.data.get('user')
if not accounts:
accounts = models.BankAccount.objects.get_all(self._user.profile)
f = self.fields
# только расчетные счета пользователя
f_acc = f['bank_account'] # TODO вынести настройку расчетных счетов в mixin?
f_acc.queryset = accounts
f_acc.empty_label = None
f_acc.label_from_instance = lambda obj: mark_safe(
force_unicode('%s<br /><span class="name">%s</span>' % (obj.account, obj.name,))) # исправить метку
# заблокировать чекбоксы, если: не заполнены определенные поля в профиле или нет расчетных счетов
if profile:
if not profile.inn: f['show_inn'].widget.attrs['disabled'] = 'disabled'
if not profile.ogrn: f['show_ogrn'].widget.attrs['disabled'] = 'disabled'
if not profile.okpo: f['show_okpo'].widget.attrs['disabled'] = 'disabled'
if not profile.get_glavbuh_fio(): f['show_glavbuh'].widget.attrs['disabled'] = 'disabled'
if not profile.address: f['show_address'].widget.attrs['disabled'] = 'disabled'
if not profile.jur_address: f['show_jur_address'].widget.attrs['disabled'] = 'disabled'
if not profile.real_address: f['show_real_address'].widget.attrs['disabled'] = 'disabled'
if not profile.get_full_phone(): f['show_phone'].widget.attrs['disabled'] = 'disabled'
if not profile.get_full_fax(): f['show_fax'].widget.attrs['disabled'] = 'disabled'
if not profile.email: f['show_email'].widget.attrs['disabled'] = 'disabled'
if not profile.site: f['show_site'].widget.attrs['disabled'] = 'disabled'
if not profile.logo: f['show_logo'].widget.attrs['disabled'] = 'disabled'
if not accounts: f['show_bank_account'].widget.attrs['disabled'] = 'disabled'
if self._profile_type == consts.IP_PROFILE:
if not profile.svid_gos_reg: f['show_svid_gos_reg'].widget.attrs['disabled'] = 'disabled'
if not profile.ip_reg_date: f['show_ip_reg_date'].widget.attrs['disabled'] = 'disabled'
elif self._profile_type == consts.ORG_PROFILE:
if not profile.name: f['show_name'].widget.attrs['disabled'] = 'disabled'
if not profile.full_name: f['show_full_name'].widget.attrs['disabled'] = 'disabled'
if not profile.kpp: f['show_kpp'].widget.attrs['disabled'] = 'disabled'
if not profile.boss_title: f['show_org_boss_title_and_fio'].widget.attrs['disabled'] = 'disabled'
if not profile.na_osnovanii: f['show_na_osnovanii'].widget.attrs['disabled'] = 'disabled'
# блокировать чекбоксы, т.к.эти реквизиты юзеру выключать нельзя
if self._profile_type == consts.IP_PROFILE:
f['show_ip_boss_fio'].widget.attrs['disabled'] = 'disabled'
elif self._profile_type == consts.ORG_PROFILE:
f['show_name'].widget.attrs['disabled'] = 'disabled'
class IpUserProfileFiltersForm(UserProfileFiltersForm):
"""Форма фильтрации реквизитов - для ИП."""
_profile_type = consts.IP_PROFILE
change_labels = {
'show_profile_type': dict(consts.PROFILE_TYPES)[_profile_type],
'show_ogrn': u'ОГРНИП',
}
class Meta(UserProfileFiltersForm.Meta):
fields = (
'show_profile_type',
'show_ip_boss_fio',
'show_inn',
'show_ogrn',
'show_okpo',
'show_svid_gos_reg',
'show_ip_reg_date',
'show_glavbuh',
'show_bank_account',
'bank_account',
'show_contact_info',
'show_address',
'show_jur_address',
'show_real_address',
'show_phone',
'show_fax',
'show_email',
'show_site',
'show_logo',
)
class OrgUserProfileFiltersForm(UserProfileFiltersForm):
"""Форма фильтрации реквизитов - для Организаций."""
_profile_type = consts.ORG_PROFILE
change_labels = {
'show_profile_type': dict(consts.PROFILE_TYPES)[_profile_type],
'show_ogrn': u'ОГРН',
}
class Meta(UserProfileFiltersForm.Meta):
fields = (
'show_profile_type',
'show_name',
'show_full_name',
'show_inn',
'show_kpp',
'show_ogrn',
'show_okpo',
'show_org_boss_title_and_fio',
'show_na_osnovanii',
'show_glavbuh',
'show_bank_account',
'bank_account',
'show_contact_info',
'show_address',
'show_jur_address',
'show_real_address',
'show_phone',
'show_fax',
'show_email',
'show_site',
'show_logo',
)
# -----------------------------------------------------------------------------
class EmailProfileForm(forms.Form):
"""Форма отправки реквизитов пользователя по email."""
to = forms.EmailField(label=u'E-mail получателя')
body = forms.CharField(label=u'Текст сообщения', max_length=1000, required=False,
widget=forms.Textarea(attrs={'cols': 80, 'rows': 3}))
class LicenseForm(forms.Form):
"""Форма продления лицензии
"""
term = forms.ModelChoiceField(queryset=models.LicensePrice.objects.all(),
widget=forms.RadioSelect, label=u'Срок лицензии', empty_label = None)
payform = forms.ChoiceField(choices=consts.PAYFORMS[1:], widget=forms.RadioSelect,
label=u'Форма оплаты')
class YaForm(PaymentForm):
def get_display_field_names(self):
return ()

@ -21,7 +21,6 @@ PAYFORMS = (
(-1, u'Бесплатно'),
(0, u'Безналичный расчёт'),
(1, u'Банковская карта'),
# (2, u'Квитанция Сбербанка'),
)
TERMS = (

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from datetime import datetime, timedelta
from django.core.cache import cache
from .models import License
from customer.models import License
def license_check_soon_ends(request):

@ -7,7 +7,7 @@ from django.contrib.auth.decorators import login_required
from commons.paginator import pagination, save_per_page_value
from .. import models, forms
from ..decorators import license_required
from ..decorators import license_required
from ..utils import raise_if_no_profile
@ -98,7 +98,7 @@ def bank_accounts_delete(request, id):
"""Удалить расчетный счет."""
raise_if_no_profile(request)
template_name='customer/bank_accounts/delete.html'
template_name = 'customer/bank_accounts/delete.html'
success_url = 'customer_bank_accounts_list'
referer = request.POST.get('referer')

@ -41,8 +41,8 @@ def profile_filters_edit_ajax(request):
data = {
'success': form.is_valid(),
'field_errors': form.errors, # ошибки полей
'form_errors': non_field_errors, # ошибки формы
'field_errors': form.errors, # ошибки полей
'form_errors': non_field_errors, # ошибки формы
}
return HttpResponse(json.dumps(data), content_type='application/json')
@ -78,7 +78,7 @@ def profile_email_ajax(request):
data = {
'success': form.is_valid(),
'field_errors': form.errors, # ошибки полей
'form_errors': non_field_errors, # ошибки формы
'field_errors': form.errors, # ошибки полей
'form_errors': non_field_errors, # ошибки формы
}
return HttpResponse(json.dumps(data), content_type='application/json')

@ -2,21 +2,25 @@
import autocomplete_light
from django.db.models import Q
from docs.models import (Country, Currency, Measure)
from docs.models import Country, Currency, Measure
from customer.models import Client
class AutocompleteWithEmptyWidget(autocomplete_light.AutocompleteModelBase):
'''Автокомплит без текста подсказки
'''
autocomplete_js_attributes = {'placeholder': u''}
"""
Автокомплит без текста подсказки
"""
autocomplete_js_attributes = {'placeholder': ''}
class AutocompleteClient(autocomplete_light.AutocompleteModelBase):
'''Автокомплит клиента в зависимости от юзера
'''
autocomplete_js_attributes = {'placeholder': u'Название из добавленных ранее'}
"""
Автокомплит клиента в зависимости от юзера
"""
attrs = {
'data-autcomplete-minimum-characters': 0,
'placeholder': 'Название из добавленных ранее',
}
def choices_for_request(self):
q = self.request.GET.get('q', '')
user_ = self.request.user
@ -30,24 +34,37 @@ class AutocompleteClient(autocomplete_light.AutocompleteModelBase):
class AutocompleteCurrency(autocomplete_light.AutocompleteModelBase):
'''Автокомплит валют
'''
autocomplete_js_attributes = {'placeholder': u'Название валюты'}
"""
Автокомплит валют
"""
attrs = {
'data-autcomplete-minimum-characters': 0,
'placeholder': 'Название валюты',
}
search_fields = ('name', '^abc_code', '^code')
class AutocompleteMeasure(autocomplete_light.AutocompleteModelTemplate):
'''Автокомплит ед. измерения
'''
autocomplete_js_attributes = {'placeholder': u'Название ед. измерения'}
"""
Автокомплит ед. измерения
"""
attrs = {
'data-autcomplete-minimum-characters': 0,
'placeholder': '',
}
widget_attrs = {'data-widget-maximum-values': 3}
search_fields = ('name', 'full_name', '^code')
choice_template = 'autocomplete_light/docs_measure_choice.html'
class AutocompleteCountry(autocomplete_light.AutocompleteModelTemplate):
'''Автокомплит стран
'''
autocomplete_js_attributes = {'placeholder': u'Название страны'}
"""
Автокомплит стран
"""
attrs = {
'data-autcomplete-minimum-characters': 0,
'placeholder': 'Название страны',
}
search_fields = ('name', 'full_name', '^code')
choice_template = 'autocomplete_light/docs_country_choice.html'

@ -18,7 +18,7 @@ class BaseModelForm(MyBaseModelForm):
# пользователя. Если же пользователь никак не был задан - селекты будут пустыми! Если в форме есть поле client,
# то оно настраивается автоматически.
client = ModelChoiceField(Client.objects.all(), label=u'клиент', required=True,
widget=autocomplete_light.ChoiceWidget('ACClient'))
widget=autocomplete_light.ChoiceWidget('ACClient'))
adjust_client_fields = []
def __init__(self, user, *args, **kwargs):
@ -64,7 +64,7 @@ class BaseModelForm(MyBaseModelForm):
self._adjust_clients()
def _adjust_clients(self):
#"""Настраивает перечисленные в self.adjust_client_fields поля на модель Client."""
# Настраивает перечисленные в self.adjust_client_fields поля на модель Client.
if self.adjust_client_fields:
user_clients = Client.objects.filter(company=self._user.profile)
for key in self.adjust_client_fields:

@ -54,8 +54,6 @@ class InvoiceItemForm(MyBaseModelForm):
class Meta:
model = InvoiceItem
# exclude = ('parent',)
# fields = ('name', 'qty', 'units', 'price', 'total_price', 'id',)
fields = ('id', 'name', 'qty', 'units', 'price', 'total_price',)

@ -109,5 +109,6 @@ class BaseItemInvoiceModel(BaseItemModel):
return u'%s, %s %s * %s = %s %s' % (self.name[:30], self.qty, self.units, self.price, self.total_price, curr)
def save(self, *args, **kwargs):
self.total_price = self.price * self.qty # пересчитать сумму
# пересчитать сумму
self.total_price = self.price * self.qty
super(BaseItemInvoiceModel, self).save(*args, **kwargs)

@ -82,7 +82,7 @@
},
checkActionButtons = function() {
var max_num = parseInt($('#id_' + options.prefix + '-MAX_NUM_FORMS').val()),
formCount = $$formsetContainer.find('.'+options.formCssClass).length
formCount = $$formsetContainer.find('.'+options.formCssClass).length;
if (options.min_num > 0) {
if (formCount <= options.min_num) {
@ -182,20 +182,20 @@
}
return $$;
}
};
/* Setup plugin defaults */
var clearErrors = function(row) {
$(row).find('.errorlist').remove();
}
};
var calc_itogo = function(row) {
window.calc_itogo();
}
};
$.fn.formset.defaults = {
prefix: 'form', // The form prefix for your django formset
min_num: 0, // Minimum count rows
formTemplate: null, // The jQuery selection cloned to generate new form instances
addText: 'Добавить строку', // Text for the add link
addText: 'Добавить позицию', // Text for the add link
deleteText: '', // Text for the delete link
addCssClass: 'add-row', // CSS class applied to the add link
deleteCssClass: 'delete-row', // CSS class applied to the delete link
@ -206,4 +206,4 @@
beforeremove: null, // Function called each time before a new form is added
removed: calc_itogo // Function called each time a form is deleted
};
})(jQuery)
})(jQuery);

@ -1,133 +0,0 @@
{# заглушка js #}
<script type="text/javascript">
$(document).ready(function() {
$('tr.plat_form').formset({
prefix: '{{ pformset.prefix }}',
formCssClass: 'plat_dynamic-form',
});
$('tr.row_tbl_items').formset({
prefix: '{{ formset.prefix }}',
formCssClass: 'dynamic-form',
});
// units
$('body').on('selectChoice change', '.units input', function(e, choice, autocomplete) {
var name_input = $(this);
var code_input = name_input.closest('.row_tbl_items').find('.units_kod input');
if (choice) {
//console.log(choice.data());
name_input.val(choice.data('name')); // short name
code_input.val(choice.data('code'));
name_input.css('color', 'black')
}
else {
//console.log(choice, 'No choice!');
code_input.val('-');
name_input.css('color', 'red')
}
});
// country
$('body').on('selectChoice change', '.country_name input', function(e, choice, autocomplete) {
var name_input = $(this);
var code_input = name_input.closest('.row_tbl_items').find('.country_code input');
if (choice) {
//console.log(choice.data());
code_input.val(choice.data('code'));
name_input.css('color', 'black')
}
else {
//console.log(choice, 'No choice!');
code_input.val('-');
name_input.css('color', 'red')
}
});
$('#id_client').on('change', function() {
var client_id = $(this).val();
$.get('/my/docs/ajax_get_invoices/' + client_id, function(data) {
var select = $('#id_invoice');
if(select.prop) {
var options = select.prop('options');
}
else {
var options = select.attr('options');
}
$('option', select).remove();
options[options.length] = new Option('-------', '');
$.each(data, function(val, text) {
options[options.length] = new Option(text, val);
});
select.prop('selectedIndex', 0);
})
});
$('#id_invoice').on('change', function() {
var invoice_id = $(this).val();
$.each($('.row_tbl_items'), function(index, item){
$(item).find('a.delete-row').trigger('click');
});
$.get('/my/docs/ajax_get_client_by_invoice/' + invoice_id, function(data) {
var client = data[0];
$('#id_client_text').hide();
$('#id_client-deck').html('<span class="div hilight" data-value='+ data[0] +'><span class="remove div" style="display: inline;">X</span>' + data[1] + '</span>');
$('#id_client').html('<option selected="selected" value="'+ data[0] +'"></option>');
//$('#id_client').trigger('change');
})
$.get('/my/docs/ajax_get_tbl_items/' + invoice_id, function(data) {
var items = JSON.parse(data);
$.each(items, function(index, item){
var name = item['fields']['name'];
var units = item['fields']['units'];
var qty = item['fields']['qty'];
var price = item['fields']['price'];
var total_price = item['fields']['total_price'];
$('#tbl_items a.add-row').trigger('click');
var $last_row = $('.row_tbl_items:visible').last();
$last_row.find('.name input').val(name);
$last_row.find('.units input').val(units);
$last_row.find('.qty input').val(qty);
$last_row.find('.price input').val(price);
$last_row.find('.total_price input').val(total_price);
$.get('/my/docs/ajax_get_pair/Measure/name/code/' + units + '/', function(data){
if (data['val']) {
$last_row.find('.units_kod input').val(data['val']);
}
});
})
})
})
//var sender_val = $('input:radio[name=sender_group]:checked', '#doc-form').val();
var toggle_sender = function(client_type) {
var sender_val = $('input:radio[name=' + client_type + '_group]:checked', '#doc-form').val();
if (sender_val == 'another') {
$('#' + client_type).show()
} else {
$('#' + client_type).hide()
}
}
$.each(['sender', 'receiver'], function(i, client_type){
toggle_sender(client_type);
$('input:radio[name=' + client_type + '_group]').change(function(){
toggle_sender(client_type);
})
})
if ($('#id_fixes').is(':checked')){
$('#fix_block').show();
} else {
$('#fix_block').hide();
}
$('#id_fixes').change(function(){
$('#fix_block').toggle();
$('#id_fix_doc_num').val('11');
$('#id_fix_doc_date').val('');
})
});
</script>

@ -1,5 +1,7 @@
{% extends "base.html" %}
{% load static %}
{% block title %}{{ padeji_mnoj.imenit|capfirst }}{% endblock %}
{% block content %}
@ -73,7 +75,7 @@
</div>
<div id="row_pointer" style="display: none; float: left;">
<img src="{{ STATIC_URL }}img/left-arrow.png" />
<img src="{% static 'img/left-arrow.png' %}">
</div>
<div class="list-col2">
@ -139,10 +141,10 @@
CLIENT.get_url_pattern = "{% url 'customer_clients_get_ajax' 0 %}";
</script>
<script src="{{ STATIC_URL }}js/docs/list.filters.js"></script>
<script src="{{ STATIC_URL }}js/docs/list.panels.js"></script>
<script src="{{ STATIC_URL }}js/docs/del_doc.js"></script>
<script src="{{ STATIC_URL }}js/docs/list.email.js"></script>
<script src="{% static 'js/docs/list.filters.js' %}"></script>
<script src="{% static 'js/docs/list.panels.js' %}"></script>
<script src="{% static 'js/docs/del_doc.js' %}"></script>
<script src="{% static 'js/docs/list.email.js' %}"></script>
<script src="{{ STATIC_URL }}js/paginator.js"></script>
<script src="{% static 'js/paginator.js' %}"></script>
{% endblock %}

@ -38,14 +38,6 @@
<td></td>
</tr>
{% comment %}
<tr>
<td colspan="3"></td>
<td align="right"><b id="itogo_nds_text">Без НДС</b></td>
<td><b id="itogo_nds"></b></td>
<td></td>
</tr>
{% endcomment %}
</table>
{{ formset.management_form }}

Loading…
Cancel
Save