diff --git "a/app.py" "b/app.py" --- "a/app.py" +++ "b/app.py" @@ -1,4 +1,3 @@ - from flask import Flask, render_template_string, request, redirect, url_for, send_file, flash, jsonify import json import os @@ -16,7 +15,7 @@ import uuid load_dotenv() app = Flask(__name__) -app.secret_key = 'your_unique_secret_key_meka_shop_12345_no_login' +app.secret_key = 'raina_hvac_secret_key_98765_landing' DATA_FILE = 'data.json' SYNC_FILES = [DATA_FILE] @@ -26,11 +25,7 @@ HF_TOKEN_WRITE = os.getenv("HF_TOKEN") HF_TOKEN_READ = os.getenv("HF_TOKEN_READ") CONTACT_PHONE = "+996 773 901 313" -CONTACT_PHONE_CLEAN = "".join(filter(str.isdigit, CONTACT_PHONE.split('+')[1])) - - -CURRENCY_CODE = 'KGS' -CURRENCY_NAME = 'Кыргызский сом' +WHATSAPP_PHONE = "996773901313" DOWNLOAD_RETRIES = 3 DOWNLOAD_DELAY = 5 @@ -40,13 +35,10 @@ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %( def download_db_from_hf(specific_file=None, retries=DOWNLOAD_RETRIES, delay=DOWNLOAD_DELAY): if not HF_TOKEN_READ and not HF_TOKEN_WRITE: logging.warning("HF_TOKEN_READ/HF_TOKEN_WRITE not set. Download might fail for private repos.") - token_to_use = HF_TOKEN_READ if HF_TOKEN_READ else HF_TOKEN_WRITE - files_to_download = [specific_file] if specific_file else SYNC_FILES logging.info(f"Attempting download for {files_to_download} from {REPO_ID}...") all_successful = True - for file_name in files_to_download: success = False for attempt in range(retries + 1): @@ -75,7 +67,7 @@ def download_db_from_hf(specific_file=None, retries=DOWNLOAD_RETRIES, delay=DOWN try: if file_name == DATA_FILE: with open(file_name, 'w', encoding='utf-8') as f: - json.dump({'products': [], 'categories': [], 'orders': {}, 'turnkey_services': []}, f) + json.dump({'products': [], 'categories': [], 'services': []}, f) logging.info(f"Created empty local file {file_name} because it was not found on HF.") except Exception as create_e: logging.error(f"Failed to create empty local file {file_name}: {create_e}") @@ -87,14 +79,11 @@ def download_db_from_hf(specific_file=None, retries=DOWNLOAD_RETRIES, delay=DOWN logging.error(f"Network error downloading {file_name} (Attempt {attempt + 1}): {e}. Retrying in {delay}s...") except Exception as e: logging.error(f"Unexpected error downloading {file_name} (Attempt {attempt + 1}): {e}. Retrying in {delay}s...", exc_info=True) - if attempt < retries: time.sleep(delay) - if not success: logging.error(f"Failed to download {file_name} after {retries + 1} attempts.") all_successful = False - logging.info(f"Download process finished. Overall success: {all_successful}") return all_successful @@ -106,7 +95,6 @@ def upload_db_to_hf(specific_file=None): api = HfApi() files_to_upload = [specific_file] if specific_file else SYNC_FILES logging.info(f"Starting upload of {files_to_upload} to HF repo {REPO_ID}...") - for file_name in files_to_upload: if os.path.exists(file_name): try: @@ -137,7 +125,7 @@ def periodic_backup(): logging.info("Periodic backup finished.") def load_data(): - default_data = {'products': [], 'categories': [], 'orders': {}, 'turnkey_services': []} + default_data = {'products': [], 'categories': [], 'services': []} try: with open(DATA_FILE, 'r', encoding='utf-8') as file: data = json.load(file) @@ -147,38 +135,25 @@ def load_data(): raise FileNotFoundError if 'products' not in data: data['products'] = [] if 'categories' not in data: data['categories'] = [] - if 'orders' not in data: data['orders'] = {} - if 'turnkey_services' not in data: data['turnkey_services'] = [] + if 'services' not in data: data['services'] = [] return data - except FileNotFoundError: - logging.warning(f"Local file {DATA_FILE} not found. Attempting download from HF.") - except json.JSONDecodeError: - logging.error(f"Error decoding JSON in local {DATA_FILE}. File might be corrupt. Attempting download.") - + except (FileNotFoundError, json.JSONDecodeError): + logging.warning(f"Local file {DATA_FILE} not found or corrupt. Attempting download from HF.") if download_db_from_hf(specific_file=DATA_FILE): try: with open(DATA_FILE, 'r', encoding='utf-8') as file: data = json.load(file) logging.info(f"Data loaded successfully from {DATA_FILE} after download.") - if not isinstance(data, dict): - logging.error(f"Downloaded {DATA_FILE} is not a dictionary. Using default.") - return default_data + if not isinstance(data, dict): return default_data if 'products' not in data: data['products'] = [] if 'categories' not in data: data['categories'] = [] - if 'orders' not in data: data['orders'] = {} - if 'turnkey_services' not in data: data['turnkey_services'] = [] + if 'services' not in data: data['services'] = [] return data - except FileNotFoundError: - logging.error(f"File {DATA_FILE} still not found even after download reported success. Using default.") - return default_data - except json.JSONDecodeError: - logging.error(f"Error decoding JSON in downloaded {DATA_FILE}. Using default.") - return default_data except Exception as e: logging.error(f"Unknown error loading downloaded {DATA_FILE}: {e}. Using default.", exc_info=True) return default_data else: - logging.error(f"Failed to download {DATA_FILE} from HF after retries. Using empty default data structure.") + logging.error(f"Failed to download {DATA_FILE} from HF. Using/creating empty local data.") if not os.path.exists(DATA_FILE): try: with open(DATA_FILE, 'w', encoding='utf-8') as f: @@ -188,7 +163,6 @@ def load_data(): logging.error(f"Failed to create empty local file {DATA_FILE}: {create_e}") return default_data - def save_data(data): try: if not isinstance(data, dict): @@ -196,9 +170,7 @@ def save_data(data): return if 'products' not in data: data['products'] = [] if 'categories' not in data: data['categories'] = [] - if 'orders' not in data: data['orders'] = {} - if 'turnkey_services' not in data: data['turnkey_services'] = [] - + if 'services' not in data: data['services'] = [] with open(DATA_FILE, 'w', encoding='utf-8') as file: json.dump(data, file, ensure_ascii=False, indent=4) logging.info(f"Data successfully saved to {DATA_FILE}") @@ -206,7 +178,6 @@ def save_data(data): except Exception as e: logging.error(f"Error saving data to {DATA_FILE}: {e}", exc_info=True) - LANDING_TEMPLATE = ''' @@ -214,122 +185,119 @@ LANDING_TEMPLATE = ''' ОсОО "Раина" - Вентиляция и Кондиционирование + - + +
+ +
-
-
-

ОсОО "Раина"

-

Ваш Партнер в Вентиляции и Кондиционировании

-

Обладая 15-летним опытом, мы реализовали более 1000 проектов, предлагая комплексные решения, которые обеспечивают комфорт и здоровье в любом помещении.

- Связаться с нами -
+
+

ОсОО "Раина": Ваш Партнер в Вентиляции и Кондиционировании

+

15 лет опыта, более 1000 реализованных проектов. Мы создаем комфорт и здоровье в любом помещении с помощью самых современных климатических систем.

+ Получить консультацию
@@ -337,23 +305,20 @@ LANDING_TEMPLATE = '''

О Нашей Компании

-
+ Команда Раина +

Основание и История

Компания "Раина" была основана в 2009 году. За эти годы мы зарекомендовали себя как надежный партнер, стремящийся к инновациям и совершенству в области климатических решений. Наш путь отмечен постоянным ростом и развитием.

-
-

Наша Миссия

-

Наша миссия — создание оптимального микроклимата для наших клиентов, обеспечивающего комфорт, здоровье и высокую производительность. Мы стремимся к тому, чтобы каждое помещение было источником чистого и свежего воздуха.

+

Наша миссия — создание оптимального микроклимата для наших клиентов, обеспечивающего комфорт, здоровье и высокую производительность. Мы стремимся к тому, чтобы каждое помещение, оборудованное нашими системами, было источником чистого и свежего воздуха.

+

Профессиональ��ая Команда

+

Наша команда состоит из высококвалифицированных и сертифицированных инженеров и техников, обладающих глубокими знаниями и опытом в области HVAC. Мы постоянно повышаем свою квалификацию, чтобы быть в курсе последних тенденций и технологий.

-
-

Профессиональная Команда

-

Наша команда состоит из высококвалифицированных и сертифицированных инженеров и техников, обладающих глубокими знаниями и опытом в области HVAC. Мы постоянно повышаем свою квалификацию, чтобы быть в курсе последних тенденций и технологий.

-
-
+

Наши Услуги

@@ -368,7 +333,7 @@ LANDING_TEMPLATE = '''

Осуществляем профессиональную установку всех типов систем HVAC, от бытовых кондиционеров до сложных промышленных систем.

- +

Сервис и Обслуживание

Предлагаем полный спектр услуг по плановому техническому обслуживанию и аварийному ремонту. Служба поддержки работает 24/7.

@@ -380,868 +345,169 @@ LANDING_TEMPLATE = '''
- - {% if turnkey_services %} -
+ +
-

Услуги под ключ

+

Услуги "под ключ"

+ {% if services %}
- {% for service in turnkey_services %} -
+ {% for service in services %} +
{% if service.photo %} - {{ service.name }} + {{ service.title }} {% endif %} -
- -

{{ service.name }}

+
+

{{ service.title }}

{{ service.description }}

{% endfor %}
+ {% else %} +

Информация об услугах "под ключ" скоро появится на сайте.

+ {% endif %}
- {% endif %}

Наше Оборудование

-
- + {% if products %} +
+ {% for category in categories %} - + {% endfor %}
-
+
{% for product in products %} -
-
- {% if product.get('photos') and product['photos']|length > 0 %} - {{ product['name'] }} - {% else %} - No Image - {% endif %} -
-
-

{{ product['name'] }}

-

{{ "%.2f"|format(product['price']) }} {{ currency_code }}

-
+
+ {% if product.photos %} + {{ product.name }} + {% else %} + No Image + {% endif %} +

{{ product.name }}

+

{{ "%.2f"|format(product.price) }} KGS

+ Запросить
{% endfor %} - {% if not products %} -

Оборудование пока не добавлено.

- {% endif %}
+ {% else %} +

Каталог оборудования скоро будет доступен.

+ {% endif %}
-
+

Реализованные Проекты

- Деловой Центр 'Заря' -
+ Деловой Центр Заря +

Деловой Центр "Заря"

Монтаж VRF-системы для 15 000 м² офисных площадей.

- Производственный Цех 'Техно' -
-

Цех "Техно"

-

Установка комплексной промышленной вентиляции.

+ Производственный Цех Техно +
+

Производственный Цех "Техно"

+

Установка промышленной вентиляции для удаления вредных веществ.

- Гостиница 'Аврора' -
+ Гостиница Аврора +

Гостиница "Аврора"

-

Внедрение центрального кондиционирования для 120 номеров.

+

Внедрение центральной системы кондиционирования для 120 номеров.

- Медицинский Центр 'Здоровье' -
-

Центр "Здоровье"

-

Создание "чистых помещений" ��ласса ISO 7 с фильтрацией воздуха.

+ Медицинский Центр Здоровье +
+

Медицинский Центр "Здоровье"

+

Создание "чистых помещений" класса ISO 7 с высокоэффективной фильтрацией.

-
-
-

Наши Преимущества

-
-
- -

Комплексный Подход

-

От аудита до постгарантийного сервиса — мы сопровождаем вас на каждом этапе, обеспечивая бесперебойную работу.

-
-
- -

Гарантия Качества

-

Мы предоставляем гарантию на выполненные работы до 5 лет, подтверждая нашу ответственность и надежность.

-
-
- -

Экономия

-

Наши решения позволяют оптимизировать затраты на эксплуатацию систем до 30% благодаря энергоэффективности.

-
-
- -

Оперативность

-

Среднее время реагирования на заявку составляет всего 2 часа, обеспечивая быстрое решение любых вопросов.

-
-
-
-
-
-
+

Контакты и Следующие Шаги

-
-
-

Благодарим вас за внимание к нашей презентации. Мы готовы стать вашим надежным партнером в создании идеального климата. Свяжитесь с нами для консультации или заказа.

-
- Написать в WhatsApp -
-
-
    -
  • Телефон:
    {{ contact_phone }}
  • -
  • Юр. адрес:
    г. Бишкек, ул. Токольдош 3а
  • -
  • Банк:
    Центральный филиал ОАО «Бакай Банк», БИК 124030
  • -
  • Счет(KGS):
    1240020000834408
  • -
-
+

Благодарим вас за внимание к нашей презентации. Мы готовы стать вашим надежным партнером в создании идеального климата.

+
+

Свяжитесь с нами по номеру: {{ contact_phone }}

+ Написать в WhatsApp +
+
+

Наши реквизиты: ОсОО «Раина»

+

ИНН: 00812202110194 | ОКПО: 31290279

+

Юр. адрес: г. Бишкек, ул. Токольдош 3а

+

Банк: Центральный филиал ОАО «Бакай Банк», БИК: 124030, Счет(KGS): 1240020000834408

- - - -''' - -SHOP_CATALOG_TEMPLATE = ''' - - - - - - Meka Shop - Каталог - - - - - - +
-
-
-

Meka Shop

-
-
- -
Наш адрес: Рынок Кербент, 6 ряд , 3 контейнер / 5 ряд 25 контейнер
- -
- - {% for category in categories %} - - {% endfor %} -
- -
- -
- -
- {% for product in products %} -
- {% if product.get('is_top', False) %} - Топ - {% endif %} -
- {% if product.get('photos') and product['photos']|length > 0 %} - {{ product['name'] }} - {% else %} - No Image - {% endif %} -
-
-

{{ product['name'] }}

-
{{ "%.2f"|format(product['price']) }} {{ currency_code }}
-

{{ product.get('description', '')[:50] }}{% if product.get('description', '')|length > 50 %}...{% endif %}

-
-
- - -
-
- {% endfor %} - {% if not products %} -

Товары пока не добавлены.

- {% endif %} -
-
- - - - - - +
- - -
- - - - - -''' - -PRODUCT_DETAIL_TEMPLATE = ''' -
-

{{ product['name'] }}

-
-
- {% if product.get('photos') and product['photos']|length > 0 %} - {% for photo in product['photos'] %} -
-
- {{ product['name'] }} - фото {{ loop.index }} -
-
- {% endfor %} - {% else %} -
- Изображение отсутствует -
- {% endif %} -
- {% if product.get('photos') and product['photos']|length > 1 %} -
-
-
- {% endif %} -
- -
-

Категория: {{ product.get('category', 'Без категории') }}

-

Цена: {{ "%.2f"|format(product['price']) }} {{ currency_code }}

-

Описание:
{{ product.get('description', 'Описание отсутствует.')|replace('\\n', '
')|safe }}

- {% set colors = product.get('colors', []) %} - {% if colors and colors|select('ne', '')|list|length > 0 %} -

Доступные цвета/варианты: {{ colors|select('ne', '')|join(', ') }}

- {% endif %} -
-
-''' - -ORDER_TEMPLATE = ''' - - - - - - Заказ №{{ order.id }} - Meka Shop - - - - - -
- {% if order %} -

Ваш Заказ №{{ order.id }}

-

Дата создания: {{ order.created_at }}

- -

Товары в заказе

-
- {% for item in order.cart %} -
- {{ item.name }} -
- {{ item.name }} {% if item.color != 'N/A' %}({{ item.color }}){% endif %} - {{ "%.2f"|format(item.price) }} {{ currency_code }} × {{ item.quantity }} -
-
- {{ "%.2f"|format(item.price * item.quantity) }} {{ currency_code }} -
-
- {% endfor %} -
- -
-

Общая сумма товаров: {{ "%.2f"|format(order.total_price) }} {{ currency_code }}

-

ИТОГО К ОПЛАТЕ: {{ "%.2f"|format(order.total_price) }} {{ currency_code }}

-
- -
-

Статус заказа

-

Этот заказ был оформлен без входа в систему.

-

Пожалуйста, свяжитесь с нами по WhatsApp для подтверждения и уточнения деталей.

-
- -
- -
- - ← Вернуться в каталог Meka Shop - - - - {% else %} -

Ошибка

-

Заказ с таким ID не найден.

- ← Вернуться в каталог Meka Shop - {% endif %} -
+ }); + ''' @@ -1256,44 +522,40 @@ ADMIN_TEMPLATE = '''