From 7197dd69224789ac84ac3a627aa4ab7d0288ff51 Mon Sep 17 00:00:00 2001 From: erjemin Date: Sun, 30 Oct 2022 00:38:45 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BC=D0=BE=D0=B4=D0=B5=D0=BB=D0=B8=20=D1=80?= =?UTF-8?q?=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=D1=8E=D1=82,=20=D0=BD=D0=BE=20?= =?UTF-8?q?=D0=BD=D1=83=D0=B6=D0=BD=D0=BE=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D1=82=D1=8C=20=D0=BA=D0=BE=D0=BC=D0=BC=D0=B5=D0=BD=D1=82?= =?UTF-8?q?=D0=B0=D1=80=D0=B8=D0=B5=D0=B2=20=D0=B8=20=D0=BA=D1=80=D0=B0?= =?UTF-8?q?=D1=81=D0=BE=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- oknardia/oknardia/models.py | 1899 +++++++++++++++++++++++++++++++++++ 1 file changed, 1899 insertions(+) create mode 100644 oknardia/oknardia/models.py 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']