# -*- coding: utf-8 -*-
__author__ = 'Sergei Erjemin'
__email__ = 'erjemin@gmail.com'
__version__ = '0.2.0'
from django.db import models
from datetime import date, datetime
from django.utils import timezone
from django.contrib.auth.models import User
from oknardia.settings import *
from web.add_func import sanitize_slug, safe_html_spec_symbols
import re
# Таблица: Каталог профилей, стеклопакетов (добавлено 09.авг.2017)
# create table oknardia_catalog2profile
# (
# id bigint auto_increment
# primary key,
# kProfile_id bigint null, -- -> Профиль, к которому относится карточка каталога
# -- через foreignkey kProfile в id в PVCprofiles
# kBlogCatalog_id bigint null, -- -> Запись в каталог-блоге относящаяся к данному профилю
# -- через foreignkey kBlogCatalog в id в BlogPosts
# sCatalogCardType smallint not null -- Тип карточки каталога: описание для профиля или для бренда
# );
#
# create index oknardia_catalog2profile_kBlogCatalog_id_0330d5e7
# on oknardia_catalog2profile (kBlogCatalog_id);
#
# create index oknardia_catalog2profile_kProfile_id_e18f5c89
# on oknardia_catalog2profile (kProfile_id);
#
# create index oknardia_catalog2profile_sCatalogCardType_69db11a2
# on oknardia_catalog2profile (sCatalogCardType);
class Catalog2Profile(models.Model):
kProfile = models.ForeignKey(
'PVCprofiles',
db_index=True,
null=True,
blank=True,
db_constraint=False,
on_delete=models.SET_NULL,
default=None,
verbose_name="Профиль",
help_text="Профиль, к которому относится карточка каталога."
)
kBlogCatalog = models.ForeignKey(
'BlogPosts',
db_index=True,
db_constraint=False,
on_delete=models.SET_NULL,
null=True,
blank=True,
default=None,
verbose_name="Каталог-блог",
help_text="Запись в каталог-блоге относящаяся к данному профилю."
)
sCatalogCardType = models.SmallIntegerField(
choices=((CATALOG_RECORD_FOR_PROFILE_MODEL, "Профиль (карточка каталога)"),
(CATALOG_RECORD_FOR_PROFILE_MANUFACTURER, "Бренд (описание производителя профиля)")),
default=CATALOG_RECORD_FOR_PROFILE_MODEL,
db_index=True,
verbose_name="Тип",
help_text="Тип карточки каталога: описание для профиля или для бренда."
)
def __unicode__(self):
return f":{self.id}:"
def __str__(self):
return f":{self.id}:"
class Meta:
verbose_name = "Связка-каталог «профили↔блог»"
verbose_name_plural = "Связки-каталог «профили↔блог»"
# Таблица: Лог замеров пользователей
# create table oknardia_logmeasure
# (
# id bigint auto_increment
# primary key, -- id
# dMeasureCreate datetime(6) not null, -- Дата когда прислали данные (datestamp - автоматически)
# kMeasureByUser_id bigint not null, -- -> Кто произвел замер и прислал данные
# -- через foreignkey kMeasureApartment
# -- в id в OurUser
# kMeasureBuilding_id bigint not null, -- -> По какому адресу был произведен замер
# -- через foreignkey kMeasureBuilding
# -- в id в Building_Info
# kMeasureApartment_id bigint not null, -- -> Для какой типовой квартиры сделали замер
# -- через foreignkey kMeasureApartment
# -- в id в Apartment_Type
# constraint oknardia_logmeasure_kMeasureApartment_id_a234f4c7_fk_oknardia_
# foreign key (kMeasureApartment_id) references oknardia_apartment_type (id),
# constraint oknardia_logmeasure_kMeasureBuilding_id_a64fdf9c_fk_oknardia_
# foreign key (kMeasureBuilding_id) references oknardia_building_info (id),
# constraint oknardia_logmeasure_kMeasureByUser_id_2efc0f8e_fk_oknardia_
# foreign key (kMeasureByUser_id) references oknardia_ouruser (id)
# );
# create index oknardia_logmeasure_dMeasureCreate_c38c8308
# on oknardia_logmeasure (dMeasureCreate);
class LogMeasure(models.Model):
dMeasureCreate = models.DateTimeField(
auto_now_add=True,
db_index=True,
verbose_name="Обращение"
)
kMeasureByUser = models.ForeignKey(
'OurUser',
unique=False,
default=0,
on_delete=models.DO_NOTHING,
verbose_name="От кого",
help_text="Кто произвел замер и прислал данные"
)
kMeasureBuilding = models.ForeignKey(
'Building_Info',
unique=False,
db_index=False,
default=0,
on_delete=models.DO_NOTHING,
verbose_name=u"Адрес",
help_text=u"По какому адресу был произведен замер."
)
kMeasureApartment = models.ForeignKey(
'Apartment_Type',
unique=False,
db_index=True,
default=0,
on_delete=models.DO_NOTHING,
verbose_name="Квартира",
help_text="Для какой типовой квартиры сделали замер."
)
def __unicode__(self):
# return '%s :: %s' % (datetime.strftime(timezone.localtime(
# self.dMeasureCreate, timezone.get_current_timezone()), "%Y-%m-%d %H:%M:%S"), self.kMeasureApartment)
return f"{self.dMeasureCreate:%Y-%m-%d %H:%M:%S} :: {self.kMeasureApartment}"
def __str__(self):
return self.__unicode__()
class Meta:
verbose_name = "Лог: замеры пользователей"
verbose_name_plural = "Лог: замеры пользователей"
ordering = ['dMeasureCreate']
# Таблица: Лог заинтересованности (Пользователь,
# create table oknardia_logdemand
# (
# id bigint auto_increment
# primary key, -- id
# dDemandCreate datetime(6) not null, -- Дата когда запросили ком.пред. (datestamp - автоматически)
# kDemandByUser_id bigint not null, -- -> Кто запросил коммерческое предложение
# -- через foreignkey kMeasureApartment
# -- в id в OurUser
# kDemandBuilding_id bigint not null, -- -> Какой адрес был запрошен
# -- через foreignkey kMeasureBuilding
# -- в id в Building_Info
# kDemandApartment_id bigint not null, -- -> Цены на окна в какую типовую квартиру запросили
# -- через foreignkey kMeasureApartment
# -- в id в Apartment_Type
# constraint oknardia_logdemand_kDemandApartment_id_4c380928_fk_oknardia_
# foreign key (kDemandApartment_id) references oknardia_apartment_type (id),
# constraint oknardia_logdemand_kDemandBuilding_id_ee8db1d6_fk_oknardia_
# foreign key (kDemandBuilding_id) references oknardia_building_info (id),
# constraint oknardia_logdemand_kDemandByUser_id_320f0009_fk_oknardia_
# foreign key (kDemandByUser_id) references oknardia_ouruser (id)
# );
# create index oknardia_logdemand_dDemandCreate_3c8ebcfe
# on oknardia_logdemand (dDemandCreate);
class LogDemand(models.Model):
dDemandCreate = models.DateTimeField(
auto_now_add=True,
db_index=True,
verbose_name="Обращение"
)
kDemandByUser = models.ForeignKey(
'OurUser',
unique=False,
default=0,
on_delete=models.DO_NOTHING,
verbose_name="Кто спросил",
help_text="Кто сделал запрос в систему"
)
kDemandBuilding = models.ForeignKey(
'Building_Info',
unique=False,
db_index=False,
default=0,
on_delete=models.DO_NOTHING,
verbose_name="Адрес",
help_text="Какой адрес был запрошен."
)
kDemandApartment = models.ForeignKey(
'Apartment_Type',
unique=False,
db_index=True,
default=0,
on_delete=models.DO_NOTHING,
verbose_name="Квартира",
help_text="Цены на окна в какую типовую квартиру запросили."
)
def __unicode__(self):
# return '%s :: %s' % (datetime.strftime(timezone.localtime(
# self.dDemandCreate, timezone.get_current_timezone()), "%Y-%m-%d %H:%M:%S"), self.kDemandApartment)
return f"{self.dDemandCreate:%Y-%m-%d %H:%M:%S} :: {self.kDemandApartment}"
def __str__(self):
return self.__unicode__()
class Meta:
verbose_name = "Лог: запрос в систему с главной"
verbose_name_plural = "Лог: запросы в систему с главной"
ordering = ['dDemandCreate']
# Таблица: Оконный профиль
# create table oknardia_pvcprofiles
# (
# id bigint auto_increment
# primary key, -- id
# sProfileName varchar(64) not null, -- Название профиля (заголовок)
# sProfileBriefDescription varchar(255) not null, -- Краткая характеристика профиля (лид)
# sProfileReinforcement varchar(255) not null, -- Армирование профиля. Описание кратко
# sProfileDescription longtext null, -- Описание профиля (JSON)
# kProfile2User_id bigint not null, -- -> Данный профиль добавил пользователь:
# -- через foreignkey kProfile2User в id в OurUser
# fProfileHeatTransf decimal(5, 2) not null, -- Сопротивление теплопередаче Ro (м²×°C/Вт)
# sProfileSealDescription varchar(128) null, -- Характеристики или цвет уплотнителя
# fProfileSeals smallint unsigned null, -- Число контуров уплотнения
# fProfileSoundproofing decimal(5, 2) not null, -- Коэффициент звукоизоляции (дБ). 1-й класс — 25-29дБ;
# -- 2-й класс — 30-24дБ; 3-й класс — 35-39дБ;
# -- 4-й класс — 40-44дБ; 5-й класс — 45-49дБ;
# -- 6-й класс — свыше 50 дБ;
# iProfileCameras varchar(5) null, -- Число камер рамка/створка
# iProfileGlazingThickness smallint unsigned not null, -- Максимальная толщина стеклопакета (мм)
# iProfileHeight smallint unsigned not null, -- Высота в световом проеме (рама+створка), мм.
# iProfileRabbet smallint unsigned not null, -- Размер зазора между рамой и створкой (фальц), мм.
# iProfileThickness smallint unsigned not null, -- Монтажная ширина профиля (мм)
# sProfileManufacturer varchar(128) not null, -- Завод (компания) производитель
# sProfileFillet varchar(255) not null, -- Штапик. Описание кратко
# sProfileColor varchar(128) not null, -- Цвет профиля
# sProfileOther varchar(255) not null, -- Прочие характеристики в формате:
# -- Характеристика: Значение; Характеристика: Значение;
# fProfileRating double not null, -- Рейтинг (0 … +5)
# dProfileCreate datetime(6) not null, -- Дата создания записи (лог)
# dProfileModify datetime(6) not null, -- Дата изменения записи (лог)
# constraint sProfileBriefDescription
# unique (sProfileBriefDescription),
# constraint sProfileName
# unique (sProfileName),
# constraint oknardia_pvcprofiles_kProfile2User_id_e868cd0a_fk_oknardia_
# foreign key (kProfile2User_id) references oknardia_ouruser (id),
# constraint fProfileSeals
# check (`fProfileSeals` >= 0),
# constraint iProfileGlazingThickness
# check (`iProfileGlazingThickness` >= 0),
# constraint iProfileHeight
# check (`iProfileHeight` >= 0),
# constraint iProfileRabbet
# check (`iProfileRabbet` >= 0),
# constraint iProfileThickness
# check (`iProfileThickness` >= 0)
# );
class PVCprofiles(models.Model):
sProfileName = models.CharField(
max_length=64,
unique=True,
db_index=True,
verbose_name="Профиль",
help_text="Название профиля."
)
sProfileBriefDescription = models.CharField(
max_length=255,
db_index=True,
blank=False,
unique=True,
verbose_name="Краткое описание",
help_text="Краткая характеристика профиля."
)
sProfileManufacturer = models.CharField(
max_length=128,
default=u"—//—",
db_index=True,
null=False,
blank=False,
verbose_name="Производитель",
help_text="Завод (компания) производитель"
)
iProfileCameras = models.CharField(
max_length=5,
default="—/—",
null=True,
blank=True,
verbose_name="Камер",
help_text="Число камер рамка/створка."
)
iProfileThickness = models.PositiveSmallIntegerField(
default=0,
verbose_name="W",
help_text="Монтажная ширина профиля (мм)."
)
fProfileHeatTransf = models.DecimalField(
max_digits=5,
decimal_places=2,
default=0,
verbose_name="Ro",
help_text="Сопротивление теплопередаче Ro (м²×°C/Вт)"
)
fProfileSoundproofing = models.DecimalField(
max_digits=5,
decimal_places=2,
default=0,
verbose_name="дБ",
help_text="Коэффициент звукоизоляции (дБ). 1-й класс — 25-29дБ; 2-й класс — 30-24дБ; 3-й класс — 35-39дБ; "
"4-й класс — 40-44дБ; 5-й класс — 45-49дБ; 6-й класс — свыше 50 дБ; "
)
iProfileGlazingThickness = models.PositiveSmallIntegerField(
default=0,
verbose_name="W-cтеклопак",
help_text="Максимальная толщина стеклопакета (мм)."
)
sProfileReinforcement = models.CharField(
blank=True,
max_length=255,
verbose_name="Армирование",
help_text="Армирование профиля. Описание кратко."
)
fProfileSeals = models.PositiveSmallIntegerField(
default=0,
null=True,
blank=True,
verbose_name="Контуров уплотнения",
help_text="Число контуров уплотнения."
)
sProfileSealDescription = models.CharField(
max_length=128,
default=u"",
null=True,
blank=True,
verbose_name="Уплотнитель",
help_text="Характеристики или цвет уплотнителя."
)
sProfileFillet = models.CharField(
blank=True,
max_length=255,
default="",
verbose_name="Штапик",
help_text="Штапик. Описание кратко."
)
iProfileHeight = models.PositiveSmallIntegerField(
default=0,
verbose_name="Высота",
help_text="Высота в световом проеме (рама+створка), мм."
)
iProfileRabbet = models.PositiveSmallIntegerField(
default=0,
verbose_name="Фальц",
help_text="Размер зазора между рамой и створкой (высота фальца), мм."
)
sProfileColor = models.CharField(
blank=True,
max_length=128,
default="белый",
verbose_name="Цвет",
help_text="Цвет профиля"
)
sProfileOther = models.CharField(
blank=True,
max_length=255,
default="",
verbose_name="Прочее",
help_text="Прочие характеристики в формате: Характеристика: Значение; Характеристика: Значение;"
)
kProfile2User = models.ForeignKey(
'OurUser',
db_index=True,
on_delete=models.DO_NOTHING,
verbose_name="User",
help_text="Данный профиль добавил пользователь."
)
fProfileRating = models.FloatField(
default=0.,
db_index=True,
verbose_name="Рейтинг",
help_text="Рейтинг (0… +5)."
)
sProfileDescription = models.TextField(
null=True,
default='',
verbose_name="Описание",
help_text="Описание профиля (JSON)"
)
dProfileCreate = models.DateTimeField(
auto_now_add=True,
db_index=False,
verbose_name="Создано"
)
dProfileModify = models.DateTimeField(
auto_now=True,
verbose_name="Когда отредактировано"
)
def __unicode__(self):
return f'{self.id:04d}: {self.sProfileName} ({self.sProfileManufacturer})'
def __str__(self):
return self.__unicode__()
class Meta:
verbose_name = "Окно: профиль"
verbose_name_plural = "Окна: профили"
ordering = ['sProfileName']
# Таблица: стеклопакет
# create table oknardia_glazing
# (
# id bigint auto_increment -- id
# primary key,
# sGlazingName varchar(128) not null, -- Краткое название или фирменное
# -- обозначение стеклопакета (заголовок)
# iGlazingCamerasN smallint unsigned not null, -- Число камер
# iGlazingThickness smallint unsigned not null, -- Толщина стеклопакета (мм)
# sGlazingBriefDescription varchar(256) not null, -- Краткая характеристика стеклопакета (лид)
# kGlazing2User_id bigint not null, -- -> Данный стеклопакет добавил пользователь
# -- через foreignkey kGlazing2User
# -- в id в OurUser
# sGlazingMark varchar(128) null, -- Схема, марка, маркировка, модель стеклопакета
# sGlazingManufacturer varchar(128) null, -- Завод (компания) производитель
# fGlazingHeatTransfer decimal(5, 2) not null, -- Сопротивление теплопередаче Ro (м²×°C/Вт)
# fGlazingSoundproofing decimal(5, 2) not null, -- Коэффициент звукоизоляции (дБ)
# fGlazingLightTransmission decimal(5, 2) not null, -- Коэффициент светопропускания (%)
# sGlazingLightReflectance varchar(7) not null, -- Коэффициент светоотражения,
# -- в формате внешний/внутренний (%)
# fGlazingPassingSun decimal(5, 2) not null, -- Коэффициент солнцепропускания (%)
# sGlazingReflectionAndAbsorptionOfHeat varchar(7) not null, -- Коэффициент теплоотражения/теплопоглощения %
# fGlazingRating double not null, -- Рейтинг (-1 … +1)
# sGlazingDescription longtext null, -- Детальное описание стеклопакета (JSON)
# sGlazingToning varchar(32) null, -- Тонирование стеклопакета (цвет)
# dGlazingCreate datetime(6) not null, -- Создано (datestamp - автоматически)
# dGlazingModify datetime(6) not null, -- Отредактировано (datestamp - автоматически)
# constraint sGlazingName
# unique (sGlazingName),
# constraint oknardia_glazing_kGlazing2User_id_07e02dad_fk_oknardia_
# foreign key (kGlazing2User_id) references oknardia_ouruser (id),
# constraint iGlazingCamerasN
# check (`iGlazingCamerasN` >= 0),
# constraint iGlazingThickness
# check (`iGlazingThickness` >= 0)
# );
#
# create index oknardia_glazing_fGlazingHeatTransfer_e1df446d
# on oknardia_glazing (fGlazingHeatTransfer);
#
# create index oknardia_glazing_fGlazingLightTransmission_175b12d1
# on oknardia_glazing (fGlazingLightTransmission);
#
# create index oknardia_glazing_fGlazingPassingSun_bd7d55eb
# on oknardia_glazing (fGlazingPassingSun);
#
# create index oknardia_glazing_fGlazingRating_c19364cf
# on oknardia_glazing (fGlazingRating);
#
# create index oknardia_glazing_fGlazingSoundproofing_a2dca26d
# on oknardia_glazing (fGlazingSoundproofing);
#
# create index oknardia_glazing_sGlazingLightReflectance_ccff0740
# on oknardia_glazing (sGlazingLightReflectance);
#
# create index oknardia_glazing_sGlazingReflectionAndAbsorptionOfHeat_b333cc75
# on oknardia_glazing (sGlazingReflectionAndAbsorptionOfHeat);
class Glazing(models.Model):
sGlazingName = models.CharField(
max_length=128,
unique=True,
verbose_name="Название",
help_text="Краткое название или фирменное обозначение стеклопакета."
)
iGlazingCamerasN = models.PositiveSmallIntegerField(
default=1,
verbose_name="Камер",
help_text="Число камер"
)
iGlazingThickness = models.PositiveSmallIntegerField(
default=0,
verbose_name="Толщина",
help_text="Толщина стеклопакета (мм)."
)
sGlazingBriefDescription = models.CharField(
max_length=256,
verbose_name="Краткая характеристика",
help_text="Краткая характеристика стеклопакета."
)
kGlazing2User = models.ForeignKey(
'OurUser',
db_index=True,
on_delete=models.DO_NOTHING,
verbose_name="User",
help_text="Описание стекопакета добавлено пользователем."
)
sGlazingMark = models.CharField(
max_length=128,
default="—",
null=True,
blank=True,
verbose_name="Марка",
help_text="Схема, марка, маркировка, модель стеклопакета"
)
sGlazingManufacturer = models.CharField(
max_length=128,
default="—",
null=True,
blank=True,
verbose_name="Производитель",
help_text="Завод (компания) производитель"
)
fGlazingHeatTransfer = models.DecimalField(
max_digits=5,
decimal_places=2,
default=0,
db_index=True,
verbose_name="Тепл.Сопр.",
help_text="Сопротивление теплопередаче Ro (м²×°C/Вт)"
)
fGlazingSoundproofing = models.DecimalField(
max_digits=5,
decimal_places=2,
default=0,
db_index=True,
verbose_name="Звукоизоляция",
help_text="Коэффициент звукоизоляции (дБ)"
)
fGlazingLightTransmission = models.DecimalField(
max_digits=5,
decimal_places=2,
default=0,
db_index=True,
verbose_name="Светопропускание",
help_text="Коэффициент светопропускания (%)"
)
sGlazingLightReflectance = models.CharField(
max_length=7,
default="—/—",
db_index=True,
verbose_name="Светоотражение",
help_text="Коэффициент светоотражения, внешний/внутренний (%)"
)
fGlazingPassingSun = models.DecimalField(
max_digits=5,
decimal_places=2,
default=0,
db_index=True,
verbose_name="Солнцепропускание",
help_text="Коэффициент солнцепропускания (%)"
)
sGlazingReflectionAndAbsorptionOfHeat = models.CharField(
max_length=7,
default=u"—/—",
db_index=True,
verbose_name="Теплоотражение и теплопоглощение",
help_text="Коэффициент теплоотражения/теплопоглощения (%)"
)
fGlazingRating = models.FloatField(
default=0.,
db_index=True,
verbose_name="Рейтинг",
help_text="Рейтинг (-1 … +1)."
)
sGlazingDescription = models.TextField(
null=True,
default='',
verbose_name="Описание",
help_text="Детальное описание стеклопакета (JSON)"
)
sGlazingToning = models.CharField(
null=True,
blank=True,
max_length=32,
default='Нет',
verbose_name="Тонирование",
help_text="Тонирование стеклопакета (цвет)"
)
dGlazingCreate = models.DateTimeField(
auto_now_add=True,
db_index=False,
verbose_name="Создано"
)
dGlazingModify = models.DateTimeField(
auto_now=True,
verbose_name="Отредактировано"
)
def __unicode__(self):
return f'{self.id:04d}: {self.sGlazingName} / {self.sGlazingMark}'
def __str__(self):
return self.__unicode__()
class Meta:
verbose_name = "Окно: стеклопакет"
verbose_name_plural = "Окна: стеклопакеты"
ordering = ['sGlazingName']
# Таблица: Типовой комплект (набор): профиль, стеклопакет, подоконник, фурнитура и т.д.
# create table oknardia_setkit
# (
# id bigint auto_increment -- id (primary key)
# primary key,
# sSetName varchar(128) not null, -- Марка, краткое название или фирменное обозначение набора
# kSet2User_id bigint not null, -- -> Пользователь, который определил данный набор
# -- через foreignkey kSet2User в id в OurUser
# sSetDescription longtext not null, -- Детальное описание стеклопакета (допустим HTML)
# kSet2PVCprofiles_id bigint not null, -- -> Профиль используемый в данном наборе.
# -- через foreignkey kSet2PVCprofiles в id в PVCprofiles
# kSet2Glazing_id bigint not null, -- -> Стеклопакет используемый в данном наборе.
# -- через foreignkey kSet2Glazing в id в Glazing
# sSetClimateControl varchar(128) not null, -- Система климат-контроля: марка, краткое название или
# -- фирменное обозначение
# sSetSill varchar(128) not null, -- Подоконник: марка, краткое название или фирменное обозначение
# sSetImplementAll varchar(128) not null, -- Фурнитура: марка, краткое название или фирменное обозначение
# sSetImplementHandles varchar(128) not null, -- Фурнитура ручки: марка, краткое название или фирменное
# -- обозначение
# sSetImplementHinges varchar(128) not null, -- Фурнитура петли: марка, краткое название или фирменное
# -- обозначение
# sSetImplementLatch varchar(128) not null, -- Фурнитура механизма запирания: марка, краткое название
# -- или фирменное обозначение
# sSetImplementLimiter varchar(128) not null, -- Фурнитура ограничителя: марка, краткое название или
# -- фирменное обозначение
# sSetImplementCatch varchar(128) not null, -- Фурнитура фиксаторов открывания: марка, краткое название
# -- или фирменное обозначение
# sSetPanes varchar(128) not null, -- Водоотлив: марка, краткое название или фирменное обозначение
# sSetSlope varchar(128) not null, -- Откос: марка, краткое название или фирменное обозначение
# sSetDelivery varchar(64) not null, -- Доставка: опишите условия, регион, способ расчета стоимости
# -- и т.п.
# bSetDelivery tinyint(1) not null, -- Отмечено, если доставка включена в стоимость
# sSetUninstallInstall varchar(64) not null, -- Доставка: опишите условия, регион, способ расчета стоимости
# bSetUninstallInstall tinyint(1) not null, -- Отмечено, если Демонтаж/Монтаж включен в стоимость
# sSetOtherConditions varchar(512) not null, -- Прочие условия: монтаж, демонтаж, вывоз мусора,
# -- предоставление пленки для укрытия мебели и т.п.
# fSetRating double not null, -- Рейтинг (0.0 … 5.0). Если рейтинг 0.1 то выводится
# -- полупрозрачным и с меткой что поставщик бяка
# iSetNumEval int unsigned not null, -- Количество оценок
# iSetImpressions int unsigned not null, -- Число просмотров (??)
# iSetViews int unsigned not null, -- Число показов (??)
# sSetActive tinyint(1) not null, -- Отображать предложение (если "вкл") или нет (если "выкл").
# dSetCommercialUntil datetime(6) not null, -- Дата до которой набор считается размещенным на
# -- коммерческой основе
# dSetCreate datetime(6) not null, -- Создано (datestamp - автоматически)
# dSetModify datetime(6) not null, -- Отредактировано (datestamp - автоматически)
# constraint sSetName
# unique (sSetName),
# constraint oknardia_setkit_kSet2Glazing_id_ed918cc4_fk_oknardia_glazing_id
# foreign key (kSet2Glazing_id) references oknardia_glazing (id),
# constraint oknardia_setkit_kSet2PVCprofiles_id_eecb9bb2_fk_oknardia_
# foreign key (kSet2PVCprofiles_id) references oknardia_pvcprofiles (id),
# constraint oknardia_setkit_kSet2User_id_e10c182d_fk_oknardia_ouruser_id
# foreign key (kSet2User_id) references oknardia_ouruser (id),
# constraint iSetImpressions
# check (`iSetImpressions` >= 0),
# constraint iSetNumEval
# check (`iSetNumEval` >= 0),
# constraint iSetViews
# check (`iSetViews` >= 0)
# );
class SetKit(models.Model):
sSetName = models.CharField(
max_length=128,
unique=True,
verbose_name="Название",
help_text="Марка, краткое название или фирменное обозначение набора."
)
kSet2User = models.ForeignKey(
'OurUser',
db_index=True,
on_delete=models.DO_NOTHING,
verbose_name="User",
help_text="Пользователь, который определил данный набор."
)
sSetDescription = models.TextField(
blank=True,
verbose_name="Описание",
help_text="Детальное описание стеклопакета (допустим HTML)"
)
kSet2PVCprofiles = models.ForeignKey(
'PVCprofiles',
db_index=True,
on_delete=models.DO_NOTHING,
verbose_name="Профиль",
help_text="Профиль используемый в данном наборе."
)
kSet2Glazing = models.ForeignKey(
'Glazing',
db_index=True,
on_delete=models.DO_NOTHING,
verbose_name="Стеклопакет",
help_text="Стеклопакет используемый в данном наборе."
)
sSetClimateControl = models.CharField(
max_length=128,
blank=True,
default="",
verbose_name="Климат-контроль",
help_text="Система климат-контроля: марка, краткое название или фирменное обозначение."
)
sSetSill = models.CharField(
max_length=128,
blank=True,
verbose_name="Подоконник",
help_text="Подоконник: марка, краткое название или фирменное обозначение."
)
sSetImplementAll = models.CharField(
max_length=128,
verbose_name="Фурнитура",
help_text="Фурнитура: марка, краткое название или фирменное обозначение."
)
sSetImplementHandles = models.CharField(
max_length=128,
blank=True,
verbose_name="Ручки",
help_text="Фурнитура ручки: марка, краткое название или фирменное обозначение."
)
sSetImplementHinges = models.CharField(
max_length=128,
blank=True,
verbose_name="Петли",
help_text="Фурнитура петли: марка, краткое название или фирменное обозначение."
)
sSetImplementLatch = models.CharField(
max_length=128,
blank=True,
verbose_name="Запоры",
help_text="Фурнитура механизма запирания: марка, краткое название или фирменное обозначение."
)
sSetImplementLimiter = models.CharField(
max_length=128,
blank=True,
verbose_name="Ограничитель",
help_text="Фурнитура ограничителя: марка, краткое название или фирменное обозначение."
)
sSetImplementCatch = models.CharField(
max_length=128,
blank=True,
verbose_name="Фиксаторы открывания",
help_text="Фурнитура фиксаторов открывания: марка, краткое название или фирменное обозначение."
)
sSetPanes = models.CharField(
max_length=128,
blank=True,
verbose_name="Водоотлив",
help_text="Водоотлив: марка, краткое название или фирменное обозначение."
)
sSetSlope = models.CharField(
max_length=128,
blank=True,
verbose_name="Откос",
help_text="Откос: марка, краткое название или фирменное обозначение."
)
sSetDelivery = models.CharField(
max_length=64,
blank=True,
default="Включена в стоимость",
verbose_name="Доставка",
help_text="Доставка: опишите условия, регион, способ расчета стоимости и т.п."
)
bSetDelivery = models.BooleanField(
default=True,
verbose_name="Доставка(б)",
help_text="Отмечено, если доставка включена в стоимость"
)
sSetUninstallInstall = models.CharField(
max_length=64,
blank=True,
default="Включен в стоимость",
verbose_name="Монтаж",
help_text="Доставка: опишите условия, регион, способ расчета стоимости…"
)
bSetUninstallInstall = models.BooleanField(
default=True,
verbose_name="Монтаж(б)",
help_text="Отмечено, если Демонтаж/Монтаж включен в стоимость"
)
sSetOtherConditions = models.CharField(
max_length=512,
blank=True,
default="",
verbose_name="Прочие условия",
help_text="Прочие условия: монтаж, демонтаж, вывоз мусора, предоставление пленки для укрытия мебели и т.п."
)
fSetRating = models.FloatField(
default=0.,
db_index=True,
verbose_name="Рейтинг",
help_text="Рейтинг (0.0 … 5.0). Если рейтинг 0.1 то выводится полупрозрачным и с меткой что поставщик бяка"
)
iSetNumEval = models.PositiveIntegerField(
default=0,
verbose_name=u"N оценок",
help_text=u"Количество оценок."
)
iSetImpressions = models.PositiveIntegerField(
default=0,
verbose_name=u"Показы",
help_text=u"Число показов."
)
iSetViews = models.PositiveIntegerField(
default=0,
verbose_name="Просмотры",
help_text="Число просмотров."
)
sSetActive = models.BooleanField(
default=True,
verbose_name="Активно",
help_text="Отображать предложение (если \"вкл\") или нет (если \"выкл\")."
)
dSetCommercialUntil = models.DateTimeField(
blank=True,
default=datetime(2018, 3, 25, 12, 0, 0),
verbose_name="Коммерческий до",
help_text="Дата до которой набор считается размещенным на коммерческой основе."
)
dSetCreate = models.DateTimeField(
auto_now_add=True,
verbose_name="Создано"
)
dSetModify = models.DateTimeField(
auto_now=True,
db_index=True,
verbose_name="Отредактировано"
)
def __unicode__(self):
# return f"{self.id:04d}: {self.sSetName} ({self.kSet2User})"
return f"{self.id:04d}: {self.sSetName} "
def __str__(self):
return self.__unicode__()
class Meta:
verbose_name = "Окно: набор"
verbose_name_plural = "Окна: наборы"
ordering = ['id', 'sSetName']
# Таблица: Ценники на установку окна
# create table oknardia_priceoffer
# (
# id bigint auto_increment
# primary key, -- id
# kOffer2MountDim_id bigint not null, -- -> Проём для которого установлена цена
# -- через foreignkey kOffer2MountDim в id в Win_MountDim
# kOfferFromUser_id bigint not null, -- -> Пользователь, который установил эту цену
# -- через foreignkey kOfferFromUser в id в OurUser
# kOffer2SetKit_id bigint not null, -- -> Набор, для которого установлена цена
# -- через foreignkey kOffer2SetKit в id в SetKit
# sOfferFlapConfig varchar(32) not null, -- Предлагаемая схема открывания (МЕТАЯЗЫК типа [>][= 0),
# constraint iOfferViews
# check (`iOfferViews` >= 0)
# );
# create index oknardia_priceoffer_dOfferModify_c562cfa5
# on oknardia_priceoffer (dOfferModify);
# create index oknardia_priceoffer_fOfferRating_a4af9121
# on oknardia_priceoffer (fOfferRating);
class PriceOffer(models.Model):
kOffer2MountDim = models.ForeignKey(
'Win_MountDim',
unique=False,
db_index=True,
on_delete=models.DO_NOTHING,
verbose_name="Проём",
help_text="Проём для которого установлена цена."
)
kOfferFromUser = models.ForeignKey(
'OurUser',
db_index=True,
on_delete=models.DO_NOTHING,
verbose_name="User",
help_text="Пользователь, который установил эту цену."
)
kOffer2SetKit = models.ForeignKey(
'SetKit',
default=1,
db_index=True,
on_delete=models.DO_NOTHING,
verbose_name="Набор",
help_text="Набор"
)
sOfferFlapConfig = models.CharField(
max_length=32,
verbose_name="Открывание",
help_text="Предлагаемая схема открывания (МЕТАЯЗЫК)"
)
fOfferPrice = models.DecimalField(
decimal_places=2,
max_digits=10,
default=0.,
verbose_name="Цена, ₽",
help_text="Цена установки окна, руб."
)
fOfferRating = models.FloatField(
default=0.,
db_index=True,
verbose_name="Рейтинг",
help_text="Поправка рейтинга (-0.5 … 0.5). Вычисляется исходя из соответствия предлагаемой схемы открывания"
)
iOfferImpressions = models.PositiveIntegerField(
default=0,
verbose_name="Показы",
help_text="Число показов."
)
iOfferViews = models.PositiveIntegerField(
default=0,
verbose_name="Просмотры",
help_text="Число просмотров."
)
sOfferActive = models.BooleanField(
# TODO: переименовать в bOfferActive
default=True,
verbose_name="Активно",
help_text="Отображать предложение (если \"вкл\") или нет (если \"выкл\")."
)
dOfferCreate = models.DateTimeField(
auto_now_add=True,
verbose_name="Создано"
)
dOfferModify = models.DateTimeField(
auto_now=True,
db_index=True,
verbose_name="Отредактировано"
)
def __unicode__(self):
return f"{self.id:04d}: {self.kOffer2SetKit} {self.sOfferFlapConfig} ({self.kOffer2MountDim})" \
f" = {float(self.fOfferPrice):.2f}₽ ►{self.kOfferFromUser}"
def __str__(self):
return self.__unicode__()
class Meta:
verbose_name = "Окно: цена"
verbose_name_plural = "Окна: цены"
ordering = ['-id']
# Таблица: Блог и каталог (унивекрсальная сущность -- какая-то публикация которые складываются во что угодно)
class BlogPosts(models.Model):
sPostHeader = models.CharField(
max_length=256,
verbose_name=u"Заголовок",
help_text=u"Заголовок поста или карточки каталога"
)
kBlogAuthorUser = models.ForeignKey(
'OurUser',
db_index=True,
default=1,
on_delete=models.DO_NOTHING,
verbose_name=u"Автор",
help_text=u"Автора поста в блог или записи в каталог."
)
sPostContent = models.TextField(
verbose_name=u"Содержание",
help_text=u"Содержание (допустим HTML)"
)
sImgForBlogSocial = models.ImageField(
max_length=128,
upload_to=PATH_FOR_IMG_BLOG,
default=u"",
blank=True,
verbose_name=u"IMG",
help_text=u"Способ загрузить картинку через админку Картинка-тизер для публикаций в соц.сетях. URL к картинке будет «/media/%s…» и этот URL можно использовать в HTML-тексте блога. Если нужно загрузить несколько картинок, то после сохранения промежуточной записи, откройте ее на редактирование еще раз и добавте новую картинку. Предыдущая картинка (и её URL) продолжат быть доступны.
ВАЖНО: ПРИ ПУБЛИКАЦИИ В СОЦ.СЕТЯХ БУДЕТ ОТОБРАЖАТЬЯ КАРТИНКА ЗАГРУЖЕННАЯ ПОСЛЕДНЕЙ.
ВАЖНО: ЕСЛИ ЗАГРУЖАЕМАЯ КАРТИНКА УЖЕ ИМЕЕТ ДУБЛИКАТ В СИСТЕМЕ, ЕЕ ИМЯ (И URL) БУДУТ ИЗМЕНЕНЫ. БУДЬТЕ ВНИМТЕЛЬНЫ!" % PATH_FOR_IMG_BLOG
)
bPublished = models.BooleanField(
default=True,
db_index=True,
help_text=u"Если отмечено, то пост доступен на сайте. Иначе ведет себя как удаленный и не «отзывается».",
verbose_name=u"Паблик"
)
bArchive = models.BooleanField(
default=False,
db_index=True,
help_text=u"Если отмечено, в архиве. Он не будет повляться в списке, но доступен через URL, поиск и пр.",
verbose_name=u"Архив"
)
dPostDataBegin = models.DateTimeField(
db_index=True,
default=datetime.now(),
help_text=u"Если установить будущую дату, то в назначеное время пост появится автоматически.",
verbose_name=u"Опубликован от"
)
bCatalog = models.BooleanField(
default=False,
db_index=True,
help_text=u"Это публикация для каталога (в блогах все равно будет доступно через URL, поиск и пр.)",
verbose_name=u"Каталог"
)
iCatalogSort = models.PositiveIntegerField(
db_index=True,
null=True,
default=1,
verbose_name=u"Сортер",
help_text=u"Число для сортировки и порядка вывода в каталогах (чем меьше, тем выше в списке)
"
u"Магические значения:
"
u" ■ %d — запись используется как рекламный тизер;
"
u" ■ %d — запись используется как обычный тизер."
u"" % (CATALOG_SORTER_MAGIC_NUMBER_ADV, CATALOG_SORTER_MAGIC_NUMBER_TIZER)
)
dPostDataModify = models.DateTimeField(
auto_now=True,
verbose_name=u"Отредактированно"
)
dPostDataCreate = models.DateTimeField(
auto_now_add=True,
db_index=False,
verbose_name=u"Создано"
)
sMetaDescription = models.CharField(
max_length=160,
blank=True,
default=u"",
verbose_name=u"Meta описание",
help_text=u"SEO: описание для мета-тега (до 160 символов). Если пусто, будет использоваться текст тизера из контента."
)
sMetaKeywords = models.CharField(
max_length=256,
blank=True,
default=u"",
verbose_name=u"Meta ключевые слова",
help_text=u"SEO: ключевые слова для мета-тега (до 256 символов). Если пусто, будет использоваться заголовок."
)
sSlug = models.SlugField(
max_length=200,
db_index=True,
blank=True,
verbose_name=u"Slug",
help_text=u"SEO: URL-friendly версия заголовка (автоматически генерируется, если оставить пусто)"
)
def __unicode__(self):
# return u'%s (%s)' % (self.sPostHeader, datetime.strftime(
# timezone.localtime(self.dPostDataCreate, timezone.get_current_timezone()), "%Y-%m-%d %H:%M"))
return f"{self.sPostHeader} ({self.dPostDataCreate.strftime('%Y-%m-%d %H:%M')})"
def __str__(self):
return self.__unicode__()
def save(self, *args, **kwargs):
"""Переопределённый метод save() для автоматической генерации слага и SEO-полей.
При сохранении записи блога:
- Генерируется sSlug из sPostHeader если тот пуст
- Генерируется sMetaDescription из текста контента (тизер)
- Генерируется sMetaKeywords из заголовка
"""
# Шаг 1: Автоматически генерируем слаг из заголовка, если он не указан
if not self.sSlug and self.sPostHeader:
self.sSlug = sanitize_slug(self.sPostHeader, max_length=200)
# Шаг 2: Автоматически генерируем sMetaDescription из контента (тизер)
if not self.sMetaDescription and self.sPostContent:
# Удаляем теги из контента
content_clean = re.sub(r'', '', self.sPostContent, flags=re.IGNORECASE)
# Генерируем тизер (очищенный текст без HTML)
tizer = safe_html_spec_symbols(content_clean)
# Обрезаем до 160 символов для мета-description
if len(tizer) > 160:
# Обрезаем слово целиком (не посередине)
tizer = tizer[:160].rsplit(' ', 1)[0] + '...' if ' ' in tizer[:160] else tizer[:160]
self.sMetaDescription = tizer
# Шаг 3: Автоматически генерируем sMetaKeywords из заголовка
if not self.sMetaKeywords and self.sPostHeader:
# Берём заголовок и удаляем HTML-теги
header_clean = safe_html_spec_symbols(self.sPostHeader)
header_clean = header_clean.strip()
# Генерируем ключевые слова: фиксированные + заголовок
fixed_keywords = u"oknardia, окнардия, блог, публикация"
self.sMetaKeywords = f"{fixed_keywords}, {header_clean}"[:256]
super().save(*args, **kwargs)
class Meta:
# db_table = "jtb_BlogPost"
verbose_name = u"Запись в блоге каталоге"
verbose_name_plural = u"Записи в блогах или каталогах"
ordering = ['-dPostDataCreate', 'iCatalogSort']
# Таблица: ЛОГИН-ПРОЛЬ и информация о пользователе
class OurUser(models.Model):
kDjangoUser = models.ForeignKey(
User,
on_delete=models.DO_NOTHING,
verbose_name=u"User",
help_text=u"Базовый пользователь"
)
sUserPhone = models.CharField(
max_length=32,
null=True,
blank=True,
default="",
verbose_name=u"Телефон",
help_text=u"Номер телефона пользователя"
)
sUserStatus = models.SmallIntegerField(
default=9,
choices=((1, u"Клиент, заказчик"),
(10, u"Представитель компании (офиса)"),
(50, u"Администратор бренда"),
(100, u"Администратор Окнардии")),
null=True,
blank=True,
help_text=u"Статус пользователя.",
verbose_name=u"Статаус"
)
kMerchantOffice = models.ForeignKey(
"MerchantOffice",
null=True,
blank=True,
default=None,
on_delete=models.SET_NULL,
verbose_name=u"Представитель",
help_text=u"Сотрудника какого офиса предтавляет этот логин."
)
sUserJobTitle = models.CharField(
max_length=64,
null=True,
blank=True,
default=None,
verbose_name=u"Должность",
help_text=u"Должность, в случае если данный логин является представителем компании."
)
sUserAvatarImg = models.ImageField(
max_length=128,
upload_to=PATH_FOR_IMG_AVATAR,
default=u"null.gif",
verbose_name=u"Avatar",
help_text=u"URL на картинку с аватаркой "
)
bUserSubscribe = models.BooleanField(
default=True,
verbose_name=u"Подписка",
help_text=u"Паользователь подписан на регулярную."
)
bUserWaitOffers = models.BooleanField(
default=True,
verbose_name=u"Ждет предложений",
help_text=u"Пользователь ждет коммерческих предложений."
)
sSocial = models.TextField(
max_length=1024,
null=True,
blank=True,
default=None,
verbose_name=u"Социальные ссылки",
help_text=u"Как это будет работать пока не ясно."
)
dUserDataModify = models.DateTimeField(
auto_now=True,
verbose_name=u"Отредактировано"
)
def __unicode__(self):
return f"{self.kDjangoUser} ({self.kMerchantOffice})"
def __str__(self):
return self.__unicode__()
class Meta:
verbose_name = u"Наш Пользователь"
verbose_name_plural = u"Наши Пользователи"
ordering = ['kDjangoUser']
# Таблица: Поставщики бренды.
class MerchantBrand(models.Model):
sMerchantName = models.CharField(
max_length=128,
unique=True,
null=False,
blank=False,
verbose_name=u"Название:",
help_text=u"Название головной компании (бренд). Например: «МОЁ ОКНО»"
)
sMerchantDescription = models.TextField(
blank=True,
null=True,
verbose_name=u"Описание",
help_text=u"Введите описание компании. Допускается HTML-разметка."
)
pMerchantLogo = models.ImageField(
max_length=255,
upload_to=PATH_FOR_IMG_LOGOS,
default="",
null=True,
blank=True,
help_text=u"Путь до картинки с логотипом",
verbose_name=u"Логотип"
)
sMerchantMainURL = models.URLField(
max_length=200,
verbose_name=u"URL",
help_text=u"URL сайта компании"
)
def __unicode__(self):
return self.sMerchantName
class Meta:
# db_table = "jtb_Merchant_Brand"
verbose_name = u"Поставщик: бренд"
verbose_name_plural = u"Поставщики: бренды"
ordering = ['sMerchantName']
# Таблица: Офисы поставщиков.
class MerchantOffice(models.Model):
sOfficeName = models.CharField(
max_length=128,
db_index=True,
unique=True,
null=False,
blank=False,
verbose_name=u"Название офиса",
help_text=u"Название компании и/или офиса. Например: «МОЁ ОКНО (головной оффис)»"
)
kMerchantName = models.ForeignKey(
'MerchantBrand',
null=True,
blank=True,
default=None,
on_delete=models.SET_NULL,
verbose_name=u"Бренд",
help_text=u"Маркой, бенд или франшиза под которой рабоатет офис."
)
sOfficeStatus = models.SmallIntegerField(
default=None,
choices=((1, "Головной офис"),
(2, "Региональный офис"),
(3, "Офис продаж"),
(4, "Представительство"),
(5, "Диллер"),
(6, "Франшиза"),
(7, "Агент")),
null=True,
blank=True,
help_text=u"Укажите статус офиса",
verbose_name=u"Статаус офиса"
)
kMerchantOfficeParent = models.ForeignKey(
'MerchantOffice',
null=True,
blank=True,
default=None,
on_delete=models.SET_NULL,
help_text=u"Укажите офис у которого настоящий офис находится в подчинении.",
verbose_name=u"Подчинен"
)
sOfficePhones = models.CharField(
max_length=128,
null=True,
blank=True,
default="",
verbose_name=u"Тел.",
help_text=u"Телефона офиса. Без пробелов, начинаются с +7. Например: «+7(495)123-12-34». Несколько телефонов записываются через запятую."
)
sOfficeEmails = models.CharField(
max_length=128,
null=True,
blank=True,
default="",
verbose_name=u"e-mail",
help_text=u"e-mail офиса. Несколько e-mail записываются через запятую."
)
sOfficeAddress = models.CharField(
max_length=255,
default='',
verbose_name=u"Адрес офиса",
help_text=u"Адрес офиса"
)
fOfficeGeoCode_Latitude = models.DecimalField(
max_digits=12,
decimal_places=8,
default=0.0,
null=True,
verbose_name=u"Широта",
help_text=u"Географическая щирота"
)
fOfficeGeoCode_Longitude = models.DecimalField(
max_digits=12,
decimal_places=8,
default=0.0,
null=True,
verbose_name=u"Долгота",
help_text=u"Географическая долгота"
)
sOfficeDescription = models.TextField(
max_length=4096,
null=True,
blank=True,
default=None,
verbose_name=u"Описание",
help_text=u"Краткое описание компании (офиса, подразделения). Максимум 4096 символов включая пробелы. HTML запрещен."
)
sOfficeDiscountMetaFormula = models.CharField(
max_length=255,
null=True,
blank=True,
default=None,
verbose_name=u"Формула скидки",
help_text=u"Формула предоставления скидок на мета-языке формул."
)
dOfficeDataCreate = models.DateTimeField(
auto_now_add=True,
verbose_name=u"Создано"
)
dOfficeDataModify = models.DateTimeField(
auto_now=True,
verbose_name=u"Отредактировано"
)
def __unicode__(self):
# return u"%03d: %s" % (self.id, self.sOfficeName)
return f"{self.id}: {self.sOfficeName}"
def __str__(self):
return self.__unicode__()
class Meta:
# db_table = "jtb_Merchant_Office"
verbose_name = u"Поставщик: офис"
verbose_name_plural = u"Поставщики: офисы"
ordering = ['sOfficeName']
#####################################################
#####################################################
# Таблица оконных проемов.
class Win_MountDim(models.Model):
iWinWidth = models.DecimalField(
max_digits=5,
decimal_places=1,
null=False,
verbose_name=u"Ширина",
help_text=u"Ширина, см."
)
iWinHight = models.DecimalField(
max_digits=5,
decimal_places=1,
null=False,
verbose_name=u"Высота",
help_text=u"Высота, см."
)
iWinDepth = models.DecimalField(
max_digits=3,
decimal_places=1,
null=False,
verbose_name=u"Глубина",
help_text=u"Глубина, см."
)
sFlapConfig = models.CharField(
max_length=32,
blank=True,
default=u"",
verbose_name=u"Открывание",
help_text=u"Рекомендуемая гор.архитектурой конфигурации открывания (МЕТАЯЗЫК)")
sDescripion = models.CharField(
max_length=64,
blank=True,
null=True,
verbose_name=u"Описание",
help_text=u"Описание для простоты последующего поиска и SEO"
)
bIsDoor = models.BooleanField(
default=False,
verbose_name=u"Дверь",
help_text=u"Это Дверь"
)
bIsNearDoor = models.BooleanField(
default=False,
verbose_name=u"Глухое",
help_text=u"Это окно рядом с дверью (может быть глухим)"
)
kApartment = models.ManyToManyField(
"Apartment_Type",
through="MountDim2Apartment",
# on_delete=models.CASCADE,
verbose_name=u"Квартира",
help_text=u"Принадлежность проема к типовой квартире"
)
iWinLimit = models.DecimalField(
max_digits=2,
decimal_places=1,
null=True,
default=5.0,
verbose_name=u"Допуск±",
help_text="Точность, допуск, предельные отклонения ширины и высоты, ±см."
)
dMountXYZDataCreate = models.DateTimeField(
auto_now_add=True,
verbose_name=u"Создано"
)
dMountXYZModify = models.DateTimeField(
auto_now=True,
verbose_name=u"Отредактировано"
)
def __unicode__(self):
return f"{self.id}: {self.sDescripion} ({self.iWinWidth}×{self.iWinHight}×{self.iWinDepth}) {self.sFlapConfig}"
def __str__(self):
return self.__unicode__()
class Meta:
verbose_name = u"Окно: проём и его конфигурация"
verbose_name_plural = u"Окна: проемы и их конфигурация"
ordering = ['id', 'iWinWidth', 'iWinHight']
#####################################################
#####################################################
# Таблица типов квартир.
class Apartment_Type(models.Model):
sNameApartment = models.CharField(
max_length=128,
verbose_name=u"Обозначение",
help_text=u"Название, наименование (отображается на кнопке в интерфейсе)"
)
sURL2IMG_Apartment = models.ImageField(
max_length=128,
upload_to=PATH_FOR_IMG_APARTMENT,
default=u"null.gif",
verbose_name=u"Изображение",
help_text=u"URL на картинку с планировкой "
)
iSort = models.IntegerField(
db_index=True,
null=True,
default=0,
verbose_name=u"Сортировка",
help_text=u"Число для сортировки и порядка вывода в списке"
)
sAreaXY = models.CharField(
max_length=256,
blank=True,
null=True,
default="",
verbose_name=u"MAP AREA",
help_text=u"строка AREA для описания MAP (для будущего использования)"
)
kSeria = models.ForeignKey(
"Seria_Info",
blank=True,
null=True,
default=None,
on_delete=models.SET_NULL,
verbose_name=u"В доме серии",
help_text=u"Данный тип квартиры принадлежит к серии дома"
)
kBuild = models.ForeignKey(
"Building_Info",
blank=True,
null=True,
default=None,
editable=False,
on_delete=models.SET_NULL,
verbose_name=u"Адрес",
help_text=u"Данный тип квартириы находится непоследственно к адресу (для индивидуальных проектов)"
)
bApartmentCheck = models.BooleanField(
default=False,
verbose_name=u"Проверено",
help_text=u"Данные добавлены админом, или проверены и подтверждены из нескольких источников"
)
dApartmentCreate = models.DateTimeField(
auto_now_add=True,
verbose_name=u"Создано"
)
dApartmentModify = models.DateTimeField(
auto_now=True,
verbose_name=u"Отредактировано"
)
def __unicode__(self):
return u"%5d: %s »» %s" % (self.id, self.sNameApartment, self.kSeria)
def __str__(self):
return u"%5d: %s »» %s" % (self.id, self.sNameApartment, self.kSeria)
class Meta:
verbose_name = u"Здание: тип квартиры"
verbose_name_plural = u"Здания: типы квартир"
# db_table = "jtb_ApartmentType"
ordering = ['-iSort', '-kSeria_id', 'id', 'sNameApartment']
# Таблица связи МНОГОЕ-КО-МНОГИМ: оконноые проемы ↔ типовые квартиры.
class MountDim2Apartment(models.Model):
kApartment = models.ForeignKey(
"Apartment_Type",
on_delete=models.DO_NOTHING,
verbose_name=u"Квартира",
help_text=u"Квартира"
)
kMountDim = models.ForeignKey(
"Win_MountDim",
on_delete=models.DO_NOTHING,
verbose_name=u"Оконный проём",
help_text=u"Параметры оконного/верного проема"
)
iQuantity = models.PositiveSmallIntegerField(
default=1,
verbose_name=u"Количество",
help_text=u"Количество окон/дверей данных габаритов в квартире"
)
def __unicode__(self):
# return u"%5d: %d × ▒%s ↔ %s▒" % (self.id, self.iQuantity, self.kApartment, self.kMountDim)
return f"{self.id:5d}: {self.iQuantity:2d} × ▒{self.kApartment} ↔ {self.kMountDim}▒"
def __str__(self):
return __unicode__(self)
class Meta:
verbose_name = u"Связка «проемы↔квартиры»"
verbose_name_plural = u"Связки «проемы↔квартиры»"
# db_table = "jtb_LinkMountXYZ2Apartment"
ordering = ['-kApartment_id', '-kMountDim_id']
#####################################################
#####################################################
# таблица серий зданий с построенными неследственными отношениями
class Seria_Info(models.Model):
sName = models.CharField(
max_length=128,
unique=True,
verbose_name=u"Серия дома",
help_text=u"Наименование серии дома."
)
sURL2IMG = models.ImageField(
max_length=128,
upload_to=PATH_FOR_IMG_SERIA,
default=u"null.gif",
verbose_name=u"Изображение",
help_text=u"Способ загрузить картинку через адмрн6ку Картинка-тизер для публикаций в соц.сетях. URL к картинке будет «/media/%s…» и этот URL можно использовать в HTML-тексте блога. Если нужно загрузить несколько картинок, то после сохранения промежуточной записи, откройте ее на редактирование еще раз и добавте новую картинку. Предыдущая картинка (и её URL) продолжат быть доступны.
ВАЖНО: ПРИ ПУБЛИКАЦИИ В СОЦ.СЕТЯХ БУДЕТ ОТОБРАЖАТЬЯ КАРТИНКА ЗАГРУЖЕННАЯ ПОСЛЕДНЕЙ.
ВАЖНО: ЕСЛИ ЗАГРУЖАЕМАЯ КАРТИНКА УЖЕ ИМЕЕТ ДУБЛИКАТ В СИСТЕМЕ, ЕЕ ИМЯ (И URL) БУДУТ ИЗМЕНЕНЫ. БУДЬТЕ ВНИМТЕЛЬНЫ!" % PATH_FOR_IMG_SERIA
)
kParent = models.ForeignKey(
'Seria_Info',
blank=True,
null=True,
default=None,
on_delete=models.SET_NULL,
verbose_name=u"Родительская серия",
help_text=u"Серия дома, которая является родительской для текущей."
)
kRoot = models.ForeignKey(
# поле необходимо для исключения рекурсивных запросов
'Seria_Info',
blank=True,
null=True,
default=None,
on_delete=models.SET_NULL,
related_name='kRootID',
verbose_name=u"Корневая серия",
help_text=u"Серия дома, которая является корневой для текущей."
)
sSeriaDescription = models.TextField(
# max_length=4096,
blank=True,
null=True,
default="",
verbose_name=u"Текст",
help_text=u"Тематическая статья, о настоящей серии дома"
)
dSeriaInfoCreate = models.DateTimeField(
auto_now_add=True,
verbose_name=u"Создано"
)
dSeriaInfoModify = models.DateTimeField(
auto_now=True,
verbose_name=u"Отредактировано"
)
def __unicode__(self):
# return u"%5d: %s → %s" % (self.id, self.sName, self.kParent)
return f"{self.id:5d}: {self.sName} → {self.kParent}"
def __str__(self):
if self.kParent_id is None:
return f"{self.id:5d}: {self.sName}"
return f"{self.id:5d}: {self.sName} → {self.kRoot}"
class Meta:
verbose_name = u"Здание: серия дома"
verbose_name_plural = u"Здания: серии домов"
# db_table = "jtb_SeriaInfo"
ordering = ['id', 'kParent_id',
'sName'] # назанчить ordering при ForeignKey просто так нельзя. Только через _id
#####################################################
#####################################################
# таблицв с развернутой информаией по зданиям. Спарсен!
class Building_Info(models.Model):
sAddress = models.CharField(
max_length=128,
unique=True,
db_index=True,
verbose_name=u"Адрес",
help_text=u"Адрес дома"
)
fGeoCode_Latitude = models.DecimalField(
max_digits=12,
decimal_places=8,
default=0.0,
null=True,
verbose_name=u"Широта",
help_text=u"Географическая щирота"
)
fGeoCode_Longitude = models.DecimalField(
max_digits=12,
decimal_places=8,
default=0.0,
null=True,
verbose_name=u"Долготоа",
help_text=u"Географическая долгота"
)
sSerias_Project = models.CharField( # 8####################################
max_length=128,
default=u"N/A",
null=True,
verbose_name=u"Серия1",
help_text=u"Серия, типовой проект здания (то как это записано в базе reformagkh.ru)."
)
kSeria_Link = models.ForeignKey(
"Seria_Info",
default=None,
blank=True,
null=True,
db_index=True,
on_delete=models.SET_NULL,
verbose_name=u"Серия2",
help_text=u"Серия, типовой проект здания в нашей базе"
)
sType = models.CharField( # 10#############################################
max_length=32,
default=u"N/A",
null=True,
verbose_name=u"Тип дома",
help_text=u"Тип жилого дома."
)
iCommissioning_year = models.CharField( # 5###############################
max_length=10,
default=u"N/A",
null=True,
verbose_name=u"Год",
help_text=u"Год ввода в эксплуатацию."
)
sWall = models.CharField( # 12#############################################
max_length=32,
default=u"N/A",
null=True,
verbose_name=u"Стены",
help_text=u"Материал стен."
)
sOverlap = models.CharField( # 13##########################################
max_length=32,
default=u"N/A",
null=True,
verbose_name=u"Перекрытия",
help_text=u"Тип перекрытий."
)
iStoreys = models.SmallIntegerField( # 14######################################################
default=-1,
null=True,
verbose_name=u"Этажей",
help_text=u"Число этажей."
)
iEntrances_Porchs = models.SmallIntegerField( # 15############################################
default=-1,
null=True,
verbose_name=u"Подъездов",
help_text=u"Число подъездов."
)
iElevators = models.SmallIntegerField( # 16####################################################
default=-1,
null=True,
verbose_name=u"Лифтов",
help_text=u"Число лифтов."
)
sEnergy_Efficiency = models.CharField( # 32#################################
max_length=4,
default=u"N/A",
null=True,
verbose_name=u"Энергоэффективность",
help_text=u"Класс энергоэффективности."
)
dEnergy_Audit = models.DateField( # 33######################################
default=date(2038, 1, 19),
null=True,
verbose_name=u"Дата аудита",
help_text=u"Дата проведения энергелического аудита."
)
# Total area, m2 //
fTotal_Area = models.DecimalField( # 1#17###################
max_digits=8,
decimal_places=2,
default=-1.0,
null=True,
verbose_name=u"Площадь м²",
help_text=u"Общаяя площадь помещений, м²."
)
fResidential_Area = models.DecimalField( # 2#18#############
max_digits=8,
decimal_places=2,
default=-1.0,
null=True,
verbose_name=u"Жилых м²",
help_text=u"Площадь жилых помещений, м²."
)
fUninhabited_Area = models.DecimalField( # 2#22#############
max_digits=8,
decimal_places=2,
default=-1.0,
null=True,
verbose_name=u"Нежилых м²",
help_text=u"Площадь нежилых помещений, м²."
)
fCommon_Area = models.DecimalField( # 3#####################
max_digits=8,
decimal_places=2,
default=-1.0,
null=True,
verbose_name=u"Обществ. м²",
help_text=u"Площадь помещений общего пользования (лестничные пролеты, подсобки и пр.), м²."
)
fPrivate_Area = models.DecimalField( # 19###################
max_digits=8,
decimal_places=2,
default=-1.0,
null=True,
verbose_name=u"Частные м²",
help_text=u"Площадь частных помещений (приватизированных), м²."
)
fMunicipal_Area = models.DecimalField( # 20#################
max_digits=8,
decimal_places=2,
default=-1.0,
null=True,
verbose_name=u"Муницип. м²",
help_text=u"Площадь мунициальных помещений (магазины, офисы и пр.), м²."
)
fGovernment_Area = models.DecimalField( # 21################
max_digits=8,
decimal_places=2,
default=-1.0,
null=True,
verbose_name=u"Гос., м²",
help_text=u"Площадь государственных помещений(не приватизированных), м²."
)
fLand_Area = models.DecimalField( # 23######################
max_digits=8,
decimal_places=2,
default=-1.0,
null=True,
verbose_name=u"Участок м²",
help_text=u"Площадь участка, м²."
)
fLocal_Area = models.DecimalField( # 24#####################
max_digits=8,
decimal_places=2,
default=-1.0,
null=True,
verbose_name=u"Придомовые м²",
help_text=u"Площадь придомовой территории, м²."
)
iNum_Apartments = models.SmallIntegerField( # 27##############################################
default=-1,
null=True,
verbose_name=u"Квартир",
help_text=u"Число квартир."
)
iNum_Residents = models.SmallIntegerField( # 28###############################################
default=-1,
null=True,
verbose_name=u"Жителей",
help_text=u"Число жителей."
)
iNum_Accounts = models.SmallIntegerField( # 29################################################
default=-1,
null=True,
verbose_name=u"Счетов",
help_text=u"Число счетов."
)
fCondition_House = models.DecimalField( # A0################
max_digits=5,
decimal_places=2,
default=-1.0,
null=True,
verbose_name=u"Износ",
help_text=u"Общая степень износа, %"
)
fCondition_Foundation = models.DecimalField( # A1###########
max_digits=5,
decimal_places=2,
default=-1.0,
null=True,
verbose_name=u"Износ_Ф",
help_text=u"Степень износа фундамента, %"
)
fCondition_Walls = models.DecimalField( # A2################
max_digits=5,
decimal_places=2,
default=-1.0,
null=True,
verbose_name=u"Износ_С",
help_text=u"Степень износа несущих стен, %"
)
fCondition_Overlap = models.DecimalField( # A3##############
max_digits=5,
decimal_places=2,
default=-1.0,
null=True,
verbose_name=u"Износ_П",
help_text=u"Степень износа перекрытий, %"
)
sCadastre_Num = models.CharField( # 4######################################
max_length=16,
default=u"N/A",
null=True,
verbose_name=u"№ кадастр",
help_text=u"Кадастровый номер"
)
sCadastre_Num_Area = models.CharField( # 26################################
max_length=16,
default=u"N/A",
null=True,
verbose_name=u"№ участка",
help_text=u"Кадастровый номер участка"
)
sInventory_Num = models.CharField( # 25####################################
max_length=16,
default=u"N/A"
, null=True,
verbose_name=u"№ инвентар",
help_text=u"Инвентарный номер"
)
sManagement_Co = models.CharField( # 7####################################
max_length=256,
default=u"N/A",
null=True,
verbose_name=u"УК ЖКХ",
help_text=u"Управляющая компани(ЖКХ)"
)
dStart_Privatization = models.DateField( # 34################################
default=date(2038, 1, 19),
null=True,
editable=False,
help_text=u"Дата начала приватизации.",
verbose_name=u"Дата приватизации"
)
sURL = models.CharField(
max_length=128,
unique=False,
db_index=False,
null=True,
editable=False,
help_text=u"URL для проверки и парсинга информации на http://www.reformagkh.ru/",
verbose_name=u"URL проверки"
)
sAddressPostIndex = models.CharField(
max_length=8,
null=True,
blank=True,
default='XXXXXX',
verbose_name=u"Индекс",
help_text=u"Почтовый индекс"
)
dBuildingInfoCreate = models.DateTimeField(
auto_now_add=True,
verbose_name=u"Создано"
)
dBuildingInfoModify = models.DateTimeField(
auto_now=True,
verbose_name=u"Отредактировано"
)
def __unicode__(self):
return f"{self.id:6d}: {self.sAddress} → [{self.sSerias_Project} ◄{self.kSeria_Link_id}►]"
def __str__(self):
return self.__unicode__()
class Meta:
verbose_name = u"Здание: адрес и описание дома"
verbose_name_plural = u"Здания: адреса и описания домов"
# db_table = "jtb_BuildingInfo"
ordering = ['sAddress']
#####################################################
#####################################################
# таблицв в который пишется циклический лог последних посещений страницы с ценовой выдачей
class LogVisitPriceReport(models.Model):
dLogVisitTime = models.DateTimeField(
auto_now=True,
# auto_now_add=True,
db_index=True,
verbose_name=u"Дата/время",
help_text=u"Дата и время визита"
)
sLogAddress = models.CharField( # в принциипе можно взять с Building_Info
max_length=128,
verbose_name=u"Адрес",
help_text=u"Адрес дома (на русском)"
)
sLogNameApartment = models.CharField( # в принциипе можно взять с Apartment_Type
max_length=128,
verbose_name=u"Обозначение",
help_text=u"Название, наименование (отображается на кнопке в интерфейсе)"
)
sLogURL = models.CharField( # по идее можно собирать из других полей…
max_length=250,
db_index=True,
verbose_name=u"URL",
help_text=u"URL"
)
def __unicode__(self):
return u"%.2f → %s" % (float(self.dLogVisitTime), self.sLogURL)
class Meta:
verbose_name = u"ЛОГ: Просмотры ценовой выдачи"
verbose_name_plural = u"ЛОГ: Просмотры ценовой выдачи"
# db_table = "jtb_BuildingInfo"
ordering = ['dLogVisitTime']