Вьюшка и шаблоны: Выдача предложений -- готово

This commit is contained in:
2022-12-31 02:55:09 +03:00
parent 28a680fdf1
commit 37a605ef09
6 changed files with 638 additions and 51 deletions

View File

@@ -266,4 +266,6 @@ CATALOG_RECORD_FOR_PROFILE_MANUFACTURER = 100
CATALOG_SORTER_MAGIC_NUMBER_ADV = 5
CATALOG_SORTER_MAGIC_NUMBER_TIZER = 1
MAX_LEN_RING_LOG_BUFFER = 250 # МАКСИМАЛЬНЫЙ РАЗМЕР КОЛЬЦЕВОГО БУФЕРА
YANDEX_MAPS_API_KEY = MY_YANDEX_MAPS_API_KEY

View File

@@ -73,6 +73,7 @@ urlpatterns = [
# ЦЕНОВЫЕ ПРЕДЛОЖЕНИЯ
re_path(r'^tsena-odnogo-okna/(?P<win_width_mm>\d+)x(?P<win_height_mm>\d+)mm/tip(?P<win_id>\d+)[/*]$',
prices.report_one_win_price),
re_path(r'^(?P<build_id>\d{1,6})/(?P<apart_id>\d{1,})/(?P<slug>[\s\S]+|.*)$', prices.report_price),
]

View File

@@ -0,0 +1,150 @@
{% load static %}{% load filters %}
{% for CurOffer in PRICE_FRAME %}
<tr>
<td colspan="11" style="font-size:xx-small;border-top:double black;border-bottom: solid 1px white;padding: 0;"></td>
</tr>{% for CurInOffer in CurOffer.DIM %}
<tr>
{% if forloop.first %}
<th rowspan="{% if CurOffer.DIM|length == 1 %}2{% else %}{{ CurOffer.DIM|length }}{% endif %}" title="Добавить коммерческое предложение окон к сравнению">{# красивые чекбоксы BEGIN #}<div class="checkbox"><label><input id="CHK{{ CurOffer.SETS_ID }}" type="checkbox" name="ForCompare" value="{{ CurOffer.SETS_ID }}" onChange="ChangeCountCheckedBox({{ CurOffer.SETS_ID }});" /><span class="cr"><i class="cr-icon glyphicon glyphicon-ok"></i></span></label></div>{# красивые чекбоксы END #}</th>
<td rowspan="{% if CurOffer.DIM|length == 1 %}2{% else %}{{ CurOffer.DIM|length }}{% endif %}"{% if CurOffer.IS_COMMERCIAL %} style="background-image: url(/media/{{ CurOffer.MERCHANT_LOGO }})"{% endif %} title="Краткая спецификация коммерческого предложения">
<span itemprop="description">
<h3 class="set-name shake-trigger" id="btn{{ CurOffer.SETS_ID }}"><a href="javascript://" onclick="show_dtl({{ CurOffer.SETS_ID }})">{{ CurOffer.MERCHANT }}{{ CurOffer.SETS_NAME }}<i class="glyphicon glyphicon-chevron-down shake-vertical"></i></a></h3>
<DiV id="dtl{{ CurOffer.SETS_ID }}" class="collapse">■ Профиль: <a href="/catalog/profile/{{ CurOffer.PVC_ID }}-{{ CurOffer.PVC_MANUFACTURER_T }}/{{ CurOffer.PVC_ID }}-{{ CurOffer.PVC_NAME_T }}">{{ CurOffer.PVC_NAME|safe }}</a> (<a href="/catalog/profile/{{ CurOffer.PVC_ID }}-{{ CurOffer.PVC_MANUFACTURER_T }}">{{ CurOffer.PVC_MANUFACTURER }}</a>)
&nbsp;{{ CurOffer.GLAZING_NAME_B|safe }} <nobr>({{ CurOffer.GLAZING_MARK }})</nobr>
&nbsp;Тонирование:&nbsp;{{ CurOffer.GLAZING_TONING }}
{% if CurOffer.PVC_SEAL %}■&nbsp;Уплотнитель:&nbsp;{{ CurOffer.PVC_SEAL }}
{% endif %}{% if CurOffer.SETS_IMPLEMENT %}■&nbsp;Фурнитура:&nbsp;{{ CurOffer.SETS_IMPLEMENT|capfirst|safe }}
{% endif %}{% if CurOffer.SETS_IMPLEMENT_R %}■&nbsp;Ручки:&nbsp;{{ CurOffer.SETS_IMPLEMENT_R|capfirst|safe }}
{% endif %}{% if CurOffer.SETS_IMPLEMENT_P %}■&nbsp;Петли:&nbsp;{{ CurOffer.SETS_IMPLEMENT_P|capfirst|safe }}
{% endif %}{% if CurOffer.SETS_IMPLEMENT_Z %}■&nbsp;Запоры:&nbsp;{{ CurOffer.SETS_IMPLEMENT_Z|capfirst|safe }}
{% endif %}{% if CurOffer.SETS_IMPLEMENT_O %}■&nbsp;Ограничители:&nbsp;{{ CurOffer.SETS_IMPLEMENT_O|capfirst|safe }}
{% endif %}{% if CurOffer.SETS_IMPLEMENT_F %}■&nbsp;Фиксаторы:&nbsp;{{ CurOffer.SETS_IMPLEMENT_F|capfirst|safe }}
{% endif %}{% if CurOffer.SETS_CLIMATE_CONTROL %}<span {% if CurOffer.SETS_CLIMATE_CONTROL|capfirst != "Нет" or CurOffer.SETS_CLIMATE_CONTROL|length > 3 %}class="bullet-green"{% endif %}>■&nbsp;Климат-контроль:&nbsp;{{ CurOffer.SETS_CLIMATE_CONTROL|capfirst|safe }}</span>
{% endif %}{% if CurOffer.SETS_SILL %}<span {% if CurOffer.SETS_SILL|capfirst == "Нет" or CurOffer.SETS_SILL|length < 3 %}class="bullet-red"{% endif %}>&nbsp;Подоконник:&nbsp;{{ CurOffer.SETS_SILL|capfirst|safe }}</span>
{% endif %}{% if CurOffer.SETS_SLOPE %}<span {% if CurOffer.SETS_SLOPE|capfirst == "Нет" or CurOffer.SETS_SLOPE|length < 3 %}class="bullet-red"{% endif %}>&nbsp;Откос:&nbsp;{{ CurOffer.SETS_SLOPE|capfirst|safe }}</span>
{% endif %}{% if CurOffer.SETS_PANES %}<span {% if CurOffer.SETS_PANES|capfirst == "Нет" or CurOffer.SETS_PANES|length < 3 %}class="bullet-red"{% endif %}>&nbsp;Водоотлив:&nbsp;{{ CurOffer.SETS_PANES|capfirst|safe }}</span>
{% endif %}{% if CurOffer.SETS_UNINSTALL_INSTALL %}<span {% if CurOffer.SETS_UNINSTALL_INSTALL_B %}class="bullet-green"{% else %}class="bullet-red"{% endif %}>&nbsp;Демонтаж/монтаж:&nbsp;{{ CurOffer.SETS_UNINSTALL_INSTALL|capfirst|safe }}</span>
{% endif %}{% if CurOffer.SETS_DELIVERY %}<span {% if CurOffer.SETS_DELIVERY_B %}class="bullet-green"{% else %}class="bullet-red"{% endif %}>&nbsp;Доставка:&nbsp;{{ CurOffer.SETS_DELIVERY|capfirst|safe }}</span>{% endif %}{% comment %} {% if CurOffer.SETS_OTHER %}■&nbsp;Прочие условия:&nbsp;{{ CurOffer.SETS_OTHER|capfirst|safe }}
{% endif %}{% endcomment %}
</DiV>
<!-- Расстояние до офиса поставщика -->
<nobr>{% if CurOffer.DISTANCE != -1 %}<nobr class="badge badge4price" title="Удалённость офиса — {{ CurOffer.DISTANCE|stringformat:"0.1f" }} км."><b class="glyphicon glyphicon-map-marker"></b> {{ CurOffer.DISTANCE|stringformat:"0.1f"|price_format }}&thinsp;км.</nobr>{% endif %}</nobr>
<!-- Дата обновления -->
<nobr class="badge badge4price" title="Дата обновления коммерческого предложения окон — {{ CurOffer.SETS_DATA_MODIFY|date:"d.M.Y" }}"><b class="glyphicon glyphicon-calendar"></b> {{ CurOffer.SETS_DATA_MODIFY|date:"d.M.Y" }}</nobr>
<!-- Звездочки рейтинга -->
<nobr class="badge badge4price" title="Рейтинг «Окнардии»{% if CurOffer.SETS_RATING > -0.1 %} — {{ CurOffer.SETS_RATING|stringformat:".2f" }} баллов{% endif %}"><a
href="javascript://"
id-set="{{ CurOffer.SETS_ID }}"
data-trigger="focus" tabindex="0"
title="{% if CurOffer.SETS_RATING > 0.01 %}<b> Рейтинг {{ CurOffer.SETS_RATING|stringformat:".2f" }}</b> для оконого набора «{{ CurOffer.SETS_NAME }}» компании «{{ CurOffer.MERCHANT }}» состоит&nbsp;из:{% else %}Рейтинг не присвоен{% endif %}"
data-toggle="popover">рейтинг</a>:&nbsp;{% for Star in CurOffer.SETS_RATING_STARTS %}{% if Star == 0 %}<b class="glyphicon glyphicon-star-empty"></b>{% else %}<b class="glyphicon glyphicon-star"></b>{% endif %}{% endfor %} {% if CurOffer.SETS_RATING > -0.1 %} {{ CurOffer.SETS_RATING|stringformat:".2f" }}{% endif %}</nobr>
</span>
<span itemprop="brand" itemscope itemtype="http://schema.org/Brand">
<meta itemprop="name" content="{{ CurOffer.MERCHANT }}" />
<meta itemprop="logo" content="https://oknardia.ru/media/{{ CurOffer.MERCHANT_LOGO }}" />
</span></td>
<!--- Конец большой ячейки со спецификацией оконного предложения --->
{% endif %}
<td class="rnw" title="{{ CurInOffer.QUANTITY }} × {{ CurInOffer.DESCRIPTION }} — {{ CurInOffer.WIDTH|stringformat:".0f" }}0x{{ CurInOffer.HIGHT|stringformat:".0f" }}0 мм.">{% for BUL in CurInOffer.BULLET %}<span class="color-bullet" style="background-image:url({% static "img/svg/mark" %}{{ BUL }}.svg);"></span>{% endfor %}</td>
<td class="rnw" title="Схема открывания окна или двери {{ CurInOffer.WIDTH|stringformat:".0f" }}0x{{ CurInOffer.HIGHT|stringformat:".0f" }}0 мм."><img src="{% static CurInOffer.IMG_MINI %}" alt="Схема открывания: {{ CurInOffer.DESCRIPTION }} — {{ CurInOffer.WIDTH|stringformat:".0f" }}0x{{ CurInOffer.HIGHT|stringformat:".0f" }}0 мм." /></td>
<td class="rnw" title="Цена {{ CurInOffer.PRICE|stringformat:".2f" }} рублей.">{{ CurInOffer.PRICE|stringformat:".2f"|price_format }}</td>
<td title="Количество: {{ CurInOffer.QUANTITY }} шт.">×{{ CurInOffer.QUANTITY }}</td>
<td class="rnw hidden-xs hidden-sm">=</td>
<td class="rnw hidden-xs hidden-sm" title="Сумма {{ CurInOffer.SUBTOTAL|stringformat:".2f" }} рублей за {{ CurInOffer.QUANTITY }} шт.">{{ CurInOffer.SUBTOTAL|stringformat:".2f"|price_format }}</td>
{% if forloop.first %}<!-- FIRST -->
<td class="rnw" title="Стоимость {{ CurOffer.TOTAL|stringformat:".2f" }} рублей за все окна квартиры {{ APART|safe }}.">{{ CurOffer.TOTAL|stringformat:".2f"|price_format }}</td>
<th{% if CurOffer.DISCOUNT_COLOR2 != "" %} style="background-color:{{ CurOffer.DISCOUNT_COLOR2 }};"{% endif %} title="{% if CurOffer.DISCOUNT < 0.1 %}Нет скидки{% else %}Скидка — {{ CurOffer.DISCOUNT|stringformat:".1f" }}%{% endif %}">{% if CurOffer.DISCOUNT < 0.1 %}{% else %}&minus;{{ CurOffer.DISCOUNT|stringformat:".1f" }}%{% endif %}</th>
<th{% if CurOffer.DISCOUNT_COLOR1 != "" %} style="background-color:{{ CurOffer.DISCOUNT_COLOR1 }};"{% endif %} itemprop="offers" itemscope itemtype="http://schema.org/Offer" title="Итого за все окна с учетом скидки: {{ CurOffer.FIN_PRICE|stringformat:".2f" }} рублей">
Итого: {{ CurOffer.FIN_PRICE|stringformat:".2f"|price_format }}&thinsp;<small class="glyphicon glyphicon-ruble" aria-label="₽ (руб.)" title="₽ (руб.)"></small>
<meta itemprop="price" content="{{ CurOffer.FIN_PRICE }}" />
<meta itemprop="priceCurrency" content="RUB" />
</th>
{% if CurOffer.DIM|length == 1 %}
</tr><tr>
<td colspan="6">&nbsp;</td>
<td colspan="3">
{% endif %}
{% elif forloop.counter0 == 1 %}
<td colspan="3" rowspan="{{ CurOffer.DIM|length|add:"-1" }}">
{% endif %}
{% if forloop.counter0 == 1 or CurOffer.DIM|length == 1 %}
<stong>{{ CurOffer.OFFICE_NAME }}</stong><br />
<div id="hid{{ CurOffer.SETS_ID }}" class="collapse in">
<a class="btn btn-info btn-xs shake-trigger" data-toggle="collapse" data-target="#tel{{ CurOffer.SETS_ID }}" onclick="show_phone_num({{ CurOffer.SETS_ID }})"><b class="glyphicon glyphicon-phone-alt shake-vertical"></b> Показать телефон</a>
</div>
<div id="tel{{ CurOffer.SETS_ID }}" class="collapse">
<small>{{ CurOffer.OFFICE_ADDRESS }}</small><br /> <b class="glyphicon glyphicon-phone-alt"></b> {{ CurOffer.OFFICE_PHONES }}<br />
<small><nobr>Пожалуйста, скажите, что нашли цены на oknardia.ru</nobr></small>
</div>
</td>
{% endif %}
</tr>{% endfor %}<!----- ПРОВЕРКА --->{% endfor %}
<Tr id="preloader_{{ N }}">
<tH colspan="11"><center><img src="{% static "img/preloader.gif" %}" alt="подгружаю цены на окна..." height="64" width="64" /></center></tH>
</Tr>
<tR id="load_and_banner_{{ N }}">
<!-- сюда подгружаем следующий фрейм прайслиста --->
<script type="application/javascript">
function get_next_pricelist_frame( ) {
try{yaCounter32997984.reachGoal("MoreOffer");}catch(e){}
// заменяем ряд с кнопочками кнопочками на рекламу
// $("#load_and_banner_{{ N }}").html("<th colspan=10>РЕКЛАМА TMP</th>");
// добавляем ячейки с дополнительными ценами и новые кнопочки
$("#load_and_banner_{{ N }}").css({"display":"none"});
$("#preloader_{{ N }}").css({"display":"table-row","transition":"1s"});// подсчитать сколько прочеканных оферов для сравнения
$("#tmp").load(
"/next_price_frame/idA{{ APPARTMENT_ID }}MDPO{{ MOUNT_DIM_PER_OFFER }}LON0LAT0N{{ N }}",
function (){
window.frame = $("#tmp").html();
$("#price-list > tbody").append(window.frame);
}
);
window.setTimeout(
function show_adv() {
$("#load_and_banner_{{ N }}").html("<td colspan='11' bgcolor='#CCCCCC' align='center'><center><a href='https://api.ozon.ru/partner-tools.affiliates/pankarta/11052421746600/link?partner=e-serg&&utm_content=banner&width=728&height=90' target='_blank'><img src='https://api.ozon.ru/partner-tools.affiliates/pankarta/11052421746600/image?partner=e-serg&utm_content=banner&width=728&height=90' width='728px' height='90px'></a><small><br/>↑ Здесь могла бы быть ваша реклама ↑</small></center></td>");
$("#load_and_banner_{{ N }}").css({"display":"table-row","transition":"all 5s"});
$("#preloader_{{ N }}").css({"display":"none","transition":"1s"});
// (adsbygoogle=window.adsbygoogle || []).push({});
window.count = 0;
for (var i=0; i < ForCompare.length; i++)
if (ForCompare[i].checked)
window.count++;
$("#NumberOfSelected").html(window.count);
$('[data-toggle="popover"]').popover({ // реинициализировать подгружаемые поповеры
placement: "top",
html: true,
content: function () {
// сохранить текущий контекст
var _this = this;
$('#shadow_buffer').load('/show_rating_components/' + $(_this).attr("id-set"),
function (response, status, xhr) {
if (status == "error")
$(_this).attr({'data-content': "Ошибка " + xhr.status + " (" + xhr.statusText + ")"});
else
$(_this).attr({'data-content': response});
$(_this).popover('show');
try{yaCounter32997984.reachGoal("ShowRating");}catch(e){};
});
}
});
},
2800);
}
</script>
<td colspan="2"><a class="btn btn-info btn-block" data-toggle="collapse" onclick="Click2CompareOffers();">Сравнить выбранные (<span id="NumberOfSelected">0</span>) <small class="glyphicon-stats glyphicon"></small></a><p id="tmp"></p></td>
<td colspan="8">{% if N != "-1" %}<a href="javascript://" class="btn btn-info btn-block" onclick="get_next_pricelist_frame();">Ещё коммерческие предложения окон &nbsp;<small class="glyphicon-refresh glyphicon"></small></a>{% endif %}</td>
<td><a data-toggle="collapse" href="#collapse_it" onclick="get_more_info_about_building()" class="shake-trigger">Подробная информация по зданию <small class="glyphicon-chevron-down glyphicon shake-vertical"></small></a></td>
</tR>

View File

@@ -0,0 +1,207 @@
{% extends "base.html" %}
{% load static %}
{% load filters %}
{% block Title %}Цены на окна для {{ ADDRESS }} — дом серии {{ APART|safe }}{% endblock %}
{% block Add_Body_Attribute %} style="padding-top:70px;"{% endblock %}
{% block Date4Meta %}{{ META_DATA_PUBLISH|date:"c" }}{% endblock %}
{% block Last4Meta %}{{ META_DATA_PUBLISH|date:"c" }}{% endblock %}
{% block Description %}Цены на окна для серии {{ APART|safe }} по адресу {{ ADDRESS }}. Размер окон (см.): {% for I_WIN_DIM in FLAP_DIM %}{{ I_WIN_DIM.iWinWidth|floatformat:0 }}x{{ I_WIN_DIM.iWinHight|floatformat:0 }}{% if forloop.last %}.{% else %}; {% endif %}{% endfor %} Оконные наборы: {% for CurOffer in PRICE_FRAME %}{{ CurOffer.SETS_NAME }}{{ CurOffer.FIN_PRICE|stringformat:".0f" }} рублей{% if forloop.last %}.{% else %}; {% endif %}{% endfor %}{% endblock %}
{% comment %}{% block Description %}Цены на плаcтиковые окна для серии {{ BASE_SERIA }} ({{ APART }} квартира, {{ ADDRESS }}) :: {% for CurOffer in PRICE_FRAME %}Поставщик: {{ CurOffer.MERCHANT }}; Комплектация: {{ CurOffer.SETS_NAME }}; Цена: {{ CurOffer.FIN_PRICE }}₽ :: {% endfor %}{% endblock %}{% endcomment %}
{% block Keywords %}цены окон, серия {{ BASE_SERIA }}, {{ BASE_SERIA }}, стоимость окон, окна для {{ BASE_SERIA }}, размеры окон, проемы серии {{ BASE_SERIA }}, окна в {{ APART|safe }}, скидки на окна, {{ ADDRESS }}, оконный профиль, {% for CurOffer in PRICE_FRAME %}{{ CurOffer.MERCHANT }}, {{ CurOffer.PVC_NAME }}, {{ CurOffer.PVC_MANUFACTURER }}, {{ CurOffer.GLAZING_MARK }}, {% endfor %} характеристики пластиковых окон, {% for I_WIN_DIM in FLAP_DIM %}{{ I_WIN_DIM.iWinWidth|floatformat:0 }}x{{ I_WIN_DIM.iWinHight|floatformat:0 }} см., {% endfor %}{{ META_KEYWORDS|default:"" }}{% endblock %}
{% block Top_JS3%}<script type="text/javascript">
function show_phone_num( id ){ // колапсатор для отображения контатной информации постафшика окон
$('#tel'+id).collapse('show');
$('#hid'+id).collapse('hide');
try {
yaCounter32997984.reachGoal('ShowPhone')
} catch (e) {
}
try {
var _tmr = window._tmr || (window._tmr = []);
_tmr.push({id: "2018432", type: "reachGoal", goal: "ViewPhone"});
} catch (e) {
}
}
function show_dtl( id ){ // колапсаторы для отобращения детальной информации оконого набора
$('#dtl'+id).collapse('show');
$('#btn'+id+' a .glyphicon-chevron-down').remove();
var ContentInA = $('#btn'+id+' a').text();
$('#btn'+id).empty();
$('#btn'+id).text(ContentInA);
try {
yaCounter32997984.reachGoal('ShowDetails')
} catch (e) {
}
try {
var _tmr = window._tmr || (window._tmr = []);
_tmr.push({id: "2018432", type: "reachGoal", goal: "ViewDetails"});
} catch (e) {
}
}
$(window).load( // уменьшение картинок .half для ретина-дисплеев
function(){var images = $('.half');images.each(function(i){$(this).width($(this).width()/2);});}
);
var count = 0;
var ForCompare = document.getElementsByName('ForCompare');
$(window).load( // подсчитать сколько прочеканных оферов для сравнения (нужно, когда на страничку возращаются через back, ее подгрущают или она приходит из кеша
function(){
for (var i=0; i < ForCompare.length; i++)
if (ForCompare[i].checked)
count++;
// alert(count);
$('#NumberOfSelected').html(count)
}
);
var ToURL = '';
function Click2CompareOffers(){ // вызывается при клике "сравнить коммерческие предложения"
try{yaCounter32997984.reachGoal('CompareOffers')}catch(e){}
//ForCompare = $('[name]=ForCompare');
for (var i=0; i < ForCompare.length; i++)
if (ForCompare[i].checked)
ToURL += ForCompare[i].value +',';
if (ToURL.match(/[,]/g).length > 1 && ToURL.match(/[,]/g).length < 7 )
location.href = '/compare_offers/' + ToURL.slice(0,-1);
else {
$('#modal-exclamation').modal('show');
ToURL = '';
}
}
function ChangeCountCheckedBox(CHK_ID){ // изменение числа выбранных для сравнения оферов
if ($("#CHK"+CHK_ID).is(":checked")) count++;
else count--;
$("#NumberOfSelected").html(count)
}
function get_more_info_about_building() {
try{yaCounter32997984.reachGoal("ClickBuildingDetails");}catch(e){}
}
$(function () { // инициализация и обработка поповеров рейтинга
$('[data-toggle="popover"]').popover({
placement: "top",
html: true,
content: function () {
// сохранить текущий контекст
var _this = this;
$('#shadow_buffer').load('/show_rating_components/' + $(_this).attr("id-set"), function (response, status, xhr) {
if (status == "error")
$(_this).attr({'data-content': "Ошибка " + xhr.status + " (" + xhr.statusText + ")"});
else
$(_this).attr({'data-content': response});
$(_this).popover('show');
try{yaCounter32997984.reachGoal("ShowRating");}catch(e){};
});
}
})
})
</script>{% endblock %}
{% block Top_CSS1 %}<link rel="stylesheet" type="text/css" href="{% static "css/csshake-vertical.min.css" %}">{% endblock %}
{% block Main_Content %}
<span itemscope itemtype="http://schema.org/Product">
<div class="row col-md-12">
<div class="col-md-9">
<h1>Цены на окна для серии {{ APART|safe }} <small>({{ ADDRESS }})</small></h1>
</div>
<div class="col-md-9">
<p>Квартира имеет проёмы (окна и балконные двери) следующих размеров: {% for I_WIN_DIM in FLAP_DIM %}{% if not forloop.first %}{% if forloop.last %} и&nbsp;{% else %}, {% endif %}{% endif %}{{ I_WIN_DIM.iWinWidth|floatformat:0 }}x{{ I_WIN_DIM.iWinHight|floatformat:0 }}&nbsp;см. —&nbsp;{{ I_WIN_DIM.iQuantity }}&nbsp;шт.{% endfor %} Проект (<a href="/catalog/seria/{{ BASE_SERIA_LAT }}/all{{ BASE_SERIA_ID }}">типовая серия {{ BASE_SERIA }}</a>) предполагает следующие схемы открывания окон:</p>
</div>
{# Микроразмектка: названеи продукта #}<meta itemprop="name" content="Окна {{ APART|safe }} ({{ ADDRESS }})" />
</div>
<div class="row col-md-12 ShowBigFlapPictures">
<div class="col-sm-9">
{% include 'report/show_big_flap_pictures.html' %}
</div>
<div class="col-sm-3 visible-md visible-lg ap_list">
<h6>Другие типовые квартиры в&nbsp;этом доме:</h6>
<ul>{% for I_APART in APARTMENT_IN_BUILDING %}
{% if I_APART.APT_ID == '!' %}<li>{{ I_APART.APT_NAME|safe }}</li>{% else %}<li><a href="/{{ BUILD_ID }}/{{ I_APART.APT_ID }}/{{ ADDRESS_T }}">{{ I_APART.APT_NAME|safe }}</a></li>{% endif %}{% endfor %}
</ul>
<a href="/catalog/seria/{{ BASE_SERIA_LAT }}/all{{ BASE_SERIA_ID }}">Информация по серии {{ BASE_SERIA }}</a>
</div>
</div>
<div class="row col-md-12">
<div class="col-md-12">
<p id="tab-note">Таблица содержит цены поставщиков. Клик на&nbsp;название отобразит детальные спецификации каждого предложения: марку профиля рамы и&nbsp;створки, схему стеклопакета, тип фурнитуры, элементы отделки (отлив, подоконник, откос, клапан <nobr>климат-контроля</nobr>) и&nbsp;сопутствующие услуги. Предложения выводятся покадрово, получите следующий кадр кнопкой &laquo;Ещё коммерческие предложения окон&raquo; под таблицей. Просмотреть и&nbsp;сравнить технические характеристик стеклопакетов, профилей и&nbsp;детальное описание сопутствующих услуг возможно с&nbsp;помощью кнопки &laquo;Сравнить выбранные&raquo;.</p>
</div>
{# Микроразмектка: названеи продукта #}
<meta itemprop="name" content="Окна {{ APART|safe }} ({{ ADDRESS }})"/>
</div>
<form class="col-md-12" method="get" action="\" id="compare_offers">
{% csrf_token %}
<table class="table" id="price-list">
<thead>
<tr>
<th><b class="glyphicon glyphicon-th-list" title="Добавление набора окон в список сравнения" aria-label="Добавление набора окон в список сравнения"></b></th>
<th>Поставщик окон и название оконного набора<small><br />
кликните чтобы увидеть описание и характеристики предложения</small>
</th>
<th colspan="2">Схема<small><br />
открывания</small></th>
<th>Цена,<b class="glyphicon glyphicon-ruble" aria-label="₽ (руб.)" title="₽ (руб.)"></b><small><br />
одно окно</small></th>
<th>N</th>
<th colspan="2" class="hidden-xs hidden-sm">Cумма,<b class="glyphicon glyphicon-ruble" aria-label="₽ (руб.)" title="₽ (руб.)"></b><small><br />
однотипные окна</small></th>
<th>Стоимость, <b class="glyphicon glyphicon-ruble" aria-label="₽ (руб.)" title="₽ (руб.)"></b><small><br />
все окна квартиры</small></th>
<th>Скидка</th>
<th>Итого<small><br />
за все окна с учетом скидки</small></th>
</tr>
</thead>
<tbody id="offers">
{% include "report/report_precelist_frame.html" %}
</tbody>
</table>
</form>
</span>
{% with SERIA_BASE=BASE_SERIA %}{% include "report/build_info_in_table.html" %}{% endwith %}
{# --- Баннер: НАЧАЛО --- #}
<div class="row"><div class="col-md-12 col-xs-12"><hr class="dotted-black" />{% include "ad/bannet-wide.html" %}</div></div>
{# --- Баннер: конец --- #}
<div class="row">
{% include "report/report_last_user_visit.html" %}
{% include "report/report_log_user_visit.html" %}
<p id="shadow_buffer"></p>
</div>
{# модальное окно #}
<div class="modal fade bs-example-modal-sm" id="modal-exclamation" tabindex="-1" role="dialog">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="mySmallModalLabel">Внимание:</h4>
</div>
<div class="modal-body">
<p>Извините, для сравнения коммерческих предложений окон нужно выбрать не менее двух и не более шести позиций.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Спасибо, все понятно.</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% comment %}
{% block Top_Nav_Bar %}
{# ОТЛАДКА, ГАСИМ ВЕРХНЕЕ МЕНЮ #}
{% endblock %}
{% endcomment %}

View File

@@ -2,15 +2,16 @@
from django.core.exceptions import ObjectDoesNotExist
from django.shortcuts import render, redirect
from django.http import HttpRequest, HttpResponse
from oknardia.models import Win_MountDim, PriceOffer
from oknardia.models import Win_MountDim, PriceOffer, Apartment_Type, Seria_Info, LogVisitPriceReport
from oknardia.settings import *
from web.report1 import get_last_all_user_visit_list, get_last_user_visit_cookies, get_last_user_visit_list
from web.add_func import normalize, get_rating_set_for_stars, get_flaps_for_big_pictures, get_flaps_for_mini_pictures,\
from web.add_func import normalize, get_rating_set_for_stars, get_flaps_for_big_pictures, get_flaps_for_mini_pictures, \
get_geo_distance
import django.utils.dateformat
import time
import os
import re
import json
import pytils
@@ -33,7 +34,7 @@ def report_price_frame(apartment_id: int, mount_dim_per_offer: int, address_long
:return: dict -- словарь данных для отображения в фрейме (цены предложений и их характеристики)
"""
# ценовая выдача
time_for_meta = 0 # время для мета-данных в HTML-кода
time_for_meta = 0 # время для мета-данных в HTML-кода
apartment_id = int(apartment_id)
mount_dim_per_offer = int(mount_dim_per_offer)
address_longitude = float(address_longitude)
@@ -46,7 +47,7 @@ def report_price_frame(apartment_id: int, mount_dim_per_offer: int, address_long
if brand_id != 0:
# Это вывод для выджета. Нужны цены только по определенному поставщику
add_to_sql_for_widget = f" AND oknardia_merchantbrand.id = {brand_id} "
offer_per_frame = 1000 # Фреймовый вывод не нужен... фигачим сразу целую 1000 предложений.
offer_per_frame = 1000 # Фреймовый вывод не нужен... фигачим сразу целую 1000 предложений.
if int(apartment_id) == 0 and int(win_id) != 0:
# если выводим цены только для одного проема
offer_per_frame = OFFER_PER_FRAME_FOR_ONE_FLAP
@@ -192,15 +193,15 @@ def report_price_frame(apartment_id: int, mount_dim_per_offer: int, address_long
total += i2.fOfferPrice * i2.iQuantity
image_file = get_flaps_for_mini_pictures(i2.sOfferFlapConfig)
dim_in_offer.append({
'PRICE': i2.fOfferPrice,
'FLAP': i2.sOfferFlapConfig,
'PRICE': i2.fOfferPrice,
'FLAP': i2.sOfferFlapConfig,
'DESCRIPTION': i2.sDescripion,
'WIDTH': i2.iWinWidth,
'HIGHT': i2.iWinHight,
'ID': i2.id,
'WIDTH': i2.iWinWidth,
'HIGHT': i2.iWinHight,
'ID': i2.id,
'IMG_MINI': image_file,
'QUANTITY': i2.iQuantity,
'BULLET': [chr(65+cur_bullet+i) for i in range(i2.iQuantity)],
'BULLET': [chr(65 + cur_bullet + i) for i in range(i2.iQuantity)],
# 'BULLET': range(CurBullet, CurBullet+i2.iQuantity),
'SUBTOTAL': i2.fOfferPrice * i2.iQuantity,
})
@@ -236,59 +237,61 @@ def report_price_frame(apartment_id: int, mount_dim_per_offer: int, address_long
# address_latitude)
else:
distance = -1
print(discount)
if discount > 99 or discount < 0.1:
discount_color1 = ""
discount_color2 = ""
else:
color_ratio = (discount + 0.) / 100
discount_color1 = f"#{255 - int(color_ratio * 128): 02x}ff{255 - int(color_ratio * 128) :02x}"
discount_color2 = f"#{255-int(color_ratio * 255): 02x}ff{255 - int(color_ratio * 255) :02x}"
discount_color1 = f"#{255 - int(color_ratio * 128):02x}ff{255 - int(color_ratio * 128):02x}"
discount_color2 = f"#{255 - int(color_ratio * 255):02x}ff{255 - int(color_ratio * 255):02x}"
print(discount_color1, discount_color2)
price_frame.append({
'DISTANCE': distance,
'DIM': dim_in_offer,
'TOTAL': total,
'DISCOUNT': discount,
'DISCOUNT_COLOR1': discount_color1,
'DISCOUNT_COLOR2': discount_color2,
'FIN_PRICE': fin_price,
'OFFICE_NAME': i2.sOfficeName,
'OFFICE_ADDRESS': i2.sOfficeAddress,
'OFFICE_PHONES': i2.sOfficePhones,
'MERCHANT': i2.sMerchantName,
'MERCHANT_LOGO': i2.pMerchantLogo,
'MERCHANT_URL': i2.sMerchantMainURL,
'DISTANCE': distance,
'DIM': dim_in_offer,
'TOTAL': total,
'DISCOUNT': discount,
'DISCOUNT_COLOR1': discount_color1,
'DISCOUNT_COLOR2': discount_color2,
'FIN_PRICE': fin_price,
'OFFICE_NAME': i2.sOfficeName,
'OFFICE_ADDRESS': i2.sOfficeAddress,
'OFFICE_PHONES': i2.sOfficePhones,
'MERCHANT': i2.sMerchantName,
'MERCHANT_LOGO': i2.pMerchantLogo,
'MERCHANT_URL': i2.sMerchantMainURL,
'MERCHANT_URL_SHOT': re.sub(r"(?:^http://|^https://|/$|www\.)", "", i2.sMerchantMainURL),
'SETS_NAME': i2.sSetName,
'GLAZING_NAME_B': i2.sGlazingBriefDescription,
'GLAZING_MARK': i2.sGlazingMark,
'GLAZING_TONING': i2.sGlazingToning,
'PVC_ID': i2.pwc_id,
'PVC_NAME': i2.sProfileName,
'PVC_NAME_T': pytils.translit.slugify(i2.sProfileName).lower(),
'SETS_NAME': i2.sSetName,
'GLAZING_NAME_B': i2.sGlazingBriefDescription,
'GLAZING_MARK': i2.sGlazingMark,
'GLAZING_TONING': i2.sGlazingToning,
'PVC_ID': i2.pwc_id,
'PVC_NAME': i2.sProfileName,
'PVC_NAME_T': pytils.translit.slugify(i2.sProfileName).lower(),
'PVC_MANUFACTURER': i2.sProfileManufacturer,
'PVC_MANUFACTURER_T': pytils.translit.slugify(i2.sProfileManufacturer).lower(),
'PVC_SEAL': i2.sProfileSealDescription,
'PVC_SEAL': i2.sProfileSealDescription,
'SETS_CLIMATE_CONTROL': i2.sSetClimateControl,
'SETS_SILL': i2.sSetSill,
'SETS_IMPLEMENT': i2.sSetImplementAll,
'SETS_SILL': i2.sSetSill,
'SETS_IMPLEMENT': i2.sSetImplementAll,
'SETS_IMPLEMENT_R': i2.sSetImplementHandles,
'SETS_IMPLEMENT_P': i2.sSetImplementHinges,
'SETS_IMPLEMENT_Z': i2.sSetImplementLatch,
'SETS_IMPLEMENT_O': i2.sSetImplementLimiter,
'SETS_IMPLEMENT_F': i2.sSetImplementCatch,
'SETS_PANES': i2.sSetPanes,
'SETS_SLOPE': i2.sSetSlope,
'SETS_DELIVERY': i2.sSetDelivery,
'SETS_DELIVERY_B': i2.bSetDelivery,
'SETS_OTHER': i2.sSetOtherConditions,
'SETS_ID': i2.setID,
'SETS_UNINSTALL_INSTALL': i2.sSetUninstallInstall,
'SETS_PANES': i2.sSetPanes,
'SETS_SLOPE': i2.sSetSlope,
'SETS_DELIVERY': i2.sSetDelivery,
'SETS_DELIVERY_B': i2.bSetDelivery,
'SETS_OTHER': i2.sSetOtherConditions,
'SETS_ID': i2.setID,
'SETS_UNINSTALL_INSTALL': i2.sSetUninstallInstall,
'SETS_UNINSTALL_INSTALL_B': i2.bSetUninstallInstall,
'SETS_RATING': i2.fSetRating,
'SETS_RATING_STARTS': get_rating_set_for_stars(i2.fSetRating),
'SETS_RATING': i2.fSetRating,
'SETS_RATING_STARTS': get_rating_set_for_stars(i2.fSetRating),
'SETS_DATA_MODIFY': i2.dOfferModify,
'IS_COMMERCIAL': i2.bCommercial,
})
'IS_COMMERCIAL': i2.bCommercial,
})
if len(price_frame) == offer_per_frame:
break
count_mount_dim_in_offer = 0
@@ -439,3 +442,225 @@ def report_one_win_price(request: HttpRequest, win_width_mm: str = '670', win_he
'ticks': float(time.time() - time_start)
})
return render(request, "report/report_price-offers_for_one_window.html", to_template)
def report_price(request: HttpRequest, build_id: str = "22427", apart_id: str = "61",
slug: str = "g-moskva-ul-novorossijskaya-d-16") -> HttpResponse:
""" Страница с расчетом стоимости окон
:param request: HttpRequest -- входящий http-запрос
:param build_id: str - id здания (адрес в таблице oknardia_building_info.id)
:param apart_id: str - id типовой планировки квартиры (в таблице oknardia_apartment_type.id)
:param slug: str - slug адреса здания
:return: response: HttpResponse
"""
time_start = time.time()
msg = ""
to_template = {}
try:
build_id = int(build_id)
apart_id = int(apart_id)
except ValueError:
return redirect("/")
try:
# получаем все типы квартир для данного адреса (а заодно и попутную информацию о площади дома и пр.)
q_apart = Apartment_Type.objects.raw(
f'SELECT'
f' oknardia_apartment_type.sNameApartment, oknardia_apartment_type.id,'
f' oknardia_apartment_type.iSort, oknardia_seria_info.kRoot_id,'
f' oknardia_building_info.kSeria_Link_id, oknardia_building_info.sAddress,'
f' oknardia_building_info.fGeoCode_Latitude, oknardia_building_info.fGeoCode_Longitude,'
f' oknardia_building_info.fTotal_Area, oknardia_building_info.sCadastre_Num_Area,'
f' oknardia_building_info.fLand_Area, oknardia_building_info.sInventory_Num,'
f' oknardia_building_info.iNum_Apartments, oknardia_building_info.sType,'
f' oknardia_building_info.iStoreys, oknardia_building_info.fCommon_Area,'
f' oknardia_building_info.sEnergy_Efficiency, oknardia_building_info.iEntrances_Porchs,'
f' oknardia_building_info.fUninhabited_Area, oknardia_building_info.sManagement_Co,'
f' oknardia_building_info.iElevators, oknardia_building_info.fResidential_Area,'
f' oknardia_building_info.iNum_Residents, oknardia_building_info.fPrivate_Area,'
f' oknardia_building_info.iNum_Accounts, oknardia_building_info.iCommissioning_year,'
f' oknardia_building_info.fGovernment_Area, oknardia_building_info.fCondition_House,'
f' oknardia_building_info.fCondition_Foundation, oknardia_building_info.fCondition_Walls,'
f' oknardia_building_info.fCondition_Overlap, oknardia_building_info.fMunicipal_Area,'
f' oknardia_building_info.sSerias_Project '
f'FROM oknardia_seria_info '
f'INNER JOIN oknardia_apartment_type'
f' ON oknardia_seria_info.kRoot_id = oknardia_apartment_type.kSeria_id '
f' INNER JOIN oknardia_building_info'
f' ON oknardia_building_info.kSeria_Link_id = oknardia_seria_info.id '
f'WHERE oknardia_building_info.id = {build_id} '
f'ORDER BY oknardia_apartment_type.iSort;')
list_apart = list(q_apart)
# если кто-то нахимичит ID квартиры не для этого дома, то сделаем так, что он будет от этого дома!
apart_inside = False
for i in q_apart:
if i.id == apart_id:
apart_inside = True
break
if not apart_inside or slug != pytils.translit.slugify(list_apart[0].sAddress):
# Переадресация 302, если с apart_id (ID-квартиры нахимичили) или slug-ом.
# Нужно для склейки парных URL в поисковиках
# При переходе с карты apart_id выставляем в 0. Из-за этого тоже нужно 302-переадресация.
return redirect(f"/{build_id}/{list_apart[0].id}/{pytils.translit.slugify(list_apart[0].sAddress)}")
address_latitude = list_apart[0].fGeoCode_Latitude
address_longitude = list_apart[0].fGeoCode_Longitude
to_template.update({'BUILD_ID': build_id})
to_template.update({'APPARTMENT_ID': apart_id})
to_template.update({'ADDRESS_LAT': address_latitude})
to_template.update({'ADDRESS_LON': address_longitude})
to_template.update({'ADDRESS': list_apart[0].sAddress})
to_template.update({'ADDRESS_T': pytils.translit.slugify(list_apart[0].sAddress)})
to_template.update({'SERIA': list_apart[0].sSerias_Project})
# данные нужные для отображения информации о доме (метраж, число подъездов и пр.)
to_template.update({'CADASTRE_NUM': list_apart[0].sCadastre_Num_Area})
to_template.update({'INVENTORY_NUM': list_apart[0].sInventory_Num})
to_template.update({'TYPE_BUILDING': list_apart[0].sType})
to_template.update({'ENERGY_EFFICIENCY': list_apart[0].sEnergy_Efficiency})
if list_apart[0].fTotal_Area != -1.0:
to_template.update({'TOTAL_AREA': f"{list_apart[0].fTotal_Area:.1f}"})
if list_apart[0].fLand_Area != -1.0:
to_template.update({'LAND': f"{list_apart[0].fLand_Area:.1f}"})
if list_apart[0].iNum_Apartments != -1:
to_template.update({'NUM_APARTMENTS': list_apart[0].iNum_Apartments})
if list_apart[0].iStoreys != -1:
to_template.update({'STOREYS': list_apart[0].iStoreys})
if list_apart[0].fCommon_Area != -1.0:
to_template.update({'COMMON_AREA': f"{list_apart[0].fCommon_Area:.1f}"})
if list_apart[0].iEntrances_Porchs != -1:
to_template.update({'NUM_ENTERANCES': list_apart[0].iEntrances_Porchs})
if list_apart[0].fUninhabited_Area != -1.0:
to_template.update({'UNINHABITED_AREA': f"{list_apart[0].fUninhabited_Area:.1f}"})
if list_apart[0].sManagement_Co != u"N/A":
to_template.update({'MANAGEMENT_CO': list_apart[0].sManagement_Co})
if list_apart[0].iElevators != -1:
to_template.update({'NUM_ELEVATORS': list_apart[0].iElevators})
if list_apart[0].fResidential_Area != -1.0:
to_template.update({'RESIDENTIAL_AREA': f"{list_apart[0].fResidential_Area:.1f}"})
if list_apart[0].iNum_Residents != -1:
to_template.update({'NUM_RESIDENTS': list_apart[0].iNum_Residents})
if list_apart[0].fPrivate_Area != -1.0:
to_template.update({'PRIVATE_AREA': f"{list_apart[0].fPrivate_Area:.1f}"})
if list_apart[0].iNum_Accounts != -1:
to_template.update({'NUM_ACCOUNTS': list_apart[0].iNum_Accounts})
if list_apart[0].iCommissioning_year != "N/A":
to_template.update({'COMMISSIONING_YEAR': list_apart[0].iCommissioning_year})
if list_apart[0].fGovernment_Area != -1.0:
to_template.update({'GOVERNMENT_AREA': f"{list_apart[0].fGovernment_Area:.1f}"})
if list_apart[0].fCondition_House != -1.0:
to_template.update({'CONDITION_HOUSE': f"{list_apart[0].fCondition_House:.0f}%"})
if list_apart[0].fCondition_Foundation != -1.0:
to_template.update({'CONDITION_FOUNDATION': f"{list_apart[0].fCondition_Foundation:.0f}%"})
if list_apart[0].fCondition_Walls != -1.0:
to_template.update({'CONDITION_WALL': f"{list_apart[0].fCondition_Walls:.0f}%"})
if list_apart[0].fCondition_Overlap != -1.0:
to_template.update({'CONDITION_OVERLAP': f"{list_apart[0].fCondition_Overlap:.0f}%"})
if list_apart[0].fMunicipal_Area != -1.0:
to_template.update({'MUNICIPAL_AREA': f"{list_apart[0].fMunicipal_Area:.1f}"})
# заполняем массив квартир для отправки в шаблон
apart_in_building = []
for apartment_count in q_apart:
apartment_in = {}
if apartment_count.id != apart_id:
apartment_in.update({'APT_ID': apartment_count.id})
else:
apartment_in.update({'APT_ID': "!"})
apartment_in.update({'APT_NAME': apartment_count.sNameApartment})
apart_in_building.append(apartment_in)
to_template.update({'APARTMENT_IN_BUILDING': apart_in_building})
# узнаем базовую серию дома
q_base_seria = Seria_Info.objects.get(id=list_apart[0].kRoot_id)
base_seria_slug = pytils.translit.slugify(q_base_seria.sName)
to_template.update({'BASE_SERIA': q_base_seria.sName,
'BASE_SERIA_LAT': base_seria_slug,
'BASE_SERIA_ID': q_base_seria.id})
except (ValueError, IndexError, TypeError, ObjectDoesNotExist):
return redirect("/")
###############################################
# получаем массив окон для данной квартиры...
try:
q_md = Win_MountDim.objects.raw(
f'SELECT'
f' oknardia_apartment_type.sNameApartment, oknardia_win_mountdim.iWinWidth,'
f' oknardia_win_mountdim.iWinHight, oknardia_win_mountdim.iWinDepth,'
f' oknardia_win_mountdim.sFlapConfig, oknardia_win_mountdim.bIsNearDoor,'
f' oknardia_win_mountdim.bIsDoor, oknardia_win_mountdim.sDescripion,'
f' oknardia_win_mountdim.id, oknardia_mountdim2apartment.iQuantity '
f'FROM oknardia_mountdim2apartment '
f'INNER JOIN oknardia_apartment_type'
f' ON oknardia_mountdim2apartment.kApartment_id = oknardia_apartment_type.id'
f' INNER JOIN oknardia_win_mountdim'
f' ON oknardia_mountdim2apartment.kMountDim_id = oknardia_win_mountdim.id '
f'WHERE oknardia_mountdim2apartment.kApartment_id = {apart_id} '
f'GROUP BY'
f' oknardia_apartment_type.sNameApartment, oknardia_win_mountdim.iWinWidth,'
f' oknardia_win_mountdim.iWinHight, oknardia_win_mountdim.iWinDepth,'
f' oknardia_win_mountdim.sFlapConfig, oknardia_win_mountdim.bIsNearDoor,'
f' oknardia_win_mountdim.bIsDoor, oknardia_win_mountdim.sDescripion,'
f' oknardia_apartment_type.bApartmentCheck, oknardia_win_mountdim.dMountXYZModify,'
f' oknardia_apartment_type.dApartmentModify, oknardia_win_mountdim.iWinLimit,'
f' oknardia_win_mountdim.id, oknardia_mountdim2apartment.iQuantity '
f'ORDER BY'
f' oknardia_win_mountdim.bIsNearDoor DESC,'
f' oknardia_win_mountdim.bIsDoor DESC,'
f' oknardia_win_mountdim.iWinWidth,'
f' oknardia_win_mountdim.iWinHight DESC;')
list_mount_dim_per_offer = list(q_md)
mount_dim_per_offer = len(list_mount_dim_per_offer)
to_template.update({'APART': list_mount_dim_per_offer[0].sNameApartment})
# получаем данные для отрисовки больших картинок с проемами.
to_template.update(get_flaps_for_big_pictures(q_md))
# <---
except (ValueError, IndexError, TypeError, ObjectDoesNotExist):
return redirect("/")
# получаем данные для фрейма ценовых предложений
price_frame = report_price_frame(apart_id, mount_dim_per_offer, address_longitude, address_latitude)
to_template.update(price_frame)
# print u"строк в querySet:", CountMountDimInFramePage
# dimension_to_template.update({'DISCOUNT_TXT': DiscountTXT})
to_template.update({'MOUNT_DIM_PER_OFFER': mount_dim_per_offer,
'META_DESCRIPTION': "Окнардия ",
'META_KEYWORDS': "Окнардия+ ",
'MSG': msg})
# получаем последние визиты всех посетителей из базы
log_visit = get_last_all_user_visit_list()
id_last_visit_log = log_visit[0]['id'] + 1
# print("id_last_visit_log:", id_last_visit_log)
to_template.update({'LOG_VISIT': log_visit})
if id_last_visit_log > MAX_LEN_RING_LOG_BUFFER: # максимальный размер циклического буфера
id_last_visit_log = 1 # ставим в начало буфера
try:
log_entry = LogVisitPriceReport.objects.get(id=id_last_visit_log)
log_entry.sLogAddress = to_template["ADDRESS"]
log_entry.sLogNameApartment = to_template["APART"]
log_entry.sLogURL = f"/{build_id}/{apart_id}/{to_template['ADDRESS_T']}"
log_entry.dLogVisitTime = time.time()
log_entry.save() # UPDATE
except ObjectDoesNotExist:
log_entry = LogVisitPriceReport(
sLogAddress=to_template["ADDRESS"],
sLogNameApartment=to_template["APART"],
sLogURL=f"/{build_id}/{apart_id}/{to_template['ADDRESS_T']}",
dLogVisitTime=time.time()
)
log_entry.save() # INSERT
# получаем последние визиты клиента через куки
last_visit = get_last_user_visit_cookies(request)
to_template.update({'LAST_VISIT': get_last_user_visit_list(last_visit)})
# подготавливаем данные о текущем посещении для помещения в cookie
Item = {
"LastURL": f"/{build_id}/{apart_id}/{to_template['ADDRESS_T']}",
"LastAddress": to_template["ADDRESS"],
"LastApart": to_template["APART"],
"Time": time.time()}
last_visit.insert(0, Item) # Добавляем текущий Item в начало
last_visit = json.dumps(last_visit[:3]) # упаковываем json без пробелов (три записи)
# print u"сейчас запишем вот эту куку:", LastVisit
to_template.update({'ticks': float(time.time() - time_start)})
response = render(request, "report/report_pricelist.html", to_template)
response.set_cookie("LastVisit", last_visit, max_age=7862400) # ставим или перезаписываем куки (91 день)
return response

View File

@@ -6,6 +6,7 @@ from oknardia.models import LogVisitPriceReport
# from oknardia.settings import *
# from web.add_func import normalize, get_rating_set_for_stars
# from time import time
import django.utils.dateformat
import json
import pytils
@@ -50,19 +51,20 @@ def get_last_all_user_visit_list() -> list:
:return: list -- список четырех последних посещений ценовых предложений всеми пользователями
"""
result_list_visit = []
id_fourth_visit = 0 # id четвертого посещения??? Зачем??? Не помню хоть убей!!!
# id_last_visit = 0 # id четвертого посещения??? Зачем??? Не помню хоть убей!!!
try:
q_log_visit = LogVisitPriceReport.objects.all().order_by('-dLogVisitTime')[:4]
for i in q_log_visit:
if id_fourth_visit == 0:
id_fourth_visit = i.id
# if id_last_visit == 0:
# id_last_visit = i.id
result_list_visit.append({
"Time": pytils.dt.distance_of_time_in_words(int(format(i.dLogVisitTime, 'U'))),
"id": i.id,
"Time": pytils.dt.distance_of_time_in_words(int(django.utils.dateformat.format(i.dLogVisitTime, 'U'))),
"LogURL": i.sLogURL,
"LogAddress": i.sLogAddress,
"LogApart": i.sLogNameApartment
})
except LogVisitPriceReport.DoesNotExist:
pass
# return id_fourth_visit+1, list_visit
# return id_last_visit+1, list_visit
return result_list_visit