You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

420 lines
20 KiB

# -*- coding: utf-8 -*-
import os
from PIL import Image
from pytils import numeral
from dateutil.relativedelta import relativedelta
from django.db import models
from django.db.models import Max
from django.contrib.auth.models import User
from . import consts, managers
PROFILE_IMAGES_UPLOAD_DIR = 'customer/profile/' # куда сохранять загруженные изображения
BOSS_SIGN_IMG_SIZE = (100, 75)
GLAVBUH_SIGN_IMG_SIZE = (100, 75)
STAMP_IMG_SIZE = (180, 180)
def get_profile(user):
"""Возвращает профиль пользователя или None."""
try:
return UserProfile.objects.get(user=user)
except UserProfile.DoesNotExist:
return None
def upload_to(path, new_filename=None):
"""Куда и под каким именем сохранить загруженный файл."""
def get_upload_path(instance, filename):
filename = new_filename or filename
return os.path.join(path, instance.user.username, filename)
return get_upload_path
class UserProfile(models.Model):
"""Профиль пользователя."""
user = models.OneToOneField(User, related_name='profile', primary_key=True)
profile_type = models.PositiveSmallIntegerField(u'Тип профиля', choices=consts.PROFILE_TYPES)
# общие поля
boss_surname = models.CharField(u'Фамилия', max_length=30, default='',
help_text=u'Используется для строки "подпись" в документах.')
boss_name = models.CharField(u'Имя', max_length=30, default='')
boss_midname = models.CharField(u'Отчество', max_length=30, default='')
inn = models.CharField(u'ИНН', max_length=12, default='') # длина: 10 для организаций, 12 для ИП
ogrn = models.CharField(u'ОГРН/ОГРНИП', max_length=15, default='') # длина: 13 для организаций, 15 для ИП
okpo = models.CharField(u'ОКПО', max_length=10, blank=True, default='') # длина: 8 для организаций, 8 или 10 для ИП
glavbuh_surname = models.CharField(u'Фамилия', max_length=30, blank=True, default='',
help_text=u'Используется для строки "подпись" в документах.')
glavbuh_name = models.CharField(u'Имя', max_length=30, blank=True, default='')
glavbuh_midname = models.CharField(u'Отчество', max_length=30, blank=True, default='')
address = models.CharField(u'Адрес для документов', max_length=256, default='',
help_text=u'Будет подставляться в создаваемые счета, акты и накладные.')
real_address = models.CharField(u'Фактический адрес', max_length=256, blank=True, default='',
help_text=u'Используется только для карточки компании.')
phone_code = models.CharField(u'Код города', max_length=10, blank=True, default='')
phone = models.CharField(u'Номер телефона', max_length=20, blank=True, default='')
fax_code = models.CharField(u'Код города', max_length=10, blank=True, default='')
fax = models.CharField(u'Номер телефона', max_length=20, blank=True, default='')
email = models.EmailField(u'Электронная почта', max_length=75, blank=True, default='')
site = models.CharField(u'Сайт', max_length=256, blank=True, default='')
# поля, только для ИП
svid_gos_reg = models.CharField(u'Свид-во о гос. регистрации', max_length=256, blank=True, default='',
help_text=u'Требуется для счет-фактуры.')
ip_reg_date = models.DateField(u'Дата регистрации ИП', blank=True, null=True)
# поля, только для Организации
name = models.CharField(u'Краткое название организации', max_length=256, default='',
help_text=u'Будет подставляться в создаваемые документы.')
full_name = models.CharField(u'Полное название организации', max_length=256, blank=True, default='',
help_text=u'Как в учредительных документах.')
kpp = models.CharField(u'КПП', max_length=9, default='')
jur_address = models.CharField(u'Юридический (почтовый) адрес', max_length=256, blank=True, default='',
help_text=u'Как в учредительных документах.')
boss_title = models.CharField(u'Должность руководителя', max_length=256, blank=True, default='')
na_osnovanii = models.CharField(u'Действует на основании', max_length=256, blank=True, default='')
# подписи, печать и логотип
boss_sign = models.ImageField(u'Подпись руководителя', blank=True, default='',
upload_to=upload_to(PROFILE_IMAGES_UPLOAD_DIR, 'boss_sign.bmp'))
glavbuh_sign = models.ImageField(u'Подпись бухгалтера', blank=True, default='',
upload_to=upload_to(PROFILE_IMAGES_UPLOAD_DIR, 'glavbuh_sign.bmp'))
stamp = models.ImageField(u'Печать', blank=True, default='',
upload_to=upload_to(PROFILE_IMAGES_UPLOAD_DIR, 'stamp.bmp'))
logo = models.ImageField(u'Логотип', blank=True, default='',
upload_to=upload_to(PROFILE_IMAGES_UPLOAD_DIR, 'logo.bmp'))
created_at = models.DateTimeField(u'Создан', auto_now_add=True)
updated_at = models.DateTimeField(u'Изменен', auto_now=True)
active = models.BooleanField(u'Активен', default=False)
confirmed = models.BooleanField(u'Подтверждён', default=False)
objects = managers.UserProfileManager()
class Meta:
verbose_name = u'Реквизиты (профиль)'
verbose_name_plural = u'Реквизиты (профили)'
def __unicode__(self):
return u'%s, %s, ИНН %s' % (self.user.email, self.get_company_name()[0:30], self.inn or u'не указан')
def save(self, *args, **kwargs):
def process_img(orig_img, size):
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.thumbnail(size, Image.ANTIALIAS)
img.save(filename, 'bmp')
super(UserProfile, self).save(*args, **kwargs)
if self.boss_sign:
process_img(self.boss_sign, size=BOSS_SIGN_IMG_SIZE)
if self.glavbuh_sign:
process_img(self.glavbuh_sign, size=GLAVBUH_SIGN_IMG_SIZE)
if self.stamp:
process_img(self.stamp, size=STAMP_IMG_SIZE)
def is_ip(self):
return self.profile_type == consts.IP_PROFILE
def is_org(self):
return self.profile_type == consts.ORG_PROFILE
def check_name_not_filled(self):
"""`ИП ФИО` или `Название Организации`."""
if self.is_ip():
return self.get_boss_full_fio().strip() == ''
elif self.is_org():
return self.name.strip() == ''
return False
def get_company_name(self):
"""`ИП ФИО` или `Название Организации`."""
if self.profile_type == consts.IP_PROFILE:
return u'ИП %s' % self.get_boss_full_fio()
elif self.profile_type == consts.ORG_PROFILE:
return self.name.strip()
return u''
def get_inn_and_kpp(self):
"""Возвращает пару ИНН/КПП или только ИНН, если это ИП или КПП не заполнен."""
if self.profile_type == consts.ORG_PROFILE:
kpp = self.kpp.strip()
if kpp:
return u'%s/%s' % (self.inn, kpp,)
return self.inn
def get_boss_title(self):
"""Текст 'Индивидуальный предприниматель' или 'Руководитель организации'."""
if self.profile_type == consts.IP_PROFILE:
return u'Индивидуальный предприниматель'
elif self.profile_type == consts.ORG_PROFILE:
return u'Руководитель организации'
return u''
def get_boss_fio(self):
"""Фамилия и инициалы руководителя ИП/организации."""
if self.boss_surname and self.boss_name and self.boss_midname:
return u'%s %s.%s.' % (self.boss_surname, self.boss_name[0], self.boss_midname[0],)
return u''
def get_boss_full_fio(self):
"""Полное ФИО руководителя ИП/организации."""
return (u'%s %s %s' % (self.boss_surname, self.boss_name, self.boss_midname,)).strip()
def get_glavbuh_fio(self):
"""Фамилия и инициалы главного бухгалтера."""
if self.glavbuh_surname and self.glavbuh_name and self.glavbuh_midname:
return (u'%s %s. %s.' % (self.glavbuh_surname, self.glavbuh_name[0], self.glavbuh_midname[0],)).strip()
return u''
def get_glavbuh_full_fio(self):
"""Полное ФИО главного бухгалтера."""
return (u'%s %s %s' % (self.glavbuh_surname, self.glavbuh_name, self.glavbuh_midname,)).strip()
def get_full_phone(self):
"""(Код города) Номер телефона."""
phone_code = self.phone_code.strip('() ')
phone_code = u'(%s)' % phone_code if phone_code else phone_code
return (u'%s %s' % (phone_code, self.phone,)).strip()
def get_email(self):
return self.user.email
def get_full_fax(self):
"""(Код города) Номер факса."""
fax_code = self.fax_code.strip('() ')
fax_code = u'(%s)' % fax_code if fax_code else fax_code
return (u'%s %s' % (fax_code, self.fax,)).strip()
class BankAccount(models.Model):
"""Расчетные счета."""
user = models.ForeignKey(User, related_name='bank_accounts')
bik = models.CharField(u'БИК', max_length=10)
name = models.CharField(u'Наименование банка', max_length=256)
address = models.CharField(u'Местонахождение', max_length=256)
korr_account = models.CharField(u'Корр. счет', max_length=20)
account = models.CharField(u'Расчетный счет', max_length=20)
is_main = models.BooleanField(u'Основной счет', default=False)
created_at = models.DateTimeField(u'Создан', auto_now_add=True)
updated_at = models.DateTimeField(u'Изменен', auto_now=True)
objects = managers.BankAccountManager()
class Meta:
verbose_name = u'Расчётный счет'
verbose_name_plural = u'Расчётные счета'
ordering = ['-created_at']
def __unicode__(self):
return (u'%s, %s' % (self.account, self.name[0:30],)).strip()
def save(self, *args, **kwargs):
super(BankAccount, self).save(*args, **kwargs)
if self.is_main:
# если задано, что это будет основной счет, то сбросить у остальных счетов пользователя этот признак
BankAccount.objects.filter(user=self.user, is_main=True).exclude(pk=self.pk).update(is_main=False)
else:
# если нет основного счета, то установить его принудительно
BankAccount.objects.force_main(user=self.user)
def delete(self, *args, **kwargs):
super(BankAccount, self).delete(*args, **kwargs)
# если нет основного счета, то установить его принудительно
BankAccount.objects.force_main(user=self.user)
class Client(models.Model):
"""Контрагенты."""
user = models.ForeignKey(User, related_name='clients')
name = models.CharField(u'Наименование', max_length=256, db_index=True)
inn = models.CharField(u'ИНН', max_length=12)
kpp = models.CharField(u'КПП', max_length=9, blank=True, default='') # Организация
okpo = models.CharField(u'ОКПО', max_length=10, blank=True, default='') # ИП
address = models.CharField(u'Юр. адрес', max_length=256)
# банковские реквизиты
bank_bik = models.CharField(u'БИК', max_length=10, blank=True, default='')
bank_name = models.CharField(u'Наименование банка', max_length=256, blank=True, default='')
bank_address = models.CharField(u'Местонахождение', max_length=256, blank=True, default='')
bank_korr_account = models.CharField(u'Корр. счет', max_length=20, blank=True, default='')
bank_account = models.CharField(u'Расчетный счет', max_length=20, blank=True, default='')
# контакты
contact_name = models.CharField(u'Имя', max_length=50, blank=True, default='')
contact_email = models.EmailField(u'E-mail', max_length=50, blank=True, default='')
contact_phone = models.CharField(u'Телефон', max_length=50, blank=True, default='')
contact_icq = models.CharField(u'ICQ', max_length=20, blank=True, default='')
contact_skype = models.CharField(u'Skype', max_length=20, blank=True, default='')
contact_other = models.CharField(u'Другое', max_length=256, blank=True, default='')
created_at = models.DateTimeField(u'Создан', auto_now_add=True)
updated_at = models.DateTimeField(u'Изменен', auto_now=True)
objects = managers.ClientManager()
class Meta:
verbose_name = u'Контрагент'
verbose_name_plural = u'Контрагенты'
ordering = ['name', '-created_at']
def __unicode__(self):
return (u'%s, ИНН %s' % (self.name[0:30], self.inn or u'не указан',)).strip()
def get_inn_and_kpp(self):
"""Возвращает пару ИНН/КПП или только ИНН, если КПП не заполнен."""
kpp = self.kpp.strip()
if kpp:
return u'%s/%s' % (self.inn, kpp,)
return self.inn
class UserProfileFilters(models.Model):
"""Фильтрация реквизитов: какие данные показывать/скрывать при генерации карточки компании."""
user = models.OneToOneField(User, related_name='profile_filters', primary_key=True)
# общие фильтры
show_profile_type = models.BooleanField(u'Тип профиля', default=True)
show_inn = models.BooleanField(u'ИНН', default=True)
show_ogrn = models.BooleanField(u'ОГРН/ОГРНИП', default=True)
show_okpo = models.BooleanField(u'ОКПО', default=True)
show_glavbuh = models.BooleanField(u'Главный бухгалтер', default=True)
show_bank_account = models.BooleanField(u'Банковские реквизиты', default=True)
bank_account = models.ForeignKey(BankAccount, related_name='+', verbose_name=u'Расчетный счет', blank=True,
null=True, default=None)
show_contact_info = models.BooleanField(u'Контактная информация', default=True)
show_real_address = models.BooleanField(u'Фактический адрес', default=True)
show_phone = models.BooleanField(u'Телефон', default=True)
show_fax = models.BooleanField(u'Факс', default=True)
show_email = models.BooleanField(u'Электронная почта', default=True)
show_site = models.BooleanField(u'Сайт', default=True)
# только для ИП
show_ip_boss_fio = models.BooleanField(u'Фамилия, Имя, Отчество', default=True)
show_svid_gos_reg = models.BooleanField(u'Свид-во о гос. регистрации', default=True)
show_ip_reg_date = models.BooleanField(u'Дата регистрации ИП', default=True)
# только для Организации
show_name = models.BooleanField(u'Краткое название организации', default=True)
show_full_name = models.BooleanField(u'Полное название организации', default=True)
show_kpp = models.BooleanField(u'КПП', default=True)
show_org_boss_title_and_fio = models.BooleanField(u'Руководитель (Должность, ФИО)', default=True)
show_na_osnovanii = models.BooleanField(u'Действует на основании', default=True)
show_jur_address = models.BooleanField(u'Юридический адрес', default=True)
objects = managers.UserProfileFiltersManager()
class Meta:
verbose_name = u'Фильтры реквизитов'
verbose_name_plural = u'Фильтры реквизитов'
def __unicode__(self):
return u'%s' % self.user.email
def save(self, *args, **kwargs):
# всегда включены
self.show_ip_boss_fio = True
self.show_name = True
super(UserProfileFilters, self).save(*args, **kwargs)
class License(models.Model):
user = models.ForeignKey(User, related_name='licenses', verbose_name=u'пользователь')
term = models.IntegerField(verbose_name=u'срок лицензии')
date_from = models.DateField(u'дата начала', null=True, blank=True)
date_to = models.DateField(u'дата окончания', null=True, blank=True)
payform = models.IntegerField(verbose_name=u'форма оплаты',
choices=consts.PAYFORMS, default=0)
status = models.IntegerField(verbose_name=u'статус лицензии',
choices=consts.LICENSE_STATUSES, default=0)
order_date = models.DateField(verbose_name=u'дата заказа', auto_now_add=True)
paid_date = models.DateField(verbose_name=u'дата оплаты', null=True)
pay_sum= models.IntegerField(verbose_name=u'сумма оплаты')
deleted = models.BooleanField(u'удалено', default=False)
def __init__(self, *args, **kwargs):
super(License, self).__init__(*args, **kwargs)
self.__prev_date = self.paid_date
def __unicode__(self):
return u'%s - %s %s (%d %s)' % (
self.user.profile.get_company_name(),
self.term,
numeral.choose_plural(self.term, u"месяц, месяца, месяцев"),
self.pay_sum,
numeral.choose_plural(self.pay_sum, u"рубль, рубля, рублей"),
)
def save(self, *args, **kwargs):
if not self.__prev_date and self.paid_date:
max_date_license = License.objects.filter(user=self.user).aggregate(Max('date_to'))['date_to__max']
self.date_from = max_date_license + relativedelta(days=1)
self.date_to = self.date_from + relativedelta(months=self.term, days=-1)
self.user.profile.active = True
self.user.profile.save()
self.status = 1
super(License, self).save(*args, **kwargs)
def get_email(self):
return self.user.email
def get_action(self):
if self.status == 0:
if self.payform == 0:
return u'Скачать счёт'
elif self.payform == 1:
return u'Оплатить счёт'
elif self.payform == 2:
return u'Скачать квитанцию'
elif self.status in [1, 2]:
return u'История операций'
else:
return ''
def get_paid_status(self):
if self.status == 1:
return u'Лицензия оплачена, ещё не активирована'
elif self.status == 2:
return u'Лицензия оплачена: осталось %d дней.'
class LicensePrice(models.Model):
term = models.IntegerField(verbose_name=u'срок лицензии',
choices=consts.TERMS)
price = models.IntegerField(verbose_name=u'сумма оплаты')
def __unicode__(self):
return u'%s %s (%d %s)' % (self.term,
numeral.choose_plural(self.term, u"месяц, месяца, месяцев"),
self.price,
numeral.choose_plural(self.price, u"рубль, рубля, рублей"),
)