mod: raw SQL на ORM, убран макаронный код и исправлена пара ошибок в сравнениях характеристик.
This commit is contained in:
@@ -3,6 +3,8 @@
|
|||||||
from django.shortcuts import render, redirect
|
from django.shortcuts import render, redirect
|
||||||
from django.http import HttpRequest, HttpResponse
|
from django.http import HttpRequest, HttpResponse
|
||||||
from django.utils.dateformat import format
|
from django.utils.dateformat import format
|
||||||
|
from django.utils import timezone
|
||||||
|
from django.db.models import F, Q, ExpressionWrapper, BooleanField, Max, Count, Avg
|
||||||
from oknardia.models import LogVisitPriceReport, SetKit
|
from oknardia.models import LogVisitPriceReport, SetKit
|
||||||
from oknardia.settings import *
|
from oknardia.settings import *
|
||||||
from web.add_func import normalize, get_rating_set_for_stars, sum_through
|
from web.add_func import normalize, get_rating_set_for_stars, sum_through
|
||||||
@@ -13,6 +15,85 @@ import json
|
|||||||
import re
|
import re
|
||||||
import pytils
|
import pytils
|
||||||
|
|
||||||
|
# Сигнальные значения для поиска min/max: заведомо вне диапазона реальных данных
|
||||||
|
_INI_MAX = -100_000
|
||||||
|
_INI_MIN = 1_000_000
|
||||||
|
|
||||||
|
|
||||||
|
def _color_hi(value, val_min: float, val_max: float, threshold=None, epsilon: float = 0.001) -> str | None:
|
||||||
|
"""Цвет ячейки "чем больше, тем лучше": зеленее → значение ближе к max.
|
||||||
|
|
||||||
|
:param value: значение поля для текущей строки
|
||||||
|
:param val_min: минимум по всей выборке (из первого прогона)
|
||||||
|
:param val_max: максимум по всей выборке
|
||||||
|
:param threshold: нижний порог: значения <= threshold считаются "нет данных" и не окрашиваются
|
||||||
|
:param epsilon: минимальный разброс, при котором окраска имеет смысл
|
||||||
|
:return: hex-строка цвета или None
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
v = float(value)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
return None
|
||||||
|
if val_max == _INI_MAX or val_min == _INI_MIN or val_max - val_min < epsilon:
|
||||||
|
return None
|
||||||
|
if threshold is not None and v <= threshold:
|
||||||
|
return None
|
||||||
|
if v <= val_min:
|
||||||
|
return None
|
||||||
|
ratio = (v - val_min) / (val_max - val_min)
|
||||||
|
c = 255 - int(ratio * 128)
|
||||||
|
return f"#{c:02x}ff{c:02x}"
|
||||||
|
|
||||||
|
|
||||||
|
def _color_lo(value, val_min: float, val_max: float, threshold=None, epsilon: float = 0.001) -> str | None:
|
||||||
|
"""Цвет ячейки "чем меньше, тем лучше": зеленее → значение ближе к min.
|
||||||
|
|
||||||
|
:param value: значение поля для текущей строки
|
||||||
|
:param val_min: минимум по всей выборке
|
||||||
|
:param val_max: максимум по всей выборке
|
||||||
|
:param threshold: нижний порог: значения <= threshold не окрашиваются
|
||||||
|
:param epsilon: минимальный разброс
|
||||||
|
:return: hex-строка цвета или None
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
v = float(value)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
return None
|
||||||
|
if val_max == _INI_MAX or val_min == _INI_MIN or val_max - val_min < epsilon:
|
||||||
|
return None
|
||||||
|
if threshold is not None and v <= threshold:
|
||||||
|
return None
|
||||||
|
if v >= val_max:
|
||||||
|
return None
|
||||||
|
ratio = (v - val_min) / (val_max - val_min)
|
||||||
|
c = 127 + int(ratio * 128)
|
||||||
|
return f"#{c:02x}ff{c:02x}"
|
||||||
|
|
||||||
|
|
||||||
|
def _bounds(items: list, field: str, threshold=None) -> tuple[float, float]:
|
||||||
|
"""Вычисляет (min, max) значений поля field по списку items, игнорируя None и <= threshold.
|
||||||
|
|
||||||
|
:param items: список объектов (SetKit с аннотациями)
|
||||||
|
:param field: имя атрибута
|
||||||
|
:param threshold: значения <= threshold исключаются из выборки
|
||||||
|
:return: (min, max) или (_INI_MIN, _INI_MAX) если нет валидных значений
|
||||||
|
"""
|
||||||
|
vals = []
|
||||||
|
for item in items:
|
||||||
|
raw = getattr(item, field, None)
|
||||||
|
if raw is None:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
v = float(raw)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
continue
|
||||||
|
if threshold is not None and v <= threshold:
|
||||||
|
continue
|
||||||
|
vals.append(v)
|
||||||
|
if not vals:
|
||||||
|
return _INI_MIN, _INI_MAX
|
||||||
|
return min(vals), max(vals)
|
||||||
|
|
||||||
|
|
||||||
def get_last_user_visit_cookies(request: HttpRequest) -> list:
|
def get_last_user_visit_cookies(request: HttpRequest) -> list:
|
||||||
""" Служебная функция: проверяет есть ли куки о последних посещениях пользователя, и если есть возвращает их
|
""" Служебная функция: проверяет есть ли куки о последних посещениях пользователя, и если есть возвращает их
|
||||||
@@ -107,55 +188,57 @@ def compare_offers(request: HttpRequest, to_compare: str = "1,2") -> HttpRespons
|
|||||||
if to_compare != list_fine:
|
if to_compare != list_fine:
|
||||||
return redirect(f"/compare_offers/{list_fine}")
|
return redirect(f"/compare_offers/{list_fine}")
|
||||||
try:
|
try:
|
||||||
q_set_kit = SetKit.objects.raw(
|
q_set_kit = (
|
||||||
f"SELECT "
|
SetKit.objects
|
||||||
f"oknardia_setkit.id, oknardia_setkit.sSetName, oknardia_setkit.sSetDescription,"
|
.filter(id__in=list_fin)
|
||||||
f"oknardia_setkit.sSetClimateControl, oknardia_setkit.sSetSill, oknardia_setkit.sSetImplementAll,"
|
.annotate(
|
||||||
f"oknardia_setkit.sSetImplementHandles, oknardia_setkit.sSetImplementHinges,"
|
# Активность коммерческого предложения (аналог dSetCommercialUntil > NOW())
|
||||||
f"oknardia_setkit.sSetImplementLatch, oknardia_setkit.sSetImplementLimiter,"
|
bCommercial=ExpressionWrapper(
|
||||||
f"oknardia_setkit.sSetImplementCatch, oknardia_setkit.sSetPanes, oknardia_setkit.sSetSlope,"
|
Q(dSetCommercialUntil__gt=timezone.now()),
|
||||||
f"oknardia_setkit.sSetDelivery, oknardia_setkit.bSetDelivery, oknardia_setkit.sSetUninstallInstall,"
|
output_field=BooleanField()
|
||||||
f"oknardia_setkit.bSetUninstallInstall, oknardia_setkit.sSetOtherConditions,"
|
),
|
||||||
f"oknardia_setkit.fSetRating, oknardia_setkit.iSetNumEval, oknardia_setkit.iSetImpressions,"
|
# Алиасы из MerchantBrand (SetKit → OurUser → MerchantOffice → MerchantBrand)
|
||||||
f"oknardia_setkit.iSetViews, oknardia_setkit.sSetActive, oknardia_setkit.dSetModify,"
|
MERCHANT_ID=F('kSet2User__kMerchantOffice__kMerchantName'),
|
||||||
f"(oknardia_setkit.dSetCommercialUntil > NOW()) AS bCommercial,"
|
sMerchantName=F('kSet2User__kMerchantOffice__kMerchantName__sMerchantName'),
|
||||||
f"oknardia_glazing.sGlazingReflectionAndAbsorptionOfHeat, oknardia_glazing.sGlazingBriefDescription,"
|
sMerchantMainURL=F('kSet2User__kMerchantOffice__kMerchantName__sMerchantMainURL'),
|
||||||
f"oknardia_glazing.sGlazingDescription, oknardia_glazing.fGlazingSoundproofing,"
|
pMerchantLogo=F('kSet2User__kMerchantOffice__kMerchantName__pMerchantLogo'),
|
||||||
f"oknardia_glazing.fGlazingRating, oknardia_glazing.sGlazingMark,"
|
# Алиасы из PVCprofiles (SetKit → kSet2PVCprofiles)
|
||||||
f"oknardia_glazing.fGlazingHeatTransfer, oknardia_glazing.fGlazingLightTransmission,"
|
PROFILE_ID=F('kSet2PVCprofiles'),
|
||||||
f"oknardia_glazing.fGlazingPassingSun, oknardia_glazing.sGlazingLightReflectance,"
|
sProfileName=F('kSet2PVCprofiles__sProfileName'),
|
||||||
f"oknardia_glazing.sGlazingManufacturer, oknardia_glazing.iGlazingCamerasN,"
|
sProfileBriefDescription=F('kSet2PVCprofiles__sProfileBriefDescription'),
|
||||||
f"oknardia_glazing.sGlazingToning, oknardia_glazing.iGlazingThickness,"
|
sProfileManufacturer=F('kSet2PVCprofiles__sProfileManufacturer'),
|
||||||
f"oknardia_merchantoffice.dOfficeDataCreate, oknardia_merchantoffice.sOfficeName,"
|
sProfileColor=F('kSet2PVCprofiles__sProfileColor'),
|
||||||
f"oknardia_merchantoffice.sOfficeStatus, oknardia_merchantoffice.sOfficePhones,"
|
iProfileCameras=F('kSet2PVCprofiles__iProfileCameras'),
|
||||||
f"oknardia_merchantoffice.sOfficeEmails, oknardia_merchantoffice.sOfficeDescription,"
|
iProfileThickness=F('kSet2PVCprofiles__iProfileThickness'),
|
||||||
f"oknardia_merchantoffice.sOfficeDiscountMetaFormula, oknardia_merchantoffice.fOfficeGeoCode_Latitude,"
|
iProfileGlazingThickness=F('kSet2PVCprofiles__iProfileGlazingThickness'),
|
||||||
f"oknardia_merchantoffice.fOfficeGeoCode_Longitude, oknardia_merchantoffice.sOfficeAddress,"
|
fProfileHeatTransf=F('kSet2PVCprofiles__fProfileHeatTransf'),
|
||||||
f"oknardia_ouruser.sUserAvatarImg, oknardia_ouruser.sUserJobTitle, oknardia_ouruser.bUserSubscribe,"
|
fProfileSeals=F('kSet2PVCprofiles__fProfileSeals'),
|
||||||
f"oknardia_ouruser.sUserPhone, oknardia_ouruser.sUserStatus, oknardia_merchantbrand.id AS MERCHANT_ID,"
|
sProfileSealDescription=F('kSet2PVCprofiles__sProfileSealDescription'),
|
||||||
f"oknardia_merchantbrand.sMerchantMainURL, oknardia_merchantbrand.sMerchantName,"
|
fProfileSoundproofing=F('kSet2PVCprofiles__fProfileSoundproofing'),
|
||||||
f"oknardia_merchantbrand.pMerchantLogo, oknardia_pvcprofiles.id AS PROFILE_ID,"
|
iProfileHeight=F('kSet2PVCprofiles__iProfileHeight'),
|
||||||
f"oknardia_pvcprofiles.sProfileName, oknardia_pvcprofiles.sProfileBriefDescription,"
|
iProfileRabbet=F('kSet2PVCprofiles__iProfileRabbet'),
|
||||||
f"oknardia_pvcprofiles.sProfileReinforcement, oknardia_pvcprofiles.sProfileDescription,"
|
sProfileFillet=F('kSet2PVCprofiles__sProfileFillet'),
|
||||||
f"oknardia_pvcprofiles.fProfileHeatTransf, oknardia_pvcprofiles.sProfileSealDescription,"
|
sProfileReinforcement=F('kSet2PVCprofiles__sProfileReinforcement'),
|
||||||
f"oknardia_pvcprofiles.fProfileSeals, oknardia_pvcprofiles.fProfileSoundproofing,"
|
sProfileOther=F('kSet2PVCprofiles__sProfileOther'),
|
||||||
f"oknardia_pvcprofiles.iProfileCameras, oknardia_pvcprofiles.iProfileGlazingThickness,"
|
fProfileRating=F('kSet2PVCprofiles__fProfileRating'),
|
||||||
f"oknardia_pvcprofiles.iProfileHeight, oknardia_pvcprofiles.iProfileRabbet,"
|
sProfileDescription=F('kSet2PVCprofiles__sProfileDescription'),
|
||||||
f"oknardia_pvcprofiles.iProfileThickness, oknardia_pvcprofiles.sProfileColor,"
|
# Алиасы из Glazing (SetKit → kSet2Glazing)
|
||||||
f"oknardia_pvcprofiles.sProfileFillet, oknardia_pvcprofiles.sProfileManufacturer,"
|
iGlazingCamerasN=F('kSet2Glazing__iGlazingCamerasN'),
|
||||||
f"oknardia_pvcprofiles.sProfileOther, oknardia_pvcprofiles.fProfileRating "
|
iGlazingThickness=F('kSet2Glazing__iGlazingThickness'),
|
||||||
f"FROM oknardia_setkit"
|
sGlazingBriefDescription=F('kSet2Glazing__sGlazingBriefDescription'),
|
||||||
f" INNER JOIN oknardia_pvcprofiles"
|
sGlazingDescription=F('kSet2Glazing__sGlazingDescription'),
|
||||||
f" ON oknardia_setkit.kSet2PVCprofiles_id = oknardia_pvcprofiles.id"
|
sGlazingMark=F('kSet2Glazing__sGlazingMark'),
|
||||||
f" INNER JOIN oknardia_glazing"
|
sGlazingManufacturer=F('kSet2Glazing__sGlazingManufacturer'),
|
||||||
f" ON oknardia_setkit.kSet2Glazing_id = oknardia_glazing.id"
|
fGlazingHeatTransfer=F('kSet2Glazing__fGlazingHeatTransfer'),
|
||||||
f" INNER JOIN oknardia_ouruser"
|
fGlazingSoundproofing=F('kSet2Glazing__fGlazingSoundproofing'),
|
||||||
f" ON oknardia_setkit.kSet2User_id = oknardia_ouruser.id"
|
fGlazingLightTransmission=F('kSet2Glazing__fGlazingLightTransmission'),
|
||||||
f" INNER JOIN oknardia_merchantoffice"
|
sGlazingLightReflectance=F('kSet2Glazing__sGlazingLightReflectance'),
|
||||||
f" ON oknardia_ouruser.kMerchantOffice_id = oknardia_merchantoffice.id"
|
fGlazingPassingSun=F('kSet2Glazing__fGlazingPassingSun'),
|
||||||
f" INNER JOIN oknardia_merchantbrand"
|
sGlazingReflectionAndAbsorptionOfHeat=F('kSet2Glazing__sGlazingReflectionAndAbsorptionOfHeat'),
|
||||||
f" ON oknardia_merchantoffice.kMerchantName_id = oknardia_merchantbrand.id "
|
sGlazingToning=F('kSet2Glazing__sGlazingToning'),
|
||||||
f"WHERE oknardia_setkit.id IN ({to_compare})")
|
fGlazingRating=F('kSet2Glazing__fGlazingRating'),
|
||||||
|
)
|
||||||
|
)
|
||||||
except SetKit.DoesNotExist:
|
except SetKit.DoesNotExist:
|
||||||
return redirect("/compare_offers/1,2")
|
return redirect("/compare_offers/1,2")
|
||||||
list_set_kit = list(q_set_kit)
|
list_set_kit = list(q_set_kit)
|
||||||
@@ -166,356 +249,156 @@ def compare_offers(request: HttpRequest, to_compare: str = "1,2") -> HttpRespons
|
|||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
return render("/compare_offers/1,2")
|
return render("/compare_offers/1,2")
|
||||||
# ПРЕДВАРИТЕЛЬНЫЙ "ПРОГОН"
|
# ПРЕДВАРИТЕЛЬНЫЙ "ПРОГОН"
|
||||||
# Для того, чтобы "покрасить" ячейки таблицы сравнения в цвета, нужно для некоторых полей найти min и max...
|
# Вычисляем min/max по каждому параметру для дальнейшей покраски ячеек.
|
||||||
ini_max = -100000
|
# Камеры профиля требуют sum_through() — обрабатываем отдельно.
|
||||||
ini_min = 1000000
|
cameras_vals = [
|
||||||
max_i_profile_cameras = max_f_profile_seals = max_i_profile_thickness = max_i_profile_glazing_thickness = \
|
c for i in list_set_kit
|
||||||
max_f_profile_heat_transf = max_f_profile_soundproofing = max_i_profile_rabbet = max_i_profile_height = \
|
if (c := sum_through(i.iProfileCameras)) is not None and c > 0
|
||||||
max_i_glazing_cameras_n = max_i_glazing_thickness = max_f_glazing_heat_transfer = max_rating_set = \
|
]
|
||||||
max_f_glazing_soundproofing = max_f_glazing_light_transmission = max_f_glazing_passing_sun = ini_max
|
min_cameras = min(cameras_vals) if cameras_vals else _INI_MIN
|
||||||
min_i_profile_cameras = min_f_profile_seals = min_i_profile_thickness = min_i_profile_glazing_thickness = \
|
max_cameras = max(cameras_vals) if cameras_vals else _INI_MAX
|
||||||
min_f_profile_heat_transf = min_f_profile_soundproofing = min_i_profile_rabbet = min_i_profile_height = \
|
|
||||||
min_i_glazing_cameras_n = min_i_glazing_thickness = min_f_glazing_heat_transfer = min_rating_set = \
|
# Остальные поля — через _bounds() с соответствующими порогами
|
||||||
min_f_glazing_soundproofing = min_f_glazing_light_transmission = min_f_glazing_passing_sun = ini_min
|
# (threshold: значения <= порога считаются "нет данных" и исключаются из диапазона)
|
||||||
list_of_merchant_name = []
|
min_seals, max_seals = _bounds(list_set_kit, 'fProfileSeals', threshold=0)
|
||||||
list_of_profile_name = []
|
min_thick, max_thick = _bounds(list_set_kit, 'iProfileThickness', threshold=10)
|
||||||
list_of_glazing_brief_description = []
|
min_glaz_d, max_glaz_d = _bounds(list_set_kit, 'iProfileGlazingThickness', threshold=4)
|
||||||
for i in list_set_kit:
|
min_heat_p, max_heat_p = _bounds(list_set_kit, 'fProfileHeatTransf', threshold=0)
|
||||||
if i.sMerchantName not in list_of_merchant_name:
|
min_sound_p, max_sound_p = _bounds(list_set_kit, 'fProfileSoundproofing', threshold=0)
|
||||||
list_of_merchant_name.append(i.sMerchantName)
|
min_rabbet, max_rabbet = _bounds(list_set_kit, 'iProfileRabbet', threshold=1)
|
||||||
if i.sProfileName not in list_of_profile_name:
|
min_height, max_height = _bounds(list_set_kit, 'iProfileHeight', threshold=12)
|
||||||
list_of_profile_name.append(i.sProfileName)
|
min_gl_cam, max_gl_cam = _bounds(list_set_kit, 'iGlazingCamerasN', threshold=0)
|
||||||
if i.sGlazingMark not in list_of_glazing_brief_description:
|
min_gl_thick, max_gl_thick = _bounds(list_set_kit, 'iGlazingThickness', threshold=3)
|
||||||
list_of_glazing_brief_description.append(i.sGlazingMark)
|
min_heat_g, max_heat_g = _bounds(list_set_kit, 'fGlazingHeatTransfer', threshold=0.05)
|
||||||
profile_num_cameras = sum_through(i.iProfileCameras)
|
min_sound_g, max_sound_g = _bounds(list_set_kit, 'fGlazingSoundproofing', threshold=5)
|
||||||
if profile_num_cameras > 0: # Общее число камер профиля (рама+створка)
|
min_light, max_light = _bounds(list_set_kit, 'fGlazingLightTransmission', threshold=5)
|
||||||
if profile_num_cameras > max_i_profile_cameras:
|
min_sun, max_sun = _bounds(list_set_kit, 'fGlazingPassingSun', threshold=5)
|
||||||
max_i_profile_cameras = profile_num_cameras
|
min_rating, max_rating = _bounds(list_set_kit, 'fSetRating', threshold=0.05)
|
||||||
if profile_num_cameras < min_i_profile_cameras:
|
|
||||||
min_i_profile_cameras = profile_num_cameras
|
list_of_merchant_name = list({i.sMerchantName for i in list_set_kit})
|
||||||
if i.iProfileThickness > 0: # Контуров уплотнения
|
list_of_profile_name = list({i.sProfileName for i in list_set_kit})
|
||||||
if i.fProfileSeals > max_f_profile_seals:
|
list_of_glazing_brief = list({i.sGlazingMark for i in list_set_kit})
|
||||||
max_f_profile_seals = i.fProfileSeals
|
|
||||||
if i.fProfileSeals < min_f_profile_seals:
|
|
||||||
min_f_profile_seals = i.fProfileSeals
|
|
||||||
if i.iProfileThickness > 10: # Монтажная ширина профиля
|
|
||||||
if i.iProfileThickness > max_i_profile_thickness:
|
|
||||||
max_i_profile_thickness = i.iProfileThickness
|
|
||||||
if i.iProfileThickness < min_i_profile_thickness:
|
|
||||||
min_i_profile_thickness = i.iProfileThickness
|
|
||||||
if i.iProfileGlazingThickness > 4: # Максимальная толщина стеклопакета
|
|
||||||
if i.iProfileGlazingThickness > max_i_profile_glazing_thickness:
|
|
||||||
max_i_profile_glazing_thickness = i.iProfileGlazingThickness
|
|
||||||
if i.iProfileGlazingThickness < min_i_profile_glazing_thickness:
|
|
||||||
min_i_profile_glazing_thickness = i.iProfileGlazingThickness
|
|
||||||
if i.fProfileHeatTransf > 0: # Сопротивление теплопередаче
|
|
||||||
if i.fProfileHeatTransf > max_f_profile_heat_transf:
|
|
||||||
max_f_profile_heat_transf = i.fProfileHeatTransf
|
|
||||||
if i.fProfileHeatTransf < min_f_profile_heat_transf:
|
|
||||||
min_f_profile_heat_transf = i.fProfileHeatTransf
|
|
||||||
if i.fProfileSoundproofing > 0: # Коэффициент звукоизоляции
|
|
||||||
if i.fProfileSoundproofing > max_f_profile_soundproofing:
|
|
||||||
max_f_profile_soundproofing = i.fProfileSoundproofing
|
|
||||||
if i.fProfileSoundproofing < min_f_profile_soundproofing:
|
|
||||||
min_f_profile_soundproofing = i.fProfileSoundproofing
|
|
||||||
if i.iProfileRabbet > 1: # Фальц
|
|
||||||
if i.iProfileRabbet > max_i_profile_rabbet:
|
|
||||||
max_i_profile_rabbet = i.iProfileRabbet
|
|
||||||
if i.iProfileRabbet < min_i_profile_rabbet:
|
|
||||||
min_i_profile_rabbet = i.iProfileRabbet
|
|
||||||
if i.iProfileHeight > 12: # Высота в световом проеме
|
|
||||||
if i.iProfileHeight > max_i_profile_height:
|
|
||||||
max_i_profile_height = i.iProfileHeight
|
|
||||||
if i.iProfileHeight < min_i_profile_height:
|
|
||||||
min_i_profile_height = i.iProfileHeight
|
|
||||||
if i.iGlazingCamerasN > 0: # Камер стеклопакета
|
|
||||||
if i.iGlazingCamerasN > max_i_glazing_cameras_n:
|
|
||||||
max_i_glazing_cameras_n = i.iGlazingCamerasN
|
|
||||||
if i.iGlazingCamerasN < min_i_glazing_cameras_n:
|
|
||||||
min_i_glazing_cameras_n = i.iGlazingCamerasN
|
|
||||||
if i.iGlazingThickness > 4: # Толщина стеклопакета
|
|
||||||
if i.iGlazingThickness > max_i_glazing_thickness:
|
|
||||||
max_i_glazing_thickness = i.iGlazingThickness
|
|
||||||
if i.iGlazingThickness < min_i_glazing_thickness:
|
|
||||||
min_i_glazing_thickness = i.iGlazingThickness
|
|
||||||
if i.fGlazingHeatTransfer > 0.05: # Сопротивление теплопередаче стеклопакета Ro (м²×°C/Вт)
|
|
||||||
if i.fGlazingHeatTransfer > max_f_glazing_heat_transfer:
|
|
||||||
max_f_glazing_heat_transfer = i.fGlazingHeatTransfer
|
|
||||||
if i.fGlazingHeatTransfer < min_f_glazing_heat_transfer:
|
|
||||||
min_f_glazing_heat_transfer = i.fGlazingHeatTransfer
|
|
||||||
if i.fGlazingSoundproofing > 5: # Коэффициент звукоизоляции стеклопакета
|
|
||||||
if i.fGlazingSoundproofing > max_f_glazing_soundproofing:
|
|
||||||
max_f_glazing_soundproofing = i.fGlazingSoundproofing
|
|
||||||
if i.fGlazingSoundproofing < min_f_glazing_soundproofing:
|
|
||||||
min_f_glazing_soundproofing = i.fGlazingSoundproofing
|
|
||||||
if i.fGlazingLightTransmission > 5: # Коэффициент светопропускания стеклопакета
|
|
||||||
if i.fGlazingLightTransmission > max_f_glazing_light_transmission:
|
|
||||||
max_f_glazing_light_transmission = i.fGlazingLightTransmission
|
|
||||||
if i.fGlazingLightTransmission < min_f_glazing_light_transmission:
|
|
||||||
min_f_glazing_light_transmission = i.fGlazingLightTransmission
|
|
||||||
if i.fGlazingPassingSun > 5: # Коэффициент солнцепропускания стеклопакета
|
|
||||||
if i.fGlazingPassingSun > max_f_glazing_passing_sun:
|
|
||||||
max_f_glazing_passing_sun = i.fGlazingPassingSun
|
|
||||||
if i.fGlazingPassingSun < min_f_glazing_passing_sun:
|
|
||||||
min_f_glazing_passing_sun = i.fGlazingPassingSun
|
|
||||||
if i.fSetRating > 0.05: # Рейтинг НАБОРА!
|
|
||||||
if i.fSetRating > max_rating_set:
|
|
||||||
max_rating_set = i.fSetRating
|
|
||||||
if i.fSetRating < min_rating_set:
|
|
||||||
min_rating_set = i.fSetRating
|
|
||||||
# ОКОНЧАТЕЛЬНЫЙ ПРОГОН
|
# ОКОНЧАТЕЛЬНЫЙ ПРОГОН
|
||||||
# Передаём данные из SQL-запроса шаблон. Иногда надо вычислять цвета и прочее.
|
# Формируем список словарей для шаблона; цвета вычисляются через хелперы _color_hi / _color_lo.
|
||||||
# Много макаронного стиля кодинга, из-за того что иначе придется передавать в функции большие массивы QuerySet.
|
|
||||||
# А это жрет много памяти.
|
|
||||||
dim = []
|
dim = []
|
||||||
for i in list_set_kit:
|
for i in list_set_kit:
|
||||||
# построим массив "цветов" для рейтинга "Общее число камер профиля (рама+створка)" (чем больше, тем лучше)
|
|
||||||
profile_num_cameras = sum_through(i.iProfileCameras)
|
profile_num_cameras = sum_through(i.iProfileCameras)
|
||||||
if max_i_profile_cameras == ini_max or min_i_profile_cameras == ini_min or profile_num_cameras <= 1 \
|
|
||||||
or profile_num_cameras == min_i_profile_cameras or max_i_profile_cameras - min_i_profile_cameras < 0.001:
|
# Рейтинг НАБОРА — особая логика со "звёздочками"
|
||||||
profile_num_cameras_color = None
|
|
||||||
else:
|
|
||||||
color_ratio = (profile_num_cameras - min_i_profile_cameras) / (
|
|
||||||
max_i_profile_cameras - min_i_profile_cameras)
|
|
||||||
profile_num_cameras_color = f"#{255 - int(color_ratio * 128):02x}ff{255 - int(color_ratio * 128):02x}"
|
|
||||||
# построим массив "цветов" для рейтинга "Контуров уплотнения" (чем больше, тем лучше)
|
|
||||||
if max_f_profile_seals == ini_max or min_f_profile_seals == ini_min or i.fProfileSeals <= 0 \
|
|
||||||
or i.fProfileSeals == min_f_profile_seals or max_f_profile_seals - min_f_profile_seals < 0.001:
|
|
||||||
profile_seals_color = None
|
|
||||||
else:
|
|
||||||
color_ratio = (i.fProfileSeals - min_f_profile_seals) / (max_f_profile_seals - min_f_profile_seals)
|
|
||||||
profile_seals_color = f"#{255 - int(color_ratio * 128):02x}ff{255 - int(color_ratio * 128):02x}"
|
|
||||||
# построим массив "цветов" для рейтинга "Монтажная ширина профиля" (чем больше, тем лучше)
|
|
||||||
if max_i_profile_thickness == ini_max or min_i_profile_thickness == ini_min or i.iProfileThickness <= 10 \
|
|
||||||
or i.iProfileThickness == min_i_profile_thickness \
|
|
||||||
or max_i_profile_thickness - min_i_profile_thickness < 0.001:
|
|
||||||
profile_thickness_color = None
|
|
||||||
else:
|
|
||||||
color_ratio = (i.iProfileThickness - min_i_profile_thickness) / (max_i_profile_thickness
|
|
||||||
- min_i_profile_thickness)
|
|
||||||
profile_thickness_color = f"#{255 - int(color_ratio * 128):02x}ff{255 - int(color_ratio * 128):02x}"
|
|
||||||
# построим массив "цветов" для рейтинга "Максимальная толщина стеклопакета" (чем больше, тем лучше)
|
|
||||||
if max_i_profile_glazing_thickness == ini_max or min_i_profile_glazing_thickness == ini_min \
|
|
||||||
or i.iProfileGlazingThickness <= 4 or i.iProfileGlazingThickness == min_i_profile_glazing_thickness \
|
|
||||||
or max_i_profile_glazing_thickness - min_i_profile_glazing_thickness < 0.001:
|
|
||||||
profile_glazing_thickness_color = None
|
|
||||||
else:
|
|
||||||
color_ratio = (i.iProfileGlazingThickness
|
|
||||||
- min_i_profile_glazing_thickness) / (max_i_profile_glazing_thickness
|
|
||||||
- min_i_profile_glazing_thickness)
|
|
||||||
profile_glazing_thickness_color = f"#{255 - int(color_ratio * 128):02x}ff{255 - int(color_ratio * 128):02x}"
|
|
||||||
# построим массив "цветов" для рейтинга "Сопротивление теплопередаче" (чем больше, тем лучше)
|
|
||||||
if max_f_profile_heat_transf == ini_max or min_f_profile_heat_transf == ini_min \
|
|
||||||
or i.fProfileHeatTransf == min_f_profile_heat_transf \
|
|
||||||
or max_f_profile_heat_transf - min_f_profile_heat_transf < 0.001:
|
|
||||||
profile_heat_transf_color = None
|
|
||||||
else:
|
|
||||||
color_ratio = (i.fProfileHeatTransf - min_f_profile_heat_transf) / (max_f_profile_heat_transf
|
|
||||||
- min_f_profile_heat_transf)
|
|
||||||
profile_heat_transf_color = f"#{255 - int(color_ratio * 128):02x}ff{255 - int(color_ratio * 128):02x}"
|
|
||||||
# построим массив "цветов" для рейтинга "Коэффициент звукоизоляции" (чем больше, тем лучше)
|
|
||||||
if max_f_profile_soundproofing == ini_max or min_f_profile_soundproofing == ini_min \
|
|
||||||
or i.fProfileSoundproofing == min_f_profile_soundproofing \
|
|
||||||
or max_f_profile_soundproofing - min_f_profile_soundproofing < 0.001:
|
|
||||||
profile_soundproofing_color = None
|
|
||||||
else:
|
|
||||||
color_ratio = (i.fProfileSoundproofing - min_f_profile_soundproofing) / (max_f_profile_soundproofing
|
|
||||||
- min_f_profile_soundproofing)
|
|
||||||
profile_soundproofing_color = f"#{255 - int(color_ratio * 128):02x}ff{255 - int(color_ratio * 128):02x}"
|
|
||||||
# построим массив "цветов" для рейтинга "Фальц" (чем больше, тем лучше)
|
|
||||||
if max_i_profile_rabbet == ini_max or min_i_profile_rabbet == ini_min or i.iProfileRabbet <= 1 \
|
|
||||||
or i.iProfileRabbet == min_i_profile_rabbet or max_i_profile_rabbet - min_i_profile_rabbet < 0.001:
|
|
||||||
profile_rabbet_color = None
|
|
||||||
else:
|
|
||||||
color_ratio = (i.iProfileRabbet - min_i_profile_rabbet) / (max_i_profile_rabbet - min_i_profile_rabbet)
|
|
||||||
profile_rabbet_color = f"#{255 - int(color_ratio * 128):02x}ff{255 - int(color_ratio * 128):02x}"
|
|
||||||
# построим массив "цветов" для рейтинга "Высота в световом проеме" (чем меньше, тем лучше)
|
|
||||||
if max_i_profile_rabbet == ini_max or min_i_profile_height == ini_min or i.iProfileHeight <= 12 \
|
|
||||||
or i.iProfileHeight == max_i_profile_height or max_i_profile_height - min_i_profile_height < 0.01:
|
|
||||||
profile_height_color = None
|
|
||||||
else:
|
|
||||||
color_ratio = (i.iProfileHeight - min_i_profile_height) / (max_i_profile_height - min_i_profile_height)
|
|
||||||
profile_height_color = f"#{127 + int(color_ratio * 128):02x}ff{127 + int(color_ratio * 128):02x}"
|
|
||||||
# построим массив "цветов" для рейтинга "Камер стеклопакета" (чем больше, тем лучше)
|
|
||||||
if max_i_glazing_cameras_n == ini_max or min_i_profile_height == ini_min \
|
|
||||||
or i.iGlazingCamerasN == min_i_glazing_cameras_n \
|
|
||||||
or max_i_glazing_cameras_n - min_i_glazing_cameras_n < 0.001:
|
|
||||||
glazing_cameras_n_color = None
|
|
||||||
else:
|
|
||||||
color_ratio = (i.iGlazingCamerasN - min_i_glazing_cameras_n) / (max_i_glazing_cameras_n
|
|
||||||
- min_i_glazing_cameras_n)
|
|
||||||
glazing_cameras_n_color = f"#{255 - int(color_ratio * 128):02x}ff{255 - int(color_ratio * 128):02x}"
|
|
||||||
# построим массив "цветов" для рейтинга "Толщина стеклопакета" (чем больше, тем лучше)
|
|
||||||
if max_i_glazing_thickness == ini_max or min_i_glazing_thickness == ini_min or i.iGlazingThickness <= 3 \
|
|
||||||
or i.iGlazingThickness == min_i_glazing_thickness \
|
|
||||||
or max_i_glazing_thickness - min_i_glazing_thickness < 0.001:
|
|
||||||
glazing_thickness_color = None
|
|
||||||
else:
|
|
||||||
color_ratio = (i.iGlazingThickness - min_i_glazing_thickness) / (max_i_glazing_thickness
|
|
||||||
- min_i_glazing_thickness)
|
|
||||||
glazing_thickness_color = f"#{255 - int(color_ratio * 128):02x}ff{255 - int(color_ratio * 128):02x}"
|
|
||||||
# построим массив "цветов" для рейтинга "Сопротивление теплопередаче стеклопакета" (чем больше, тем лучше)
|
|
||||||
if max_f_glazing_heat_transfer == ini_max or min_f_glazing_heat_transfer == ini_min \
|
|
||||||
or i.fGlazingHeatTransfer <= 0.05 or i.fGlazingHeatTransfer == min_f_glazing_heat_transfer \
|
|
||||||
or max_f_glazing_heat_transfer - min_f_glazing_heat_transfer < 0.001:
|
|
||||||
glazing_heat_transfer_color = None
|
|
||||||
else:
|
|
||||||
color_ratio = (i.fGlazingHeatTransfer - min_f_glazing_heat_transfer) / (max_f_glazing_heat_transfer
|
|
||||||
- min_f_glazing_heat_transfer)
|
|
||||||
glazing_heat_transfer_color = f"#{255 - int(color_ratio * 128):02x}ff{255 - int(color_ratio * 128):02x}"
|
|
||||||
# построим массив "цветов" для рейтинга "Коэффициент звукоизоляции стеклопакета" (чем больше, тем лучше)
|
|
||||||
if max_f_glazing_soundproofing == ini_max or min_f_glazing_soundproofing == ini_min \
|
|
||||||
or i.fGlazingSoundproofing <= 5 or i.fGlazingSoundproofing == min_f_glazing_heat_transfer \
|
|
||||||
or max_f_glazing_soundproofing - min_f_glazing_soundproofing < 0.001:
|
|
||||||
glazing_soundproofing_color = None
|
|
||||||
else:
|
|
||||||
color_ratio = (i.fGlazingSoundproofing - min_f_glazing_soundproofing) / (max_f_glazing_soundproofing
|
|
||||||
- min_f_glazing_soundproofing)
|
|
||||||
glazing_soundproofing_color = f"#{255 - int(color_ratio * 128):02x}ff{255 - int(color_ratio * 128):02x}"
|
|
||||||
# построим массив "цветов" для рейтинга "Коэффициент светопропускания стеклопакета" (чем больше, тем лучше)
|
|
||||||
if max_f_glazing_light_transmission == ini_max or min_f_glazing_light_transmission == ini_min \
|
|
||||||
or i.fGlazingLightTransmission <= 5 or i.fGlazingLightTransmission == min_f_glazing_light_transmission \
|
|
||||||
or max_f_glazing_light_transmission - min_f_glazing_light_transmission < 0.002:
|
|
||||||
glazing_light_transmission_color = None
|
|
||||||
else:
|
|
||||||
color_ratio = (i.fGlazingLightTransmission
|
|
||||||
- min_f_glazing_light_transmission) / (max_f_glazing_light_transmission
|
|
||||||
- min_f_glazing_light_transmission)
|
|
||||||
glazing_light_transmission_color = f"#{255 - int(color_ratio * 128):02x}ff{255 - int(color_ratio * 128):02x}"
|
|
||||||
# построим массив "цветов" для рейтинга "Коэффициент солнцепропускания стеклопакета" (чем меньше, тем лучше)
|
|
||||||
if max_f_glazing_passing_sun == ini_max or min_f_glazing_passing_sun == ini_min or i.fGlazingPassingSun <= 5 \
|
|
||||||
or i.fGlazingPassingSun == max_f_glazing_passing_sun \
|
|
||||||
or max_f_glazing_passing_sun - min_f_glazing_passing_sun < 0.0001:
|
|
||||||
glazing_passing_sun_color = None
|
|
||||||
else:
|
|
||||||
color_ratio = (i.fGlazingPassingSun - min_f_glazing_passing_sun) / (max_f_glazing_passing_sun
|
|
||||||
- min_f_glazing_passing_sun)
|
|
||||||
glazing_passing_sun_color = f"#{127 + int(color_ratio * 128):02x}ff{127 + int(color_ratio * 128):02x}"
|
|
||||||
########################################################################
|
|
||||||
# построим массив цветов "звездочек" для рейтинга наборов
|
|
||||||
if i.fSetRating > RARING_SET_MAX:
|
if i.fSetRating > RARING_SET_MAX:
|
||||||
rating_set_n = RARING_SET_MAX
|
rating_set_n = RARING_SET_MAX
|
||||||
rating_set_color = "#80ff80"
|
rating_set_color = "#80ff80"
|
||||||
elif i.fSetRating < RARING_SET_MIN + 0.05 or max_rating_set - min_rating_set < 0.001:
|
elif i.fSetRating < RARING_SET_MIN + 0.05 or max_rating - min_rating < 0.001:
|
||||||
rating_set_n = RARING_SET_MIN
|
rating_set_n = RARING_SET_MIN
|
||||||
rating_set_color = ""
|
rating_set_color = ""
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
rating_set_n = i.fSetRating * (RARING_SET_MAX - RARING_SET_MIN) / RARING_STAR
|
rating_set_n = i.fSetRating * (RARING_SET_MAX - RARING_SET_MIN) / RARING_STAR
|
||||||
color_ratio = (i.fSetRating - min_rating_set) / (max_rating_set - min_rating_set)
|
rating_set_color = _color_hi(i.fSetRating, min_rating, max_rating)
|
||||||
rating_set_color = f"#{255 - int(color_ratio * 128):02x}ff{255 - int(color_ratio * 128):02x}"
|
|
||||||
except (ZeroDivisionError, TypeError):
|
except (ZeroDivisionError, TypeError):
|
||||||
rating_set_color = None
|
rating_set_color = None
|
||||||
rating_set_n = RARING_SET_MIN
|
rating_set_n = RARING_SET_MIN
|
||||||
# print RatingSet
|
|
||||||
list2_del = f",{to_compare},"
|
list2_del = f",{to_compare},"
|
||||||
dim.append({
|
dim.append({
|
||||||
"MERCHANT": i.sMerchantName,
|
"MERCHANT": i.sMerchantName,
|
||||||
"MERCHANT_ID": i.MERCHANT_ID,
|
"MERCHANT_ID": i.MERCHANT_ID,
|
||||||
"IS_COMMERCIAL": i.bCommercial,
|
"IS_COMMERCIAL": i.bCommercial,
|
||||||
"MERCHANT_T": pytils.translit.slugify(i.sMerchantName),
|
"MERCHANT_T": pytils.translit.slugify(i.sMerchantName),
|
||||||
'MERCHANT_URL': i.sMerchantMainURL,
|
"MERCHANT_URL": i.sMerchantMainURL,
|
||||||
'MERCHANT_URL_SHOT': re.sub("(?:^http://|^https://|/$|www\.)", "", i.sMerchantMainURL),
|
"MERCHANT_URL_SHOT": re.sub(r"(?:^https?://|/$|www\.)", "", i.sMerchantMainURL),
|
||||||
"SET_NAME": i.sSetName,
|
"SET_NAME": i.sSetName,
|
||||||
"MERCHANT_LOGO": i.pMerchantLogo,
|
"MERCHANT_LOGO": i.pMerchantLogo,
|
||||||
"RATING_SET": get_rating_set_for_stars(i.fSetRating),
|
"RATING_SET": get_rating_set_for_stars(i.fSetRating),
|
||||||
"RATING_SET_N": rating_set_n,
|
"RATING_SET_N": rating_set_n,
|
||||||
"RATING_SET_COLOR": rating_set_color,
|
"RATING_SET_COLOR": rating_set_color,
|
||||||
"PROFILE_ID": i.PROFILE_ID,
|
"PROFILE_ID": i.PROFILE_ID,
|
||||||
"PROFILE_NAME": i.sProfileName,
|
"PROFILE_NAME": i.sProfileName,
|
||||||
"PROFILE_NAME_T": pytils.translit.slugify(i.sProfileName),
|
"PROFILE_NAME_T": pytils.translit.slugify(i.sProfileName),
|
||||||
"PROFILE_MANUFACTURER": i.sProfileManufacturer,
|
"PROFILE_MANUFACTURER": i.sProfileManufacturer,
|
||||||
"PROFILE_MANUFACTURER_T": pytils.translit.slugify(i.sProfileManufacturer),
|
"PROFILE_MANUFACTURER_T": pytils.translit.slugify(i.sProfileManufacturer),
|
||||||
"PROFILE_NUM_COLOR": i.sProfileColor,
|
"PROFILE_NUM_COLOR": i.sProfileColor,
|
||||||
"PROFILE_NUM_CAMERAS": i.iProfileCameras, # Число камер рамы/створки
|
"PROFILE_NUM_CAMERAS": i.iProfileCameras, # Число камер рамы/створки
|
||||||
"PROFILE_NUM_CAMERAS_COLOR": profile_num_cameras_color, # Число камер рамы/створки ЦВЕТА
|
"PROFILE_NUM_CAMERAS_COLOR": _color_hi(profile_num_cameras, min_cameras, max_cameras, threshold=1),
|
||||||
"PROFILE_THICKNESS": i.iProfileThickness, # Монтажная ширина профиля
|
"PROFILE_THICKNESS": i.iProfileThickness, # Монтажная ширина профиля
|
||||||
"PROFILE_THICKNESS_COLOR": profile_thickness_color, # Окраска Монтажная ширина профиля ЦВЕТА
|
"PROFILE_THICKNESS_COLOR": _color_hi(i.iProfileThickness, min_thick, max_thick, threshold=10),
|
||||||
"PROFILE_GLAZING_THICKNESS": i.iProfileGlazingThickness, # Максимальная толщина стеклопакета
|
"PROFILE_GLAZING_THICKNESS": i.iProfileGlazingThickness, # Макс. толщина стеклопакета
|
||||||
"PROFILE_GLAZING_THICKNESS_COLOR": profile_glazing_thickness_color, # Макс-толщина стеклопакета ЦВЕТА
|
"PROFILE_GLAZING_THICKNESS_COLOR": _color_hi(i.iProfileGlazingThickness, min_glaz_d, max_glaz_d, threshold=4),
|
||||||
"PROFILE_HEAT_TRANSFER": i.fProfileHeatTransf, # Сопротивление теплопередаче
|
"PROFILE_HEAT_TRANSFER": i.fProfileHeatTransf, # Сопротивление теплопередаче
|
||||||
"PROFILE_HEAT_TRANSFER_COLOR": profile_heat_transf_color, # Сопротивление теплопередаче ЦВЕТА
|
"PROFILE_HEAT_TRANSFER_COLOR": _color_hi(i.fProfileHeatTransf, min_heat_p, max_heat_p),
|
||||||
"PROFILE_NUM_SEALS": i.fProfileSeals, # Контуров уплотнения
|
"PROFILE_NUM_SEALS": i.fProfileSeals, # Контуров уплотнения
|
||||||
"PROFILE_NUM_SEALS_COLOR": profile_seals_color, # Контуров уплотнения ЦВЕТА
|
"PROFILE_NUM_SEALS_COLOR": _color_hi(i.fProfileSeals, min_seals, max_seals, threshold=0),
|
||||||
"PROFILE_SEAL_DESCRIPTION": i.sProfileSealDescription,
|
"PROFILE_SEAL_DESCRIPTION": i.sProfileSealDescription,
|
||||||
"PROFILE_SOUND_PROOFING": i.fProfileSoundproofing, # Коэффициент звукоизоляции
|
"PROFILE_SOUND_PROOFING": i.fProfileSoundproofing, # Коэффициент звукоизоляции профиля
|
||||||
"PROFILE_SOUND_PROOFING_COLOR": profile_soundproofing_color, # Коэффициент звукоизоляции ЦВЕТА
|
"PROFILE_SOUND_PROOFING_COLOR": _color_hi(i.fProfileSoundproofing, min_sound_p, max_sound_p),
|
||||||
"PROFILE_HEIGHT": i.iProfileHeight, # Высота в световом проеме
|
"PROFILE_HEIGHT": i.iProfileHeight, # Высота в световом проеме (меньше = лучше)
|
||||||
"PROFILE_HEIGHT_COLOR": profile_height_color, # Высота в световом проеме ЦВЕТА
|
"PROFILE_HEIGHT_COLOR": _color_lo(i.iProfileHeight, min_height, max_height, threshold=12),
|
||||||
"PROFILE_RABBET": i.iProfileRabbet, # Фальц
|
"PROFILE_RABBET": i.iProfileRabbet, # Фальц
|
||||||
"PROFILE_RABBET_COLOR": profile_rabbet_color, # Фальц ЦВЕТА
|
"PROFILE_RABBET_COLOR": _color_hi(i.iProfileRabbet, min_rabbet, max_rabbet, threshold=1),
|
||||||
"PROFILE_FILLET": i.sProfileFillet, # Штапик
|
"PROFILE_FILLET": i.sProfileFillet, # Штапик
|
||||||
"PROFILE_REINFORCEMENT": i.sProfileReinforcement, # Армирование профиля
|
"PROFILE_REINFORCEMENT": i.sProfileReinforcement, # Армирование профиля
|
||||||
"PROFILE_OTHER": i.sProfileOther,
|
"PROFILE_OTHER": i.sProfileOther,
|
||||||
"SET_ID": i.id, # id-набора
|
"SET_ID": i.id,
|
||||||
"SET_CLIMATE_CONTROL": i.sSetClimateControl, # климат контроль
|
"SET_CLIMATE_CONTROL": i.sSetClimateControl,
|
||||||
"SET_STILL": i.sSetSill, # Подоконник
|
"SET_STILL": i.sSetSill,
|
||||||
"SET_IMPLEMENTS_ALL": i.sSetImplementAll, # Фурнитура
|
"SET_IMPLEMENTS_ALL": i.sSetImplementAll,
|
||||||
"SET_IMPLEMENTS_HANDLES": i.sSetImplementHandles, # Фурнитура: Ручки
|
"SET_IMPLEMENTS_HANDLES": i.sSetImplementHandles,
|
||||||
"SET_IMPLEMENTS_HINGES": i.sSetImplementHinges, # Фурнитура: Петли
|
"SET_IMPLEMENTS_HINGES": i.sSetImplementHinges,
|
||||||
"SET_IMPLEMENTS_LATCH": i.sSetImplementLatch, # Фурнитура: механизма запирания (запор)
|
"SET_IMPLEMENTS_LATCH": i.sSetImplementLatch,
|
||||||
"SET_IMPLEMENTS_LIMITER": i.sSetImplementLimiter, # Фурнитура: Ограничитель
|
"SET_IMPLEMENTS_LIMITER": i.sSetImplementLimiter,
|
||||||
"SET_IMPLEMENTS_CATCH": i.sSetImplementCatch, # Фурнитура: Фиксаторы открывания
|
"SET_IMPLEMENTS_CATCH": i.sSetImplementCatch,
|
||||||
"SET_PANES": i.sSetPanes, # Водоотлив
|
"SET_PANES": i.sSetPanes,
|
||||||
"SET_SLOPE": i.sSetSlope, # Откос
|
"SET_SLOPE": i.sSetSlope,
|
||||||
"SET_DELIVERY": i.sSetDelivery, # Доставка (условия
|
"SET_DELIVERY": i.sSetDelivery,
|
||||||
"SET_DELIVERY_B": i.bSetDelivery, # Доставка (да/нет)
|
"SET_DELIVERY_B": i.bSetDelivery,
|
||||||
"SET_UNINSTALL_INSTALL": i.sSetUninstallInstall, # Монтаж/демонтаж (условия)
|
"SET_UNINSTALL_INSTALL": i.sSetUninstallInstall,
|
||||||
"SET_UNINSTALL_INSTALL_B": i.bSetUninstallInstall, # Монтаж/демонтаж (да/нет)
|
"SET_UNINSTALL_INSTALL_B": i.bSetUninstallInstall,
|
||||||
"SET_OTHER_CONDITIONS": i.sSetOtherConditions, # Прочие условия
|
"SET_OTHER_CONDITIONS": i.sSetOtherConditions,
|
||||||
"GLAZING_CAMERAS_NUM": i.iGlazingCamerasN, # Камер стеклопакета
|
"GLAZING_CAMERAS_NUM": i.iGlazingCamerasN, # Камер стеклопакета
|
||||||
"GLAZING_CAMERAS_COLOR": glazing_cameras_n_color, # Камер стеклопакета ЦВЕТА
|
"GLAZING_CAMERAS_COLOR": _color_hi(i.iGlazingCamerasN, min_gl_cam, max_gl_cam),
|
||||||
"GLAZING_THICKNESS": i.iGlazingThickness, # Толщина стеклопакета
|
"GLAZING_THICKNESS": i.iGlazingThickness, # Толщина стеклопакета
|
||||||
"GLAZING_THICKNESS_COLOR": glazing_thickness_color, # Толщина стеклопакета
|
"GLAZING_THICKNESS_COLOR": _color_hi(i.iGlazingThickness, min_gl_thick, max_gl_thick, threshold=3),
|
||||||
"GLAZING_BRIEF_DESCRIPTION": re.sub(u",[\s\d]+мм", "", i.sGlazingBriefDescription), # Кратко о стеклопакете
|
"GLAZING_BRIEF_DESCRIPTION": re.sub(r",[\s\d]+мм", "", i.sGlazingBriefDescription),
|
||||||
"GLAZING_MARK": i.sGlazingMark, # Схема, марка, маркировка, модель стеклопакета
|
"GLAZING_MARK": i.sGlazingMark,
|
||||||
"GLAZING_MANUFACTURER": i.sGlazingManufacturer, # Производитель стеклопакета
|
"GLAZING_MANUFACTURER": i.sGlazingManufacturer,
|
||||||
"GLAZING_HEAT_TRANSFER": i.fGlazingHeatTransfer, # Сопротивление теплопередаче стеклопакета Ro (м²×°C/Вт)
|
"GLAZING_HEAT_TRANSFER": i.fGlazingHeatTransfer, # Ro стеклопакета (м²×°C/Вт)
|
||||||
"GLAZING_HEAT_TRANSFER_COLOR": glazing_heat_transfer_color, # Сопротивление теплопередаче стеклопакета ЦВЕТ
|
"GLAZING_HEAT_TRANSFER_COLOR": _color_hi(i.fGlazingHeatTransfer, min_heat_g, max_heat_g, threshold=0.05),
|
||||||
"GLAZING_SOUNDPROOFING": i.fGlazingSoundproofing, # Коэффициент звукоизоляции стеклопакета
|
"GLAZING_SOUNDPROOFING": i.fGlazingSoundproofing, # Звукоизоляция стеклопакета
|
||||||
"GLAZING_SOUNDPROOFING_COLOR": glazing_soundproofing_color, # Коэффициент звукоизоляции стеклопакета ЦВЕТА
|
"GLAZING_SOUNDPROOFING_COLOR": _color_hi(i.fGlazingSoundproofing, min_sound_g, max_sound_g, threshold=5),
|
||||||
"GLAZING_LIGHT_TRANSMISSION": i.fGlazingLightTransmission, # Коэффициент светопропускания стеклопакета
|
"GLAZING_LIGHT_TRANSMISSION": i.fGlazingLightTransmission,
|
||||||
"GLAZING_LIGHT_TRANSMISSION_COLOR": glazing_light_transmission_color, # Коэффициент светопропускания ЦВЕТА
|
"GLAZING_LIGHT_TRANSMISSION_COLOR": _color_hi(i.fGlazingLightTransmission, min_light, max_light, threshold=5, epsilon=0.002),
|
||||||
"GLAZING_LIGHT_REFLECTION": i.sGlazingLightReflectance, # Коэффициент светоотражения внешний/внутренний
|
"GLAZING_LIGHT_REFLECTION": i.sGlazingLightReflectance,
|
||||||
"GLAZING_PASSING_SUN": i.fGlazingPassingSun, # Коэффициент солнцепропускания стеклопакета
|
"GLAZING_PASSING_SUN": i.fGlazingPassingSun, # Солнцепропускание (меньше = лучше)
|
||||||
"GLAZING_PASSING_SUN_COLOR": glazing_passing_sun_color, # Коэффициент солнцепропускания ЦВЕТ
|
"GLAZING_PASSING_SUN_COLOR": _color_lo(i.fGlazingPassingSun, min_sun, max_sun, threshold=5, epsilon=0.0001),
|
||||||
"GLAZING_REFLECTION_AND_ABSORPTION": i.sGlazingReflectionAndAbsorptionOfHeat,
|
"GLAZING_REFLECTION_AND_ABSORPTION": i.sGlazingReflectionAndAbsorptionOfHeat,
|
||||||
# Коэффициент теплоотражения/теплопоглощения стеклопакета
|
"GLAZING_TONING": i.sGlazingToning,
|
||||||
"GLAZING_TONING": i.sGlazingToning, # Тонирование стеклопакета
|
"URL_W_DEL": list2_del.replace(f",{i.id},", ",")[1:-1],
|
||||||
"URL_W_DEL": list2_del.replace(f",{i.id},", ",")[1:-1] # Тонирование стеклопакета
|
|
||||||
})
|
})
|
||||||
to_template.update({'SET_LIST': dim,
|
to_template.update({'SET_LIST': dim,
|
||||||
'LIST_MERCHANT': list_of_merchant_name,
|
'LIST_MERCHANT': list_of_merchant_name,
|
||||||
'LIST_PROFILE': list_of_profile_name,
|
'LIST_PROFILE': list_of_profile_name,
|
||||||
'LIST_GLAZING': list_of_glazing_brief_description})
|
'LIST_GLAZING': list_of_glazing_brief})
|
||||||
# Предложения для добавления в сравнения:
|
# Предложения для добавления в сравнения:
|
||||||
if len(list_set_kit) < 7:
|
if len(list_set_kit) < 7:
|
||||||
try:
|
try:
|
||||||
q_set_kit = SetKit.objects.raw(
|
q_set_kit = (
|
||||||
f"SELECT "
|
SetKit.objects
|
||||||
f" oknardia_setkit.id, oknardia_setkit.sSetName,"
|
.exclude(id__in=list_fin) # исключаем уже сравниваемые наборы
|
||||||
f" oknardia_setkit.dSetModify, oknardia_setkit.fSetRating,"
|
.filter(priceoffer__isnull=False) # только наборы с ценовыми предложениями
|
||||||
f" oknardia_merchantbrand.sMerchantName,"
|
.annotate(
|
||||||
f" MAX(oknardia_priceoffer.dOfferModify) AS dLastData,"
|
dLastData=Max('priceoffer__dOfferModify'),
|
||||||
f" TO_DAYS(NOW()) - TO_DAYS(MAX(oknardia_priceoffer.dOfferModify)) AS deltaData "
|
sMerchantName=F('kSet2User__kMerchantOffice__kMerchantName__sMerchantName'),
|
||||||
f"FROM oknardia_ouruser"
|
)
|
||||||
f" INNER JOIN oknardia_setkit"
|
.order_by('-dLastData')[:25]
|
||||||
f" ON oknardia_ouruser.id = oknardia_setkit.kSet2User_id"
|
)
|
||||||
f" INNER JOIN oknardia_merchantoffice"
|
|
||||||
f" ON oknardia_merchantoffice.id = oknardia_ouruser.kMerchantOffice_id"
|
|
||||||
f" INNER JOIN oknardia_merchantbrand"
|
|
||||||
f" ON oknardia_merchantbrand.id = oknardia_merchantoffice.kMerchantName_id"
|
|
||||||
f" INNER JOIN oknardia_priceoffer"
|
|
||||||
f" ON oknardia_setkit.id = oknardia_priceoffer.kOffer2SetKit_id "
|
|
||||||
f"WHERE oknardia_setkit.id NOT IN (%s) "
|
|
||||||
f"GROUP BY oknardia_setkit.id,"
|
|
||||||
f" oknardia_setkit.sSetName,"
|
|
||||||
f" oknardia_merchantbrand.sMerchantName,"
|
|
||||||
f" oknardia_setkit.fSetRating "
|
|
||||||
f"ORDER BY dLastData DESC "
|
|
||||||
f"LIMIT 25;" % to_compare)
|
|
||||||
dim = []
|
dim = []
|
||||||
for i in q_set_kit:
|
for i in q_set_kit:
|
||||||
|
# Вычисляем deltaData в Python (аналог TO_DAYS(NOW()) - TO_DAYS(MAX(dOfferModify)))
|
||||||
|
i.deltaData = (
|
||||||
|
(timezone.now().date() - i.dLastData.date()).days
|
||||||
|
if i.dLastData else 999
|
||||||
|
)
|
||||||
if i.deltaData < 100:
|
if i.deltaData < 100:
|
||||||
early_data = pytils.dt.distance_of_time_in_words(
|
early_data = pytils.dt.distance_of_time_in_words(
|
||||||
int(django.utils.dateformat.format(i.dLastData, 'U')), accuracy=2
|
int(django.utils.dateformat.format(i.dLastData, 'U')), accuracy=2
|
||||||
@@ -557,22 +440,17 @@ def show_rating_components(request: HttpRequest, win_set: str = "1") -> HttpResp
|
|||||||
win_set = int(win_set)
|
win_set = int(win_set)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
win_set = 1
|
win_set = 1
|
||||||
q = SetKit.objects.raw(
|
q = (
|
||||||
f"SELECT oknardia_pvcprofiles.fProfileRating, oknardia_glazing.fGlazingRating,"
|
SetKit.objects
|
||||||
f" oknardia_setkit.fSetRating, oknardia_setkit.id, MAX(oknardia_priceoffer.dOfferModify) AS dPriceModify,"
|
.filter(id=win_set)
|
||||||
f" COUNT(oknardia_priceoffer.id) AS NumOffer, AVG(oknardia_priceoffer.fOfferRating) AS fOfferRatingAvg "
|
.annotate(
|
||||||
f"FROM oknardia_setkit"
|
dPriceModify=Max('priceoffer__dOfferModify'),
|
||||||
f" INNER JOIN oknardia_glazing"
|
NumOffer=Count('priceoffer__id'),
|
||||||
f" ON oknardia_setkit.kSet2Glazing_id = oknardia_glazing.id"
|
fOfferRatingAvg=Avg('priceoffer__fOfferRating'),
|
||||||
f" INNER JOIN oknardia_pvcprofiles"
|
fProfileRating=F('kSet2PVCprofiles__fProfileRating'),
|
||||||
f" ON oknardia_setkit.kSet2PVCprofiles_id = oknardia_pvcprofiles.id"
|
fGlazingRating=F('kSet2Glazing__fGlazingRating'),
|
||||||
f" INNER JOIN oknardia_priceoffer"
|
)
|
||||||
f" ON oknardia_priceoffer.kOffer2SetKit_id = oknardia_setkit.id "
|
)
|
||||||
f"WHERE oknardia_setkit.id = {win_set} "
|
|
||||||
f"GROUP BY oknardia_pvcprofiles.fProfileRating,"
|
|
||||||
f" oknardia_glazing.fGlazingRating,"
|
|
||||||
f" oknardia_setkit.fSetRating,"
|
|
||||||
f" oknardia_setkit.id;")
|
|
||||||
raring_list = list(q)
|
raring_list = list(q)
|
||||||
f_rating_service = raring_list[0].fSetRating - RARING_WEIGHT_PVC_PROFILE_IN_SET * normalize(
|
f_rating_service = raring_list[0].fSetRating - RARING_WEIGHT_PVC_PROFILE_IN_SET * normalize(
|
||||||
raring_list[0].fProfileRating, val_max=RARING_PVC_PROFILE_MAX
|
raring_list[0].fProfileRating, val_max=RARING_PVC_PROFILE_MAX
|
||||||
|
|||||||
Reference in New Issue
Block a user