| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479 |
- import re
- from django.conf import settings
- from django.core.mail import EmailMessage, get_connection
- from django.http import Http404, HttpResponseRedirect
- from django.shortcuts import render
- from landing.forms import MyForm, OrderForm, SERVICE_CHOICES
- from landing.models import FAQmodel, LandingMainPageSettings, LandingPage, LandingTeamMember
- from landing.utils import (
- get_faq_response,
- get_landing_category_agreement_url,
- get_landing_service_agreement_data,
- )
- from dbsynce.lib import dicts
- from dbsynce.lib.geolocation import CoordinatesValidationError, parse_coordinates
- from dbsynce.models import Provider, Service, ServiceCategory
- from dbsynce.services.service_catalog import (
- build_public_service_catalog,
- get_public_category_catalog,
- get_public_tariff_catalog,
- user_can_order_catalog,
- )
- from sharix_admin.models import Metaservice
- import core.settings_vars as sv
- def get_current_metaservice():
- try:
- return Metaservice.objects.order_by('-created_at').first()
- except Exception:
- return None
- def get_landing_settings():
- return LandingMainPageSettings.get_current()
- def get_active_service_categories():
- return [item["object"] for item in build_public_service_catalog()]
- def prepare_landing_catalog(request, catalog, metaservice=None):
- for category_card in catalog:
- category_card["agreement_url"] = get_landing_category_agreement_url(
- request,
- category_card["object"],
- metaservice=metaservice,
- )
- return catalog
- def send_email_mess(body, sub):
- with get_connection(
- host=settings.EMAIL_HOST,
- port=settings.EMAIL_PORT,
- username=settings.EMAIL_HOST_USER,
- password=settings.EMAIL_HOST_PASSWORD,
- use_tls=settings.EMAIL_USE_TLS,
- use_ssl=settings.EMAIL_USE_SSL
- ) as connection:
- subject = sub
- email_from = settings.EMAIL_HOST_USER
- recipient_list = [settings.EMAIL_TO]
- EmailMessage(subject, body, email_from, recipient_list, connection=connection).send()
- def index_html(request):
- form = MyForm(request.POST or None)
- if request.method == 'POST' and form.is_valid():
- body = f"""
- Имя: {form.cleaned_data['name']}\n
- Email: {form.cleaned_data['email']}\n
- Комментарий: {form.cleaned_data['message']}
- """
- send_email_mess(body, "Пользователь оставил отзыв")
- metaservice = get_current_metaservice()
- service_catalog = prepare_landing_catalog(
- request,
- build_public_service_catalog(),
- metaservice=metaservice,
- )
- context = {
- "menu": [item["object"] for item in service_catalog],
- "service_catalog": service_catalog,
- "can_order_catalog": user_can_order_catalog(request.user),
- "form": form,
- "metaservice": metaservice,
- "landing_settings": get_landing_settings(),
- "landing_team_members": (
- LandingTeamMember.objects
- .filter(is_active=True)
- .select_related('user')
- .order_by('sort_order', 'id')
- ),
- }
- return render(request, 'landing/pages/main.html', context=context)
- def page_html(request):
- form = MyForm(request.POST or None)
- slug = request.path[1:-1]
- metaservice = get_current_metaservice()
- mainpage = LandingPage.objects.filter(slug=slug).first()
- menu = LandingPage.objects.filter(slug__startswith='clean')
- if mainpage is None:
- return render(request, 'landing/pages/in_work.html', context={
- "form": form,
- "menu": menu,
- "metaservice": metaservice,
- })
- return render(request, 'landing/pages/simple.html', context={
- "mainpage": mainpage,
- "form": form,
- "menu": menu,
- "metaservice": metaservice,
- })
- def service_category_html(request, pk):
- category_catalog = get_public_category_catalog(pk)
- if category_catalog is None:
- raise Http404('Service category does not exist')
- metaservice = get_current_metaservice()
- service_catalog = prepare_landing_catalog(
- request,
- build_public_service_catalog(),
- metaservice=metaservice,
- )
- category_catalog["agreement_url"] = get_landing_category_agreement_url(
- request,
- category_catalog["object"],
- metaservice=metaservice,
- )
- context = {
- "menu": [item["object"] for item in service_catalog],
- "category_catalog": category_catalog,
- "service_category": category_catalog["object"],
- "services_cards": category_catalog["tariffs"],
- "can_order_catalog": user_can_order_catalog(request.user),
- "metaservice": metaservice,
- }
- return render(request, 'landing/pages/service_category.html', context=context)
- def service_detail_html(request, pk):
- tariff_catalog = get_public_tariff_catalog(pk)
- if tariff_catalog is None:
- raise Http404('Service does not exist')
- service = tariff_catalog["object"]
- metaservice = get_current_metaservice()
- service_catalog = prepare_landing_catalog(
- request,
- build_public_service_catalog(),
- metaservice=metaservice,
- )
- provider_cards = tariff_catalog["offers"]
- for index, provider_card in enumerate(provider_cards, start=1):
- provider_card["offer_number"] = index
- service_agreement_data = get_landing_service_agreement_data(
- request=request,
- service=service,
- metaservice=metaservice,
- )
- context = {
- "menu": [item["object"] for item in service_catalog],
- "service": service,
- "tariff_catalog": tariff_catalog,
- "provider_cards": provider_cards,
- "active_providers": [item["object"] for item in provider_cards],
- "can_order_catalog": user_can_order_catalog(request.user),
- "metaservice": metaservice,
- "service_agreement_data": service_agreement_data,
- "service_agreement": service_agreement_data,
- }
- return render(request, 'landing/pages/service_detail.html', context=context)
- def send_email(request):
- if request.method == 'POST':
- request.POST.get('email')
- return HttpResponseRedirect('/')
- def make_unique_address_variants(items):
- result = []
- seen = set()
- for item in items:
- value = str(item or '').strip()
- value = re.sub(r'\s+', ' ', value).strip(' ,.;')
- if not value:
- continue
- key = value.lower()
- if key in seen:
- continue
- seen.add(key)
- result.append(value)
- return result
- def clean_legal_address_for_map(address):
- value = str(address or '').strip()
- if not value:
- return ''
- # Убираем почтовый индекс в начале: 199155, ...
- value = re.sub(r'^\s*\d{5,6}\s*,?\s*', '', value)
- # Убираем офисно-юридические уточнения, которые обычно мешают геокодеру.
- value = re.sub(
- r'\b(помещ|помещение|офис|каб|кабинет|комн|комната|этаж)\.?\s*[^,;]*',
- '',
- value,
- flags=re.IGNORECASE,
- )
- # Нормализуем частые русские сокращения.
- value = re.sub(r'\bгород\b\s*', '', value, flags=re.IGNORECASE)
- value = re.sub(r'\bг\.\s*', '', value, flags=re.IGNORECASE)
- value = re.sub(r'\bул\.\s*', 'улица ', value, flags=re.IGNORECASE)
- value = re.sub(r'\bпр-?т\.?\s*', 'проспект ', value, flags=re.IGNORECASE)
- value = re.sub(r'\bпер\.\s*', 'переулок ', value, flags=re.IGNORECASE)
- value = re.sub(r'\bнаб\.\s*', 'набережная ', value, flags=re.IGNORECASE)
- value = re.sub(r'\bд\.\s*', '', value, flags=re.IGNORECASE)
- # "32 к 1" -> "32 корпус 1"
- value = re.sub(r'(\d+)\s*к\s*(\d+)', r'\1 корпус \2', value, flags=re.IGNORECASE)
- # "литер д" / "литера д" -> "литера д"
- value = re.sub(r'\bлитер(?:а)?\.?\s*([а-яa-z])\b', r'литера \1', value, flags=re.IGNORECASE)
- # Чистим лишние запятые и пробелы.
- value = re.sub(r'\s*,\s*', ', ', value)
- value = re.sub(r'(,\s*)+', ', ', value)
- value = re.sub(r'\s+', ' ', value).strip(' ,.;')
- return value
- def build_contact_address_variants(address):
- original = str(address or '').strip()
- if not original:
- return []
- cleaned = clean_legal_address_for_map(original)
- # Вариант без литеры часто находится лучше.
- cleaned_without_litera = re.sub(
- r'\s*,?\s*литера\s+[а-яa-z]\b',
- '',
- cleaned,
- flags=re.IGNORECASE,
- ).strip(' ,.;')
- # Вариант без корпуса иногда тоже помогает.
- cleaned_without_korpus = re.sub(
- r'\s+корпус\s+\d+\b',
- '',
- cleaned_without_litera,
- flags=re.IGNORECASE,
- ).strip(' ,.;')
- variants = [
- cleaned,
- cleaned_without_litera,
- cleaned_without_korpus,
- original,
- ]
- variants_with_country = []
- for value in variants:
- if not value:
- continue
- variants_with_country.append(value)
- if 'россия' not in value.lower():
- variants_with_country.append(f'Россия, {value}')
- return make_unique_address_variants(variants_with_country)
- def normalize_contact_address(address):
- variants = build_contact_address_variants(address)
- if variants:
- return variants[0]
- return ''
- def get_first_object_value(obj, *field_names, default=''):
- if obj is None:
- return default
- for field_name in field_names:
- if not hasattr(obj, field_name):
- continue
- value = getattr(obj, field_name)
- if callable(value):
- continue
- if value is not None and str(value).strip() != '':
- return value
- return default
- def contact_html(request):
- metaservice = get_current_metaservice()
- address = metaservice.address if metaservice and metaservice.address else 'г. Москва, ул. Большая Ордынка 5к3'
- contact_data = {
- 'email': metaservice.email if metaservice and metaservice.email else 'email@sharix.org',
- 'phone': metaservice.phone if metaservice and metaservice.phone else '',
- 'address': address,
- 'map_search_address': normalize_contact_address(address),
- 'map_search_variants': build_contact_address_variants(address),
- 'legal_name': metaservice.legal_name if metaservice and metaservice.legal_name else 'SHARiX',
- 'inn': metaservice.inn if metaservice and metaservice.inn else '',
- 'kpp': metaservice.kpp if metaservice and metaservice.kpp else '',
- 'ogrn': metaservice.ogrn if metaservice and metaservice.ogrn else '',
- 'bank_name': metaservice.bank_name if metaservice and metaservice.bank_name else '',
- 'bik': metaservice.bik if metaservice and metaservice.bik else '',
- 'rs': metaservice.rs if metaservice and metaservice.rs else '',
- 'ks': metaservice.ks if metaservice and metaservice.ks else '',
- }
- context = {
- "menu": get_active_service_categories(),
- "contact": contact_data,
- "metaservice": metaservice,
- }
- return render(request, 'landing/pages/contact.html', context)
- def price_html(request):
- return render(request, 'landing/pages/price.html', {
- "menu": get_active_service_categories(),
- "metaservice": get_current_metaservice(),
- })
- def order_html(request):
- metaservice = get_current_metaservice()
- form = OrderForm(request.POST or None)
- if request.method == 'POST' and form.is_valid():
- services = ""
- for item in form.cleaned_data['service']:
- services += f"{SERVICE_CHOICES[int(item)][1]}, "
- body = f"""
- Имя: {form.cleaned_data['name']}\n
- Фамилия: {form.cleaned_data['surname']}\n
- Номер телефона: {form.cleaned_data['phone']}\n
- Выбранные услуги: {services}\n
- Желаемое время оказания услуги: {form.cleaned_data['datetime']}\n
- Комментарий: {form.cleaned_data['comment'] or "Комментарий отсутствует"}
- """
- send_email_mess(body, "ЗАКАЗ")
- context = {
- "form": form,
- "menu": get_active_service_categories(),
- "metaservice": metaservice,
- }
- return render(request, 'landing/pages/order.html', context)
- def faq_html(request):
- prompt = ""
- answer = None
- landing_settings = get_landing_settings()
- if request.method == "POST":
- prompt = (request.POST.get("prompt") or "").strip()
- if prompt:
- answer = get_faq_response(prompt, landing_settings)
- else:
- answer = "Введите текст вопроса."
- context = {
- "form": MyForm(),
- "menu": get_active_service_categories(),
- "faq": FAQmodel.objects.all(),
- "metaservice": get_current_metaservice(),
- "landing_settings": landing_settings,
- "prompt": prompt,
- "answer": answer,
- }
- return render(request, 'landing/pages/faq.html', context)
- def parse_provider_location(provider, offer_number):
- """Build a public marker only from a valid static point."""
- if provider.location_type != dicts.location_type["static"]:
- return None
- raw_location = str(provider.default_location or "").strip()
- if not raw_location:
- return None
- try:
- point = parse_coordinates(raw_location)
- except CoordinatesValidationError:
- return None
- title = f"Предложение {offer_number}"
- service_caption = provider.service.caption if provider.service else ""
- company_name = provider.company.legal_name if provider.company else ""
- return {
- "id": provider.pk,
- "title": title,
- "service": service_caption,
- "company": company_name,
- "location": raw_location,
- "lat": float(point.latitude),
- "lng": float(point.longitude),
- }
- def providers_map_html(request):
- providers = (
- Provider.objects
- .filter(status='0', is_visible='t')
- .select_related('service', 'company')
- .order_by('id')
- )
- offer_markers = [
- item
- for item in (
- parse_provider_location(provider, index)
- for index, provider in enumerate(providers, start=1)
- )
- if item
- ]
- context = {
- "menu": get_active_service_categories(),
- "metaservice": get_current_metaservice(),
- "offer_markers": offer_markers,
- }
- return render(request, 'landing/pages/providers_map.html', context)
- def ai_demo_html(request):
- return faq_html(request)
- def support_html(request):
- return faq_html(request)
|