diff --git a/oknardia/oknardia/models.py b/oknardia/oknardia/models.py
new file mode 100644
index 0000000..e4c783f
--- /dev/null
+++ b/oknardia/oknardia/models.py
@@ -0,0 +1,1899 @@
+# -*- 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 *
+
+
+# Таблица: Каталог профилей, стеклопакетов (добавлено 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"Создано"
+ )
+
+ 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__()
+
+ 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,
+ 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']