fully functional. UX/UI stage
@@ -1,162 +1,40 @@
|
|||||||
# import telebot
|
|
||||||
# from decouple import config
|
|
||||||
# from django.shortcuts import get_object_or_404
|
|
||||||
# from web.models import Client, ServiceRequest, Order
|
|
||||||
# from comunication.models import TelegramSettings
|
|
||||||
# import re
|
|
||||||
# import base64
|
|
||||||
# import logging
|
|
||||||
|
|
||||||
# class TelegramBot:
|
|
||||||
# def __init__(self):
|
|
||||||
# # Get bot settings from the database
|
|
||||||
# bot_settings = TelegramSettings.objects.first()
|
|
||||||
# if bot_settings:
|
|
||||||
# TELEGRAM_BOT_TOKEN = bot_settings.bot_token
|
|
||||||
# self.bot = telebot.TeleBot(TELEGRAM_BOT_TOKEN)
|
|
||||||
# else:
|
|
||||||
# raise Exception("Telegram bot settings not found")
|
|
||||||
|
|
||||||
# def start_bot_polling(self):
|
|
||||||
# @self.bot.message_handler(commands=['start'])
|
|
||||||
# def send_welcome(message):
|
|
||||||
# # Проверяем, содержатся ли параметры в команде /start
|
|
||||||
# match = re.match(r'/start request_(\d+)_token_(.*)', message.text)
|
|
||||||
# if match:
|
|
||||||
# self.handle_confirm_command(message, match)
|
|
||||||
# elif message.text.strip() == '/start':
|
|
||||||
# self.bot.reply_to(message, "Ошибка: Некорректная команда. Пожалуйста, используйте ссылку, предоставленную на сайте для регистрации.")
|
|
||||||
# else:
|
|
||||||
# self.bot.reply_to(message, "Здравствуйте! Чем я могу помочь? Вы можете задать вопросы о статусе заявки или заказе.")
|
|
||||||
|
|
||||||
# @self.bot.message_handler(func=lambda message: 'статус заявки' in message.text.lower())
|
|
||||||
# def handle_service_request_status(message):
|
|
||||||
# chat_id = message.chat.id
|
|
||||||
# client = Client.objects.filter(chat_id=chat_id).first()
|
|
||||||
# if client:
|
|
||||||
# service_requests = ServiceRequest.objects.filter(client_email=client.email)
|
|
||||||
# if service_requests.exists():
|
|
||||||
# response = "Ваши заявки:\n"
|
|
||||||
# for req in service_requests:
|
|
||||||
# response += f"Номер заявки: {req.id}, Услуга: {req.service.name}, Дата создания: {req.created_at.strftime('%d-%m-%Y')}\n"
|
|
||||||
# else:
|
|
||||||
# response = "У вас нет активных заявок."
|
|
||||||
# else:
|
|
||||||
# response = "Клиент не найден. Пожалуйста, зарегистрируйтесь."
|
|
||||||
# self.bot.reply_to(message, response)
|
|
||||||
|
|
||||||
# @self.bot.message_handler(func=lambda message: 'статус заказа' in message.text.lower())
|
|
||||||
# def handle_order_status(message):
|
|
||||||
# chat_id = message.chat.id
|
|
||||||
# client = Client.objects.filter(chat_id=chat_id).first()
|
|
||||||
# if client:
|
|
||||||
# orders = Order.objects.filter(client=client)
|
|
||||||
# if orders.exists():
|
|
||||||
# response = "Ваши заказы:\n"
|
|
||||||
# for order in orders:
|
|
||||||
# response += f"Номер заказа: {order.id}, Услуга: {order.service.name}, Статус: {order.get_status_display()}\n"
|
|
||||||
# else:
|
|
||||||
# response = "У вас нет активных заказов."
|
|
||||||
# else:
|
|
||||||
# response = "Клиент не найден. Пожалуйста, зарегистрируйтесь."
|
|
||||||
# self.bot.reply_to(message, response)
|
|
||||||
|
|
||||||
# self.bot.polling(non_stop=True)
|
|
||||||
|
|
||||||
# def handle_confirm_command(self, message, match=None):
|
|
||||||
# chat_id = message.chat.id
|
|
||||||
# if not match:
|
|
||||||
# match = re.match(r'/start request_(\d+)_token_(.*)', message.text)
|
|
||||||
# if match:
|
|
||||||
# request_id = match.group(1)
|
|
||||||
# encoded_token = match.group(2)
|
|
||||||
|
|
||||||
# # Декодируем токен из base64
|
|
||||||
# try:
|
|
||||||
# token = base64.urlsafe_b64decode(encoded_token + '==').decode('utf-8')
|
|
||||||
# logging.info(f"Декодированный токен: {token}")
|
|
||||||
# except Exception as e:
|
|
||||||
# logging.error(f"Ошибка при декодировании токена: {e}")
|
|
||||||
# self.bot.send_message(chat_id, "Ошибка: Некорректный токен. Пожалуйста, повторите попытку позже.")
|
|
||||||
# return
|
|
||||||
|
|
||||||
# # Получаем заявку по ID и токену
|
|
||||||
# service_request = ServiceRequest.objects.filter(id=request_id, token=token).first()
|
|
||||||
# if service_request:
|
|
||||||
# # Обновляем chat_id клиента
|
|
||||||
# service_request.chat_id = chat_id
|
|
||||||
# service_request.client_name = message.from_user.first_name
|
|
||||||
# service_request.save()
|
|
||||||
|
|
||||||
# response_message = (
|
|
||||||
# f"Здравствуйте, {message.from_user.first_name}!\n"
|
|
||||||
# f"Ваша заявка на услугу успешно зарегистрирована. "
|
|
||||||
# f"Пожалуйста, вернитесь на сайт для продолжения оформления."
|
|
||||||
# )
|
|
||||||
# else:
|
|
||||||
# response_message = "Ошибка: Неверная заявка или токен. Пожалуйста, проверьте ссылку."
|
|
||||||
|
|
||||||
# self.bot.send_message(chat_id, response_message)
|
|
||||||
# else:
|
|
||||||
# response_message = "Ошибка: Некорректная команда. Пожалуйста, используйте ссылку, предоставленную на сайте для регистрации."
|
|
||||||
# self.bot.send_message(chat_id, response_message)
|
|
||||||
|
|
||||||
# def send_telegram_message(self, client_id, service_request_id, custom_message, order_id=None):
|
|
||||||
# # Get the client and service request from the database
|
|
||||||
# client = get_object_or_404(Client, pk=client_id)
|
|
||||||
# service_request = get_object_or_404(ServiceRequest, pk=service_request_id)
|
|
||||||
# chat_id = client.chat_id
|
|
||||||
|
|
||||||
# # Build the message content
|
|
||||||
# message = f"Здравствуйте, {client.first_name} {client.last_name}!\n"
|
|
||||||
# message += custom_message
|
|
||||||
|
|
||||||
# if order_id:
|
|
||||||
# order = get_object_or_404(Order, pk=order_id)
|
|
||||||
# message += f"\n\nДетали заказа:\nУслуга: {order.service.name}\nСтатус: {order.get_status_display()}\n"
|
|
||||||
|
|
||||||
# # Add service request details
|
|
||||||
# message += f"\nНомер заявки: {service_request.id}\nДата создания заявки: {service_request.created_at.strftime('%d-%m-%Y')}\n"
|
|
||||||
|
|
||||||
# # Send the message using the bot
|
|
||||||
# try:
|
|
||||||
# self.bot.send_message(chat_id, message)
|
|
||||||
# except Exception as e:
|
|
||||||
# logging.error(f"Ошибка при отправке сообщения в Telegram: {e}")
|
|
||||||
|
|
||||||
|
|
||||||
import telebot
|
|
||||||
from telebot import types
|
|
||||||
from decouple import config
|
|
||||||
from django.shortcuts import get_object_or_404
|
|
||||||
from web.models import Client, ServiceRequest, Order
|
|
||||||
from comunication.models import TelegramSettings
|
|
||||||
import re
|
|
||||||
import base64
|
|
||||||
import logging
|
import logging
|
||||||
|
import json
|
||||||
|
import requests
|
||||||
|
import os
|
||||||
|
import base64
|
||||||
|
import re
|
||||||
|
from comunication.models import TelegramSettings
|
||||||
|
from web.models import ServiceRequest, Order, Project, Client, User
|
||||||
|
import telebot
|
||||||
|
from django.shortcuts import get_object_or_404
|
||||||
|
from django.utils.crypto import get_random_string
|
||||||
|
|
||||||
class TelegramBot:
|
class TelegramBot:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# Get bot settings from the database
|
# Получение настроек бота из базы данных
|
||||||
bot_settings = TelegramSettings.objects.first()
|
bot_settings = TelegramSettings.objects.first()
|
||||||
if bot_settings:
|
if bot_settings:
|
||||||
TELEGRAM_BOT_TOKEN = bot_settings.bot_token
|
TELEGRAM_BOT_TOKEN = bot_settings.bot_token
|
||||||
self.bot = telebot.TeleBot(TELEGRAM_BOT_TOKEN)
|
self.bot = telebot.TeleBot(TELEGRAM_BOT_TOKEN)
|
||||||
|
logging.info("[TelegramBot] Бот инициализирован с токеном.")
|
||||||
else:
|
else:
|
||||||
raise Exception("Telegram bot settings not found")
|
raise Exception("Telegram bot settings not found")
|
||||||
|
|
||||||
def start_bot_polling(self):
|
def start_bot_polling(self):
|
||||||
|
logging.info("[TelegramBot] Бот начал работу в режиме polling.")
|
||||||
|
|
||||||
@self.bot.message_handler(commands=['start'])
|
@self.bot.message_handler(commands=['start'])
|
||||||
def send_welcome(message):
|
def send_welcome(message):
|
||||||
# Проверяем, содержатся ли параметры в команде /start
|
# Проверяем, содержатся ли параметры в команде /start
|
||||||
match = re.match(r'/start request_(\d+)_token_(.*)', message.text)
|
match = re.match(r'/start request_(\d+)_token_(.*)', message.text)
|
||||||
|
logging.info(f"[TelegramBot] Получена команда /start: {message.text}")
|
||||||
|
|
||||||
if match:
|
if match:
|
||||||
self.handle_confirm_command(message, match)
|
self.handle_confirm_command(message, match)
|
||||||
elif message.text.strip() == '/start':
|
elif message.text.strip() == '/start':
|
||||||
kbd = types.InlineKeyboardMarkup()
|
# Ответ на просто команду /start без параметров
|
||||||
url_btn = types.InlineKeyboardButton('Перейти на сайт', url=config("URL"))
|
self.bot.reply_to(message, "Здравствуйте! Пожалуйста, используйте команду /start с корректными параметрами для подтверждения регистрации.")
|
||||||
kbd.add(url_btn)
|
|
||||||
self.bot.reply_to(message, "Здравствуйте! Данный бот предназначен для информирования клиентов SmartSolTech и регистрации на сайте. Пройдите на сайт для получения информации.", reply_markup = kbd)
|
|
||||||
else:
|
else:
|
||||||
self.bot.reply_to(message, "Здравствуйте! Пожалуйста, используйте команду /start с корректными параметрами для подтверждения регистрации.")
|
self.bot.reply_to(message, "Здравствуйте! Пожалуйста, используйте команду /start с корректными параметрами для подтверждения регистрации.")
|
||||||
|
|
||||||
@@ -165,14 +43,17 @@ class TelegramBot:
|
|||||||
chat_id = message.chat.id
|
chat_id = message.chat.id
|
||||||
client = Client.objects.filter(chat_id=chat_id).first()
|
client = Client.objects.filter(chat_id=chat_id).first()
|
||||||
if client:
|
if client:
|
||||||
service_requests = ServiceRequest.objects.filter(chat_id=client.chat_id)
|
service_requests = ServiceRequest.objects.filter(client=client)
|
||||||
if service_requests.exists():
|
if service_requests.exists():
|
||||||
response = "Ваши заявки:\n"
|
response = "Ваши заявки:\n"
|
||||||
for req in service_requests:
|
for req in service_requests:
|
||||||
response += f"Номер заявки: {req.id}\n" \
|
response += (
|
||||||
f"Услуга: {req.service.name}\n" \
|
f"Номер заявки: {req.id}\n"
|
||||||
f"Дата создания: {req.created_at.strftime('%Y-%m-%d')}\n" \
|
f"Услуга: {req.service.name}\n"
|
||||||
f"UID заявки: {req.token}\n"
|
f"Дата создания: {req.created_at.strftime('%Y-%m-%d')}\n"
|
||||||
|
f"UID заявки: {req.token}\n"
|
||||||
|
f"Подтверждена: {'Да' if req.is_verified else 'Нет'}\n\n"
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
response = "У вас нет активных заявок."
|
response = "У вас нет активных заявок."
|
||||||
else:
|
else:
|
||||||
@@ -188,19 +69,52 @@ class TelegramBot:
|
|||||||
if orders.exists():
|
if orders.exists():
|
||||||
response = "Ваши заказы:\n"
|
response = "Ваши заказы:\n"
|
||||||
for order in orders:
|
for order in orders:
|
||||||
response += f"Номер заказа: {order.id}, Услуга: {order.service.name}, Статус: {order.get_status_display()}\n"
|
response += (
|
||||||
|
f"Номер заказа: {order.id}\n"
|
||||||
|
f"Услуга: {order.service.name}\n"
|
||||||
|
f"Статус: {order.get_status_display()}\n\n"
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
response = "У вас нет активных заказов."
|
response = "У вас нет активных заказов."
|
||||||
else:
|
else:
|
||||||
response = "Клиент не найден. Пожалуйста, зарегистрируйтесь."
|
response = "Клиент не найден. Пожалуйста, зарегистрируйтесь."
|
||||||
self.bot.reply_to(message, response)
|
self.bot.reply_to(message, response)
|
||||||
|
|
||||||
self.bot.polling(non_stop=True)
|
@self.bot.message_handler(func=lambda message: 'статус проекта' in message.text.lower())
|
||||||
|
def handle_project_status(message):
|
||||||
|
chat_id = message.chat.id
|
||||||
|
client = Client.objects.filter(chat_id=chat_id).first()
|
||||||
|
if client:
|
||||||
|
projects = Project.objects.filter(order__client=client)
|
||||||
|
if projects.exists():
|
||||||
|
response = "Ваши проекты:\n"
|
||||||
|
for project in projects:
|
||||||
|
response += (
|
||||||
|
f"Номер проекта: {project.id}\n"
|
||||||
|
f"Название проекта: {project.name}\n"
|
||||||
|
f"Статус: {project.get_status_display()}\n"
|
||||||
|
f"Дата завершения: {project.completion_date.strftime('%Y-%m-%d') if project.completion_date else 'В процессе'}\n\n"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
response = "У вас нет активных проектов."
|
||||||
|
else:
|
||||||
|
response = "Клиент не найден. Пожалуйста, зарегистрируйтесь."
|
||||||
|
self.bot.reply_to(message, response)
|
||||||
|
|
||||||
|
|
||||||
|
# Запуск бота
|
||||||
|
try:
|
||||||
|
self.bot.polling(non_stop=True)
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"[TelegramBot] Ошибка при запуске polling: {e}")
|
||||||
|
|
||||||
def handle_confirm_command(self, message, match=None):
|
def handle_confirm_command(self, message, match=None):
|
||||||
chat_id = message.chat.id
|
chat_id = message.chat.id
|
||||||
|
logging.info(f"[TelegramBot] Получено сообщение для подтверждения: {message.text}")
|
||||||
|
|
||||||
if not match:
|
if not match:
|
||||||
match = re.match(r'/start request_(\d+)_token_(.*)', message.text)
|
match = re.match(r'/start request_(\d+)_token_(.*)', message.text)
|
||||||
|
|
||||||
if match:
|
if match:
|
||||||
request_id = match.group(1)
|
request_id = match.group(1)
|
||||||
encoded_token = match.group(2)
|
encoded_token = match.group(2)
|
||||||
@@ -208,61 +122,88 @@ class TelegramBot:
|
|||||||
# Декодируем токен
|
# Декодируем токен
|
||||||
try:
|
try:
|
||||||
token = base64.urlsafe_b64decode(encoded_token + '==').decode('utf-8')
|
token = base64.urlsafe_b64decode(encoded_token + '==').decode('utf-8')
|
||||||
|
logging.info(f"[TelegramBot] Декодированный токен: {token}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
logging.error(f"[TelegramBot] Ошибка при декодировании токена: {e}")
|
||||||
self.bot.send_message(chat_id, "Ошибка: Некорректный токен. Пожалуйста, повторите попытку позже.")
|
self.bot.send_message(chat_id, "Ошибка: Некорректный токен. Пожалуйста, повторите попытку позже.")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Получаем заявку
|
# Получаем заявку
|
||||||
service_request = ServiceRequest.objects.filter(id=request_id, token=token).first()
|
try:
|
||||||
if service_request:
|
service_request = ServiceRequest.objects.get(id=request_id, token=token)
|
||||||
# Обновляем chat_id клиента
|
logging.info(f"[TelegramBot] Заявка найдена: {service_request}")
|
||||||
service_request.chat_id = chat_id
|
except ServiceRequest.DoesNotExist:
|
||||||
service_request.client_name = message.from_user.first_name
|
logging.error(f"[TelegramBot] Заявка с id {request_id} и токеном {token} не найдена.")
|
||||||
service_request.save()
|
self.bot.send_message(chat_id, "Ошибка: Неверная заявка или токен. Пожалуйста, проверьте ссылку.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Если заявка найдена, обновляем и подтверждаем клиента
|
||||||
|
if service_request:
|
||||||
|
service_request.chat_id = chat_id
|
||||||
|
service_request.is_verified = True # Обновляем статус на подтвержденный
|
||||||
|
service_request.save()
|
||||||
|
logging.info(f"[TelegramBot] Заявка {service_request.id} подтверждена и обновлена.")
|
||||||
|
|
||||||
|
# Обновляем или создаем клиента, связанного с заявкой
|
||||||
|
client = service_request.client
|
||||||
|
|
||||||
|
# Проверяем, существует ли связанный пользователь, если нет — создаем его
|
||||||
|
if not client.user:
|
||||||
|
user, created = User.objects.get_or_create(
|
||||||
|
email=client.email,
|
||||||
|
defaults={
|
||||||
|
'username': f"{client.email.split('@')[0]}_{get_random_string(5)}",
|
||||||
|
'first_name': message.from_user.first_name,
|
||||||
|
'last_name': message.from_user.last_name if message.from_user.last_name else ''
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if not created:
|
||||||
|
# Если пользователь уже существовал, обновляем его данные
|
||||||
|
user.first_name = message.from_user.first_name
|
||||||
|
if message.from_user.last_name:
|
||||||
|
user.last_name = message.from_user.last_name
|
||||||
|
user.save()
|
||||||
|
logging.info(f"[TelegramBot] Обновлен пользователь {user.username} с данными из Телеграм.")
|
||||||
|
|
||||||
|
# Связываем клиента с пользователем
|
||||||
|
client.user = user
|
||||||
|
client.save()
|
||||||
|
|
||||||
# Отправляем данные обратно на сервер для создания заявки
|
|
||||||
data = {
|
|
||||||
"service_request_id": request_id,
|
|
||||||
"client_name": message.from_user.first_name,
|
|
||||||
"client_chat_id": chat_id
|
|
||||||
}
|
|
||||||
response = requests.post('http://localhost:8000/service/send_telegram_notification/', json=data)
|
|
||||||
if response.status_code == 200:
|
|
||||||
self.bot.send_message(chat_id, "Ваш аккаунт успешно подтвержден! Вернитесь на сайт для продолжения.")
|
|
||||||
else:
|
else:
|
||||||
self.bot.send_message(chat_id, "Ошибка при подтверждении. Пожалуйста, повторите попытку позже.")
|
# Обновляем данные существующего пользователя
|
||||||
|
user = client.user
|
||||||
|
user.first_name = message.from_user.first_name
|
||||||
|
if message.from_user.last_name:
|
||||||
|
user.last_name = message.from_user.last_name
|
||||||
|
user.save()
|
||||||
|
logging.info(f"[TelegramBot] Пользователь {user.username} обновлен с данными из Телеграм.")
|
||||||
|
|
||||||
|
# Обновляем chat_id клиента
|
||||||
|
client.chat_id = chat_id
|
||||||
|
client.save()
|
||||||
|
logging.info(f"[TelegramBot] Клиент {client.id} обновлен с chat_id {chat_id}")
|
||||||
|
|
||||||
|
# Отправляем сообщение пользователю в Telegram с подтверждением и информацией о заявке
|
||||||
|
confirmation_message = (
|
||||||
|
f"Здравствуйте, {client.first_name}!\n\n"
|
||||||
|
f"Ваш аккаунт успешно подтвержден! 🎉\n\n"
|
||||||
|
f"Детали вашей заявки:\n"
|
||||||
|
f"Номер заявки: {service_request.id}\n"
|
||||||
|
f"Услуга: {service_request.service.name}\n"
|
||||||
|
f"Статус заявки: {'Подтверждена' if service_request.is_verified else 'Не подтверждена'}\n"
|
||||||
|
f"Дата создания: {service_request.created_at.strftime('%Y-%m-%d %H:%M:%S')}\n"
|
||||||
|
f"Спасибо, что выбрали наши услуги! Если у вас возникнут вопросы, вы всегда можете обратиться к нам."
|
||||||
|
)
|
||||||
|
self.bot.send_message(chat_id, confirmation_message)
|
||||||
|
|
||||||
|
# Вместо дополнительного POST-запроса — сообщаем о подтверждении через сообщение
|
||||||
|
self.bot.send_message(chat_id, "Ваш аккаунт успешно подтвержден на сервере! Продолжайте на сайте.")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.bot.send_message(chat_id, "Ошибка: Неверная заявка или токен. Пожалуйста, проверьте ссылку.")
|
self.bot.send_message(chat_id, "Ошибка: Неверная заявка или токен. Пожалуйста, проверьте ссылку.")
|
||||||
|
|
||||||
self.bot.send_message(chat_id, response_message)
|
|
||||||
else:
|
else:
|
||||||
response_message = "Ошибка: Некорректная команда. Пожалуйста, используйте ссылку, предоставленную на сайте для регистрации."
|
response_message = "Ошибка: Некорректная команда. Пожалуйста, используйте ссылку, предоставленную на сайте для регистрации."
|
||||||
self.bot.send_message(chat_id, response_message)
|
self.bot.send_message(chat_id, response_message)
|
||||||
|
|
||||||
def send_telegram_message(self, client_id, service_request_id, custom_message, order_id=None):
|
|
||||||
# Get the client and service request from the database
|
|
||||||
client = get_object_or_404(Client, pk=client_id)
|
|
||||||
service_request = get_object_or_404(ServiceRequest, pk=service_request_id)
|
|
||||||
chat_id = client.chat_id
|
|
||||||
|
|
||||||
# Build the message content
|
|
||||||
message = f"Здравствуйте, {client.first_name} {client.last_name}!\n"
|
|
||||||
message += custom_message
|
|
||||||
|
|
||||||
if order_id:
|
|
||||||
order = get_object_or_404(Order, pk=order_id)
|
|
||||||
message += f"\n\nДетали заказа:\nУслуга: {order.service.name}\nСтатус: {order.get_status_display()}\n"
|
|
||||||
|
|
||||||
# Add service request details
|
|
||||||
message += f"\nНомер заявки: {service_request.id}\nДата создания заявки: {service_request.created_at.strftime('%d-%m-%Y')}\n"
|
|
||||||
|
|
||||||
# Send the message using the bot
|
|
||||||
try:
|
|
||||||
self.bot.send_message(chat_id, message)
|
|
||||||
except Exception as e:
|
|
||||||
logging.error(f"Ошибка при отправке сообщения в Telegram: {e}")
|
|
||||||
|
|
||||||
# Example usage:
|
|
||||||
# bot = TelegramBot()
|
|
||||||
# bot.start_bot_polling()
|
|
||||||
# bot.send_telegram_message(client_id=1, service_request_id=1, custom_message="Ваши данные для входа на сайт.")
|
|
||||||
BIN
smartsoltech/media/static/img/customer/JD-26-512_SKOAvnB.jpg
Normal file
|
After Width: | Height: | Size: 15 KiB |
18
smartsoltech/static/assets/js/get-csrf-token.js
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
// Функция для получения CSRF токена из куков
|
||||||
|
function getCookie(name) {
|
||||||
|
let cookieValue = null;
|
||||||
|
if (document.cookie && document.cookie !== '') {
|
||||||
|
const cookies = document.cookie.split(';');
|
||||||
|
for (let i = 0; i < cookies.length; i++) {
|
||||||
|
const cookie = cookies[i].trim();
|
||||||
|
if (cookie.substring(0, name.length + 1) === (name + '=')) {
|
||||||
|
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cookieValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Инициализация переменной csrftoken, которая будет доступна глобально
|
||||||
|
const csrftoken = getCookie('csrftoken');
|
||||||
@@ -1,110 +1,49 @@
|
|||||||
document.addEventListener("DOMContentLoaded", function () {
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
// Работа с модальным окном заявки
|
||||||
var modalElement = document.getElementById('orderModal');
|
var modalElement = document.getElementById('orderModal');
|
||||||
if (modalElement) {
|
if (modalElement) {
|
||||||
var modal = new bootstrap.Modal(modalElement);
|
var modal = new bootstrap.Modal(modalElement);
|
||||||
|
|
||||||
// Инициализация модального окна
|
// Инициализация модального окна
|
||||||
modalElement.addEventListener('show.bs.modal', function (event) {
|
modalElement.addEventListener('show.bs.modal', function () {
|
||||||
console.log("Модальное окно открыто");
|
console.log("Модальное окно открыто");
|
||||||
});
|
});
|
||||||
|
|
||||||
modalElement.addEventListener('hide.bs.modal', function (event) {
|
modalElement.addEventListener('hide.bs.modal', function () {
|
||||||
console.log("Модальное окно закрыто");
|
console.log("Модальное окно закрыто");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
// Открытие модального окна для заявки на услугу
|
||||||
const generateQrButton = document.getElementById('generateQrButton');
|
const openModalBtn = document.getElementById('openModalBtn');
|
||||||
|
const serviceModal = document.getElementById('serviceModal');
|
||||||
|
|
||||||
if (generateQrButton) {
|
if (openModalBtn && serviceModal) {
|
||||||
generateQrButton.addEventListener('click', function () {
|
openModalBtn.addEventListener('click', function (event) {
|
||||||
const clientEmail = document.getElementById('clientEmail').value;
|
event.preventDefault();
|
||||||
const clientPhone = document.getElementById('clientPhone').value;
|
const serviceId = openModalBtn.getAttribute('data-service-id');
|
||||||
const clientName = document.getElementById('clientName').value;
|
console.log("Service ID при открытии модального окна:", serviceId);
|
||||||
const description = document.getElementById('description').value;
|
|
||||||
const serviceId = generateQrButton.getAttribute('data-service-id');
|
|
||||||
|
|
||||||
// Проверка заполненности полей
|
if (!serviceId) {
|
||||||
if (!clientEmail || !clientPhone || !clientName || !description || !serviceId) {
|
alert("Идентификатор услуги не найден. Обновите страницу и попробуйте снова.");
|
||||||
alert('Все поля должны быть заполнены.');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Получение CSRF токена из cookies
|
generateQrButton.dataset.serviceId = serviceId;
|
||||||
function getCookie(name) {
|
|
||||||
let cookieValue = null;
|
|
||||||
if (document.cookie && document.cookie !== '') {
|
|
||||||
const cookies = document.cookie.split(';');
|
|
||||||
for (let i = 0; i < cookies.length; i++) {
|
|
||||||
const cookie = cookies[i].trim();
|
|
||||||
if (cookie.substring(0, name.length + 1) === (name + '=')) {
|
|
||||||
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cookieValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const csrftoken = getCookie('csrftoken');
|
serviceModal.classList.add('show');
|
||||||
|
serviceModal.style.display = 'block';
|
||||||
// Отправка POST запроса на создание заявки
|
|
||||||
fetch('/service/create_request/', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'X-CSRFToken': csrftoken
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
client_email: clientEmail,
|
|
||||||
client_phone: clientPhone,
|
|
||||||
client_name: clientName,
|
|
||||||
service_id: serviceId,
|
|
||||||
description: description
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.then(response => {
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error('Ошибка при создании заявки');
|
|
||||||
}
|
|
||||||
return response.json();
|
|
||||||
})
|
|
||||||
.then(data => {
|
|
||||||
if (data.status === 'success') {
|
|
||||||
alert(data.message);
|
|
||||||
} else if (data.status === 'existing_request') {
|
|
||||||
alert(data.message);
|
|
||||||
} else {
|
|
||||||
alert('Неизвестная ошибка. Пожалуйста, попробуйте снова.');
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('Ошибка при создании заявки:', error);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
function checkVerificationStatus(serviceRequestId, interval) {
|
document.querySelectorAll('.close').forEach(closeBtn => {
|
||||||
fetch(`/service/request_status/${serviceRequestId}/`)
|
closeBtn.addEventListener('click', function () {
|
||||||
.then(response => {
|
if (serviceModal) {
|
||||||
if (!response.ok) {
|
serviceModal.classList.remove('show');
|
||||||
throw new Error('Ошибка при проверке статуса заявки');
|
setTimeout(() => {
|
||||||
|
serviceModal.style.display = 'none';
|
||||||
|
}, 500);
|
||||||
}
|
}
|
||||||
return response.json();
|
|
||||||
})
|
|
||||||
.then(data => {
|
|
||||||
if (data.is_verified) {
|
|
||||||
// Закрываем форму и показываем окно подтверждения
|
|
||||||
document.getElementById('serviceModal').style.display = 'none';
|
|
||||||
document.getElementById('confirmationModal').style.display = 'block';
|
|
||||||
|
|
||||||
// Останавливаем интервал проверки статуса
|
|
||||||
clearInterval(interval);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('Ошибка при проверке статуса заявки:', error);
|
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
|
});
|
||||||
|
|||||||
116
smartsoltech/static/assets/js/service_request.js
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
// service-request.js
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
// Открытие модального окна
|
||||||
|
const openModalBtn = document.getElementById('openModalBtn');
|
||||||
|
const serviceModal = document.getElementById('serviceModal');
|
||||||
|
const generateQrButton = document.getElementById('generateQrButton');
|
||||||
|
|
||||||
|
if (openModalBtn && serviceModal) {
|
||||||
|
openModalBtn.addEventListener('click', function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
// Логирование значения serviceId при открытии модального окна
|
||||||
|
const serviceId = openModalBtn.getAttribute('data-service-id');
|
||||||
|
console.log("Service ID при открытии модального окна:", serviceId);
|
||||||
|
|
||||||
|
// Проверяем, если serviceId отсутствует
|
||||||
|
if (!serviceId) {
|
||||||
|
alert("Идентификатор услуги не найден. Обновите страницу и попробуйте снова.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Сохраняем serviceId для дальнейшего использования
|
||||||
|
generateQrButton.dataset.serviceId = serviceId;
|
||||||
|
|
||||||
|
// Показываем модальное окно
|
||||||
|
serviceModal.classList.add('show');
|
||||||
|
serviceModal.style.display = 'block';
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.error('Не удалось найти элемент с id openModalBtn или serviceModal.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Закрытие модального окна
|
||||||
|
document.querySelectorAll('.close').forEach(closeBtn => {
|
||||||
|
closeBtn.addEventListener('click', function () {
|
||||||
|
if (serviceModal) {
|
||||||
|
serviceModal.classList.remove('show');
|
||||||
|
setTimeout(() => {
|
||||||
|
serviceModal.style.display = 'none';
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Обработчик кнопки "Создать заявку"
|
||||||
|
if (generateQrButton) {
|
||||||
|
generateQrButton.addEventListener('click', function () {
|
||||||
|
// Получение значений полей
|
||||||
|
const clientEmail = document.getElementById('clientEmail').value.trim();
|
||||||
|
const clientPhone = document.getElementById('clientPhone').value.trim();
|
||||||
|
const clientName = document.getElementById('clientName').value.trim();
|
||||||
|
const description = document.getElementById('description').value.trim();
|
||||||
|
|
||||||
|
// Получаем serviceId из кнопки открытия модального окна
|
||||||
|
const serviceId = generateQrButton.dataset.serviceId;
|
||||||
|
|
||||||
|
// Логируем для проверки значения serviceId перед отправкой
|
||||||
|
console.log("Service ID перед отправкой запроса:", serviceId);
|
||||||
|
|
||||||
|
// Проверка заполненности полей
|
||||||
|
if (!clientEmail || !clientPhone || !clientName || !description || !serviceId) {
|
||||||
|
let errorMessage = 'Пожалуйста, заполните все поля формы перед продолжением.\n';
|
||||||
|
if (!serviceId) {
|
||||||
|
errorMessage += 'Идентификатор услуги не найден. Обновите страницу и попробуйте снова.\n';
|
||||||
|
}
|
||||||
|
alert(errorMessage);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Отправка POST запроса на создание заявки
|
||||||
|
fetch(`/service/generate_qr_code/${serviceId}/`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-CSRFToken': csrftoken // Используем глобально инициализированный CSRF токен
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
client_email: clientEmail,
|
||||||
|
client_phone: clientPhone,
|
||||||
|
client_name: clientName,
|
||||||
|
description: description
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error('Ошибка при создании заявки');
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
if (data.qr_code_url) {
|
||||||
|
// Обновляем src изображения QR-кода и показываем его
|
||||||
|
const qrCodeImg = document.getElementById('qrCodeImg');
|
||||||
|
if (qrCodeImg) {
|
||||||
|
qrCodeImg.src = data.qr_code_url;
|
||||||
|
qrCodeImg.style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Начинаем проверку статуса заявки
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
checkVerificationStatus(data.service_request_id, interval);
|
||||||
|
}, 5000);
|
||||||
|
} else if (data.status === 'existing_request') {
|
||||||
|
alert(data.message);
|
||||||
|
} else {
|
||||||
|
alert('Неизвестная ошибка. Пожалуйста, попробуйте снова.');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Ошибка при создании заявки:', error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.error('Не удалось найти элемент с id generateQrButton.');
|
||||||
|
}
|
||||||
|
});
|
||||||
37
smartsoltech/static/assets/js/verification_status.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
// verification-status.js
|
||||||
|
|
||||||
|
function checkVerificationStatus(serviceRequestId, interval) {
|
||||||
|
console.log(`Проверка статуса для заявки с ID: ${serviceRequestId}`); // Лог для проверки
|
||||||
|
|
||||||
|
fetch(`/service/request_status/${serviceRequestId}/`)
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error('Ошибка при проверке статуса заявки');
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
if (data.is_verified) {
|
||||||
|
// Закрываем форму и показываем окно подтверждения
|
||||||
|
const serviceModal = document.getElementById('serviceModal');
|
||||||
|
const confirmationModal = document.getElementById('confirmationModal');
|
||||||
|
|
||||||
|
if (serviceModal) {
|
||||||
|
serviceModal.style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (confirmationModal) {
|
||||||
|
confirmationModal.style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Останавливаем интервал проверки статуса
|
||||||
|
clearInterval(interval);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Ошибка при проверке статуса заявки:', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Делаем функцию доступной глобально
|
||||||
|
window.checkVerificationStatus = checkVerificationStatus;
|
||||||
BIN
smartsoltech/static/qr_codes/request_347.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
smartsoltech/static/qr_codes/request_348.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_349.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_350.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_351.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_352.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_353.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_354.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_355.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_356.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_357.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_358.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
smartsoltech/static/qr_codes/request_359.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_360.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_361.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_362.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_363.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_364.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
smartsoltech/static/qr_codes/request_365.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_366.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_367.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_368.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_369.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_370.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_371.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_372.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_373.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_374.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_375.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_376.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_377.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_378.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_379.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_380.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_381.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_382.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_383.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
smartsoltech/static/qr_codes/request_384.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_385.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_386.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_387.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_388.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_389.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_390.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_391.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_392.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_393.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_394.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_395.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_396.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_397.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_398.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_399.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_400.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_401.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_402.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_403.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_404.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/static/qr_codes/request_405.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,22 @@
|
|||||||
|
# Generated by Django 5.1.1 on 2024-11-01 04:45
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('web', '0008_alter_servicerequest_client'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='servicerequest',
|
||||||
|
options={'ordering': ['-is_verified', '-created_at'], 'verbose_name': 'Заявка на услугу', 'verbose_name_plural': 'Заявки на услуги'},
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='servicerequest',
|
||||||
|
name='is_verified',
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -76,11 +76,12 @@ class ServiceRequest(models.Model):
|
|||||||
created_at = models.DateTimeField(auto_now_add=True)
|
created_at = models.DateTimeField(auto_now_add=True)
|
||||||
token = models.UUIDField(default=uuid.uuid4, unique=True) # Генерация уникального токена
|
token = models.UUIDField(default=uuid.uuid4, unique=True) # Генерация уникального токена
|
||||||
chat_id = models.CharField(max_length=100, blank=True, null=True) # Telegram chat ID
|
chat_id = models.CharField(max_length=100, blank=True, null=True) # Telegram chat ID
|
||||||
|
is_verified = models.BooleanField(default=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = 'Заявка на услугу'
|
verbose_name = 'Заявка на услугу'
|
||||||
verbose_name_plural = 'Заявки на услуги'
|
verbose_name_plural = 'Заявки на услуги'
|
||||||
ordering = ['-created_at']
|
ordering = ['-is_verified', '-created_at']
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"Request for {self.service.name} by {self.client.first_name}"
|
return f"Request for {self.service.name} by {self.client.first_name}"
|
||||||
@@ -150,5 +151,5 @@ class Review(models.Model):
|
|||||||
ordering = ['-review_date']
|
ordering = ['-review_date']
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"Review by {self.client.first_name} {self.client.last_name} for {self.service.name}"
|
return f"Отзыв от {self.client.first_name} {self.client.last_name} for {self.service.name}"
|
||||||
|
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
<!-- web/templates/web/modal_order_form.html -->
|
|
||||||
<div id="orderModal" class="modal fade" tabindex="-1">
|
|
||||||
<div class="modal-dialog">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title">Оформление заявки на услугу</h5>
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<form id="orderForm" method="post" action="{% url 'create_service_request' service_id=service.pk %}">
|
|
||||||
|
|
||||||
{% csrf_token %}
|
|
||||||
<div class="form-group mb-3">
|
|
||||||
<label class="form-label">Имя</label>
|
|
||||||
<input id="client_name" class="form-control" type="text" name="client_name" required minlength="2" maxlength="50" />
|
|
||||||
</div>
|
|
||||||
<div class="form-group mb-3">
|
|
||||||
<label class="form-label">Телефон</label>
|
|
||||||
<input id="client_phone" class="form-control" type="tel" name="client_phone" required pattern="^\+?[0-9\s\-]{7,15}$" />
|
|
||||||
</div>
|
|
||||||
<div class="form-group mb-3">
|
|
||||||
<label class="form-label">Адрес электронной почты</label>
|
|
||||||
<input id="client_email" class="form-control" type="email" name="client_email" required />
|
|
||||||
</div>
|
|
||||||
<div class="form-group mb-3 text-center">
|
|
||||||
<label class="form-label">Сканируйте QR код для регистрации в Telegram боте</label>
|
|
||||||
<div id="qrCodeContainer">
|
|
||||||
<img src="{{ qr_code }}" alt="QR код для Telegram бота" class="img-fluid" />
|
|
||||||
</div>
|
|
||||||
<div class="form-group mt-3">
|
|
||||||
<a href="{{ registration_link }}" target="_blank">Перейдите по этой ссылке для регистрации в Telegram боте</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
|
|
||||||
<button type="submit" class="btn btn-primary" id="submitButton" disabled>Отправить заявку</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
const checkVerificationStatus = () => {
|
|
||||||
fetch(`/service/request_status/{{ service_request_id }}/`)
|
|
||||||
.then(response => {
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error('Network response was not ok');
|
|
||||||
}
|
|
||||||
return response.json();
|
|
||||||
})
|
|
||||||
.then(data => {
|
|
||||||
if (data.is_verified) {
|
|
||||||
document.getElementById('submitButton').disabled = false;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => console.error('Ошибка при проверке статуса:', error));
|
|
||||||
};
|
|
||||||
|
|
||||||
setInterval(checkVerificationStatus, 5000);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@@ -1,214 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="ru">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
|
|
||||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
|
|
||||||
<title>Модальное окно для заявки на услугу</title>
|
|
||||||
<style>
|
|
||||||
/* Стили для модального окна */
|
|
||||||
.modal {
|
|
||||||
display: none;
|
|
||||||
position: fixed;
|
|
||||||
z-index: 1;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
overflow: auto;
|
|
||||||
background-color: rgba(0, 0, 0, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-content {
|
|
||||||
background-color: #fefefe;
|
|
||||||
margin: 15% auto;
|
|
||||||
padding: 20px;
|
|
||||||
border: 1px solid #888;
|
|
||||||
width: 80%;
|
|
||||||
max-width: 600px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.close {
|
|
||||||
color: #aaa;
|
|
||||||
float: right;
|
|
||||||
font-size: 28px;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.close:hover,
|
|
||||||
.close:focus {
|
|
||||||
color: #000;
|
|
||||||
text-decoration: none;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
#qrCodeImg {
|
|
||||||
display: block;
|
|
||||||
margin: 20px auto;
|
|
||||||
width: 200px;
|
|
||||||
height: 200px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<!-- Модальное окно -->
|
|
||||||
<div id="serviceModal" class="modal">
|
|
||||||
<div class="modal-content">
|
|
||||||
<span class="close">×</span>
|
|
||||||
<h4>Заполните заявку на услугу</h4>
|
|
||||||
<p>QR-код для завершения регистрации:</p>
|
|
||||||
<img id="qrCodeImg" src="" alt="QR Code">
|
|
||||||
<form id="serviceRequestForm">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="clientName">Ваше имя:</label>
|
|
||||||
<input type="text" class="form-control" id="clientName" name="client_name" placeholder="Введите ваше имя" required minlength="2" maxlength="50" readonly>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="clientChatId">Ваш chat ID:</label>
|
|
||||||
<input type="text" class="form-control" id="clientChatId" name="client_chat_id" placeholder="Ваш chat ID" readonly>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="clientEmail">Ваш email:</label>
|
|
||||||
<input type="email" class="form-control" id="clientEmail" name="client_email" placeholder="Введите ваш email" required>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="clientPhone">Ваш телефон:</label>
|
|
||||||
<input type="text" class="form-control" id="clientPhone" name="client_phone" placeholder="Введите ваш телефон" required pattern="^\+?[0-9\s\-]{7,15}$">
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="description">Описание заявки:</label>
|
|
||||||
<textarea class="form-control" id="description" name="description" placeholder="Опишите вашу заявку" required></textarea>
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="btn btn-success" id="submitButton" disabled>Отправить заявку</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// Обработчик открытия модального окна
|
|
||||||
document.getElementById('openModalBtn').addEventListener('click', function () {
|
|
||||||
const serviceId = this.getAttribute('data-service-id');
|
|
||||||
// Открываем модальное окно
|
|
||||||
document.getElementById('serviceModal').style.display = 'block';
|
|
||||||
|
|
||||||
// Выполняем запрос на генерацию QR-кода
|
|
||||||
fetch(`/service/generate_qr_code/${serviceId}/`)
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
// Обновляем src изображения QR-кода
|
|
||||||
document.getElementById('qrCodeImg').src = data.qr_code_url;
|
|
||||||
|
|
||||||
// Запуск проверки статуса каждые 5 секунд
|
|
||||||
const interval = setInterval(() => {
|
|
||||||
checkVerificationStatus(data.service_request_id, interval);
|
|
||||||
}, 5000);
|
|
||||||
})
|
|
||||||
.catch(error => console.error('Ошибка при генерации QR-кода:', error));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Обработчик закрытия модального окна
|
|
||||||
document.querySelector('.close').addEventListener('click', function () {
|
|
||||||
document.getElementById('serviceModal').style.display = 'none';
|
|
||||||
});
|
|
||||||
|
|
||||||
// Обработчик отправки формы
|
|
||||||
document.getElementById('serviceRequestForm').addEventListener('submit', function (event) {
|
|
||||||
event.preventDefault();
|
|
||||||
const formData = new FormData(this);
|
|
||||||
const serviceId = document.getElementById('openModalBtn').getAttribute('data-service-id');
|
|
||||||
// Отправка данных формы на сервер
|
|
||||||
fetch('/service/request/' + serviceId + '/', {
|
|
||||||
method: 'POST',
|
|
||||||
body: formData
|
|
||||||
}).then(response => {
|
|
||||||
if (response.ok) {
|
|
||||||
alert('Заявка успешно отправлена!');
|
|
||||||
document.getElementById('serviceModal').style.display = 'none';
|
|
||||||
// Отправка сообщения в Telegram
|
|
||||||
sendTelegramNotification(formData);
|
|
||||||
} else {
|
|
||||||
alert('Ошибка при отправке заявки. Пожалуйста, попробуйте снова.');
|
|
||||||
}
|
|
||||||
}).catch(error => console.error('Ошибка при отправке данных формы:', error));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Проверка статуса заявки на наличие подтверждения Telegram
|
|
||||||
const checkVerificationStatus = (serviceRequestId, interval) => {
|
|
||||||
fetch(`/service/request_status/${serviceRequestId}/`)
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
if (data.is_verified) {
|
|
||||||
// Заполнение полей формы данными пользователя
|
|
||||||
document.getElementById('clientName').value = data.client_name;
|
|
||||||
document.getElementById('clientChatId').value = data.client_chat_id;
|
|
||||||
|
|
||||||
// Активируем кнопку отправки, если все поля заполнены
|
|
||||||
updateButtonState();
|
|
||||||
|
|
||||||
// Останавливаем интервал проверки статуса
|
|
||||||
clearInterval(interval);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => console.error('Ошибка при проверке статуса заявки:', error));
|
|
||||||
};
|
|
||||||
|
|
||||||
// Код для активации кнопки "Отправить" при заполнении всех полей
|
|
||||||
const clientEmail = document.getElementById('clientEmail');
|
|
||||||
const clientPhone = document.getElementById('clientPhone');
|
|
||||||
const clientName = document.getElementById('clientName');
|
|
||||||
const description = document.getElementById('description');
|
|
||||||
const clientChatId = document.getElementById('clientChatId');
|
|
||||||
const submitButton = document.getElementById('submitButton');
|
|
||||||
|
|
||||||
const updateButtonState = () => {
|
|
||||||
if (clientEmail.value && clientPhone.value && clientName.value && description.value && clientChatId.value) {
|
|
||||||
submitButton.disabled = false;
|
|
||||||
} else {
|
|
||||||
submitButton.disabled = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Привязка событий к полям для обновления состояния кнопки отправки
|
|
||||||
clientEmail.addEventListener('input', updateButtonState);
|
|
||||||
clientPhone.addEventListener('input', updateButtonState);
|
|
||||||
description.addEventListener('input', updateButtonState);
|
|
||||||
|
|
||||||
// Удаление placeholder при установке фокуса на поле
|
|
||||||
document.querySelectorAll('input, textarea').forEach(field => {
|
|
||||||
field.addEventListener('focus', function () {
|
|
||||||
this.dataset.placeholder = this.placeholder;
|
|
||||||
this.placeholder = '';
|
|
||||||
});
|
|
||||||
field.addEventListener('blur', function () {
|
|
||||||
this.placeholder = this.dataset.placeholder;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Функция для отправки уведомления в Telegram
|
|
||||||
const sendTelegramNotification = (formData) => {
|
|
||||||
const clientName = formData.get('client_name');
|
|
||||||
const serviceDescription = formData.get('description');
|
|
||||||
const chatId = formData.get('client_chat_id');
|
|
||||||
const message = `Здравствуйте, ${clientName}! Ваша заявка успешно зарегистрирована. Детали: ${serviceDescription}`;
|
|
||||||
|
|
||||||
fetch('/service/send_telegram_notification/', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
},
|
|
||||||
body: JSON.stringify({ chat_id: chatId, message: message })
|
|
||||||
}).then(response => {
|
|
||||||
if (response.ok) {
|
|
||||||
console.log('Уведомление успешно отправлено в Telegram');
|
|
||||||
} else {
|
|
||||||
console.error('Ошибка при отправке уведомления в Telegram');
|
|
||||||
}
|
|
||||||
}).catch(error => console.error('Ошибка при отправке уведомления в Telegram:', error));
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
|
||||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Модальное окно для создания заявки на услугу -->
|
||||||
{% include "web/modal_order_form.html" %}
|
{% include "web/modal_order_form.html" %}
|
||||||
|
|
||||||
<div class="container py-4">
|
<div class="container py-4">
|
||||||
@@ -78,174 +79,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<!-- Подключение JavaScript файлов, вынесенных в директорию static/assets/js -->
|
||||||
/* Добавляем стили для анимации появления модального окна */
|
<script src="{% static 'assets/js/get-csrf-token.js' %}"></script>
|
||||||
#serviceModal {
|
<script src="{% static 'assets/js/modal-init.js' %}"></script>
|
||||||
display: none;
|
<script src="{% static 'assets/js/service_request.js' %}"></script>
|
||||||
position: fixed;
|
<script src="{% static 'assets/js/verification_status.js' %}"></script>
|
||||||
z-index: 1;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background-color: rgba(0, 0, 0, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-content {
|
|
||||||
position: relative;
|
|
||||||
background-color: #fefefe;
|
|
||||||
margin: auto;
|
|
||||||
padding: 20px;
|
|
||||||
border: 1px solid #888;
|
|
||||||
width: 80%;
|
|
||||||
max-width: 600px;
|
|
||||||
transform: scale(0);
|
|
||||||
transition: transform 0.5s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal.show .modal-content {
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<script <script src="{% static 'assets/js/modal-init.js' %}"> </script>
|
|
||||||
<script>
|
|
||||||
function checkVerificationStatus(serviceRequestId, interval) {
|
|
||||||
fetch(`/service/request_status/${serviceRequestId}/`)
|
|
||||||
.then(response => {
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error('Ошибка при проверке статуса заявки');
|
|
||||||
}
|
|
||||||
return response.json();
|
|
||||||
})
|
|
||||||
.then(data => {
|
|
||||||
if (data.is_verified) {
|
|
||||||
// Закрываем форму и показываем окно подтверждения
|
|
||||||
document.getElementById('serviceModal').style.display = 'none';
|
|
||||||
document.getElementById('confirmationModal').style.display = 'block';
|
|
||||||
|
|
||||||
// Останавливаем интервал проверки статуса
|
|
||||||
clearInterval(interval);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('Ошибка при проверке статуса заявки:', error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
|
||||||
// Получение CSRF токена
|
|
||||||
function getCookie(name) {
|
|
||||||
let cookieValue = null;
|
|
||||||
if (document.cookie && document.cookie !== '') {
|
|
||||||
const cookies = document.cookie.split(';');
|
|
||||||
for (let i = 0; i < cookies.length; i++) {
|
|
||||||
const cookie = cookies[i].trim();
|
|
||||||
if (cookie.substring(0, name.length + 1) === (name + '=')) {
|
|
||||||
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cookieValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const csrftoken = getCookie('csrftoken');
|
|
||||||
|
|
||||||
// Открытие модального окна
|
|
||||||
const openModalBtn = document.getElementById('openModalBtn');
|
|
||||||
const serviceModal = document.getElementById('serviceModal');
|
|
||||||
if (openModalBtn) {
|
|
||||||
openModalBtn.addEventListener('click', function (event) {
|
|
||||||
event.preventDefault(); // Предотвращаем отправку формы при нажатии на кнопку
|
|
||||||
serviceModal.classList.add('show');
|
|
||||||
serviceModal.style.display = 'block';
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.error('Не удалось найти элемент с id openModalBtn.');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Закрытие модальных окон
|
|
||||||
document.querySelectorAll('.close').forEach(closeBtn => {
|
|
||||||
closeBtn.addEventListener('click', function () {
|
|
||||||
serviceModal.classList.remove('show');
|
|
||||||
setTimeout(() => {
|
|
||||||
serviceModal.style.display = 'none';
|
|
||||||
}, 500); // Ждем, пока завершится анимация закрытия
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Обработчик кнопки "Продолжить" для генерации QR-кода
|
|
||||||
const generateQrButton = document.getElementById('generateQrButton');
|
|
||||||
if (generateQrButton) {
|
|
||||||
generateQrButton.addEventListener('click', function () {
|
|
||||||
const clientEmail = document.getElementById('clientEmail').value;
|
|
||||||
const clientPhone = document.getElementById('clientPhone').value;
|
|
||||||
const clientName = document.getElementById('clientName').value;
|
|
||||||
const description = document.getElementById('description').value;
|
|
||||||
|
|
||||||
// Проверяем, чтобы все поля были заполнены
|
|
||||||
if (!clientEmail || !clientPhone || !clientName || !description) {
|
|
||||||
alert('Все поля должны быть заполнены.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Выполняем валидацию телефона перед продолжением
|
|
||||||
let phonePattern = /^\+?[0-9\s\-]{7,15}$/;
|
|
||||||
if (!phonePattern.test(clientPhone)) {
|
|
||||||
alert('Введите правильный номер телефона.');
|
|
||||||
return; // Останавливаем выполнение, если телефон не валиден
|
|
||||||
}
|
|
||||||
|
|
||||||
// Получаем serviceId из кнопки открытия модального окна
|
|
||||||
const serviceId = openModalBtn.getAttribute('data-service-id');
|
|
||||||
if (!serviceId) {
|
|
||||||
console.error('Не удалось найти идентификатор услуги');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Запрос на генерацию QR-кода с использованием метода POST
|
|
||||||
fetch(`/service/generate_qr_code/${serviceId}/`, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'X-CSRFToken': csrftoken // Добавляем CSRF токен в заголовок
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
client_email: clientEmail,
|
|
||||||
client_phone: clientPhone,
|
|
||||||
client_name: clientName,
|
|
||||||
description: description
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.then(response => {
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error('Ошибка при генерации QR-кода');
|
|
||||||
}
|
|
||||||
return response.json();
|
|
||||||
})
|
|
||||||
.then(data => {
|
|
||||||
if (!data.qr_code_url) {
|
|
||||||
throw new Error('Ответ не содержит URL QR-кода');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Обновляем src изображения QR-кода и показываем его
|
|
||||||
const qrCodeImg = document.getElementById('qrCodeImg');
|
|
||||||
qrCodeImg.src = data.qr_code_url;
|
|
||||||
qrCodeImg.style.display = 'block';
|
|
||||||
|
|
||||||
// Запуск проверки статуса каждые 5 секунд
|
|
||||||
const interval = setInterval(() => {
|
|
||||||
checkVerificationStatus(data.service_request_id, interval, clientEmail, clientPhone, description);
|
|
||||||
}, 5000);
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('Ошибка при генерации QR-кода:', error);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -17,12 +17,12 @@ urlpatterns = [
|
|||||||
path('service/request_status/<int:service_id>/', views.request_status, name='request_status'),
|
path('service/request_status/<int:service_id>/', views.request_status, name='request_status'),
|
||||||
path('service/request/<int:service_id>/', views.create_service_request, name='create_service_request'),
|
path('service/request/<int:service_id>/', views.create_service_request, name='create_service_request'),
|
||||||
path('complete_registration/<int:request_id>/', views.complete_registration, name='complete_registration'),
|
path('complete_registration/<int:request_id>/', views.complete_registration, name='complete_registration'),
|
||||||
path('complete_registration/', views.complete_registration_basic, name='complete_registration_basic'),
|
# path('complete_registration/', views.complete_registration_basic, name='complete_registration_basic'),
|
||||||
path('service/check_service_request_data/', views.check_service_request_data, name='check_service_request_data'),
|
# path('service/check_service_request_data/', views.check_service_request_data, name='check_service_request_data'),
|
||||||
path('client/orders/', views.client_orders, name='client_orders'),
|
# path('client/orders/', views.client_orders, name='client_orders'),
|
||||||
path('order/<int:pk>/', views.order_detail, name='order_detail'),
|
# path('order/<int:pk>/', views.order_detail, name='order_detail'),
|
||||||
path('service/send_telegram_notification/', views.send_telegram_notification, name='send_telegram_notification'),
|
path('service/send_telegram_notification/', views.send_telegram_notification, name='send_telegram_notification'),
|
||||||
path('service/create_request/', views.create_service_request_basic, name='create_service_request_basic'),
|
# path('service/create_request/', views.create_service_request_basic, name='create_service_request_basic'),
|
||||||
]
|
]
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||||
@@ -9,7 +9,7 @@ import uuid
|
|||||||
from django.utils.http import urlsafe_base64_encode
|
from django.utils.http import urlsafe_base64_encode
|
||||||
from django.utils.encoding import force_bytes
|
from django.utils.encoding import force_bytes
|
||||||
from django.http import JsonResponse
|
from django.http import JsonResponse
|
||||||
from django.utils.crypto import get_random_string # Импорт get_random_string
|
from django.utils.crypto import get_random_string
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from decouple import config
|
from decouple import config
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
@@ -21,13 +21,16 @@ import hashlib
|
|||||||
import json
|
import json
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
import logging
|
import logging
|
||||||
|
from django.db import transaction, IntegrityError
|
||||||
|
from django.db.models import Q
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
# sens
|
|
||||||
|
# Initialize Telegram Bot
|
||||||
try:
|
try:
|
||||||
bot = TelegramBot()
|
bot = TelegramBot()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print (e)
|
logger.error(f"Failed to initialize Telegram bot: {str(e)}")
|
||||||
|
|
||||||
def home(request):
|
def home(request):
|
||||||
services = Service.objects.all()
|
services = Service.objects.all()
|
||||||
@@ -69,21 +72,18 @@ def about_view(request):
|
|||||||
def create_service_request(request, service_id):
|
def create_service_request(request, service_id):
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
try:
|
try:
|
||||||
# Извлечение данных из запроса
|
|
||||||
data = json.loads(request.body)
|
data = json.loads(request.body)
|
||||||
client_email = data.get('client_email')
|
client_email = data.get('client_email')
|
||||||
client_phone = data.get('client_phone')
|
client_phone = data.get('client_phone')
|
||||||
client_name = data.get('client_name')
|
client_name = data.get('client_name')
|
||||||
|
|
||||||
# Проверка на наличие всех необходимых данных
|
|
||||||
if not all([client_email, client_phone, client_name]):
|
if not all([client_email, client_phone, client_name]):
|
||||||
return JsonResponse({'status': 'error', 'message': 'Все поля должны быть заполнены'}, status=400)
|
return JsonResponse({'status': 'error', 'message': 'Все поля должны быть заполнены'}, status=400)
|
||||||
|
|
||||||
# Получение услуги
|
|
||||||
service = get_object_or_404(Service, pk=service_id)
|
service = get_object_or_404(Service, pk=service_id)
|
||||||
|
|
||||||
# Создаем или получаем клиента
|
# Проверяем наличие клиента по email (так как email должен быть уникальным)
|
||||||
client, created = Client.objects.get_or_create(
|
client, client_created = Client.objects.get_or_create(
|
||||||
email=client_email,
|
email=client_email,
|
||||||
defaults={
|
defaults={
|
||||||
'first_name': client_name.split()[0] if client_name else "",
|
'first_name': client_name.split()[0] if client_name else "",
|
||||||
@@ -92,27 +92,28 @@ def create_service_request(request, service_id):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
# Обновляем данные клиента, если он уже существовал
|
# Обновляем данные клиента, если он уже существовал (например, телефон или имя изменились)
|
||||||
if not created:
|
if not client_created:
|
||||||
client.first_name = client_name.split()[0]
|
client.first_name = client_name.split()[0]
|
||||||
client.last_name = client_name.split()[-1] if len(client_name.split()) > 1 else ""
|
client.last_name = client_name.split()[-1] if len(client_name.split()) > 1 else ""
|
||||||
client.phone_number = client_phone
|
client.phone_number = client_phone
|
||||||
client.save()
|
client.save()
|
||||||
|
|
||||||
# Проверяем, есть ли у клиента уже активная заявка
|
# Проверяем наличие заявки на эту же услугу, не завершенной и не подтвержденной
|
||||||
existing_requests = ServiceRequest.objects.filter(client=client, service=service, chat_id__isnull=True)
|
existing_requests = ServiceRequest.objects.filter(client=client, service=service, is_verified=False)
|
||||||
if existing_requests.exists():
|
if existing_requests.exists():
|
||||||
return JsonResponse({
|
return JsonResponse({
|
||||||
'status': 'existing_request',
|
'status': 'existing_request',
|
||||||
'message': 'У вас уже есть активная заявка на данную услугу. Пожалуйста, проверьте ваш Telegram для завершения процесса.'
|
'message': 'У вас уже есть активная заявка на данную услугу. Пожалуйста, проверьте ваш Telegram для завершения процесса.'
|
||||||
})
|
})
|
||||||
|
|
||||||
# Создание новой заявки на услугу
|
# Создаем новую заявку для клиента
|
||||||
token = uuid.uuid4().hex
|
token = uuid.uuid4().hex
|
||||||
service_request = ServiceRequest.objects.create(
|
service_request = ServiceRequest.objects.create(
|
||||||
service=service,
|
service=service,
|
||||||
client=client,
|
client=client,
|
||||||
token=token
|
token=token,
|
||||||
|
is_verified=False
|
||||||
)
|
)
|
||||||
|
|
||||||
return JsonResponse({
|
return JsonResponse({
|
||||||
@@ -122,94 +123,8 @@ def create_service_request(request, service_id):
|
|||||||
})
|
})
|
||||||
|
|
||||||
except json.JSONDecodeError:
|
except json.JSONDecodeError:
|
||||||
|
logger.error("Invalid JSON format")
|
||||||
return JsonResponse({'status': 'error', 'message': 'Неверный формат данных'}, status=400)
|
return JsonResponse({'status': 'error', 'message': 'Неверный формат данных'}, status=400)
|
||||||
|
|
||||||
return JsonResponse({'status': 'error', 'message': 'Метод запроса должен быть POST'}, status=405)
|
|
||||||
|
|
||||||
def create_service_request_basic(request):
|
|
||||||
if request.method == 'POST':
|
|
||||||
try:
|
|
||||||
# Извлечение данных из тела запроса
|
|
||||||
data = json.loads(request.body)
|
|
||||||
client_email = data.get('client_email')
|
|
||||||
client_phone = data.get('client_phone')
|
|
||||||
client_name = data.get('client_name')
|
|
||||||
service_id = data.get('service_id')
|
|
||||||
description = data.get('description')
|
|
||||||
|
|
||||||
# Проверка на наличие всех необходимых данных
|
|
||||||
if not all([client_email, client_phone, client_name, service_id, description]):
|
|
||||||
return JsonResponse({'status': 'error', 'message': 'Все поля должны быть заполнены'}, status=400)
|
|
||||||
|
|
||||||
# Получаем услугу по ID
|
|
||||||
service = get_object_or_404(Service, pk=service_id)
|
|
||||||
|
|
||||||
# Проверка на существование активной заявки для клиента на данную услугу
|
|
||||||
existing_requests = ServiceRequest.objects.filter(client__email=client_email, service=service, chat_id__isnull=True)
|
|
||||||
if existing_requests.exists():
|
|
||||||
return JsonResponse({
|
|
||||||
'status': 'existing_request',
|
|
||||||
'message': 'У вас уже есть активная заявка на данную услугу. Пожалуйста, проверьте ваш Telegram для завершения процесса.'
|
|
||||||
})
|
|
||||||
|
|
||||||
# Создаем или получаем клиента
|
|
||||||
user, created = User.objects.get_or_create(
|
|
||||||
username=f"{client_email.split('@')[0]}_{get_random_string(5)}",
|
|
||||||
defaults={"email": client_email}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Обновляем данные пользователя, если он уже существовал
|
|
||||||
user.first_name = client_name.split()[0] if client_name else ""
|
|
||||||
user.last_name = client_name.split()[-1] if len(client_name.split()) > 1 else ""
|
|
||||||
user.save()
|
|
||||||
|
|
||||||
# Создаем или получаем объект клиента
|
|
||||||
client, _ = Client.objects.get_or_create(
|
|
||||||
email=client_email,
|
|
||||||
defaults={
|
|
||||||
'user': user,
|
|
||||||
'first_name': user.first_name,
|
|
||||||
'last_name': user.last_name,
|
|
||||||
'phone_number': client_phone,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Создаем заявку на услугу
|
|
||||||
token = uuid.uuid4().hex
|
|
||||||
service_request = ServiceRequest.objects.create(
|
|
||||||
service=service,
|
|
||||||
client=client,
|
|
||||||
token=token
|
|
||||||
)
|
|
||||||
|
|
||||||
# Создаем заказ на основе заявки
|
|
||||||
order = Order.objects.create(
|
|
||||||
service_request=service_request,
|
|
||||||
client=client,
|
|
||||||
service=service,
|
|
||||||
message=description,
|
|
||||||
status="pending"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Отправляем уведомление в Telegram, если chat_id у клиента заполнен
|
|
||||||
if client.chat_id:
|
|
||||||
# Предполагается, что bot.send_telegram_message() уже настроен
|
|
||||||
bot.send_telegram_message(
|
|
||||||
client.chat_id,
|
|
||||||
f"Ваш заказ на услугу '{service.name}' был успешно создан. Пожалуйста, завершите процесс регистрации в Telegram."
|
|
||||||
)
|
|
||||||
|
|
||||||
return JsonResponse({
|
|
||||||
'status': 'success',
|
|
||||||
'message': 'Заявка успешно создана. Пожалуйста, проверьте ваш Telegram для подтверждения.',
|
|
||||||
'service_request_id': service_request.id,
|
|
||||||
})
|
|
||||||
|
|
||||||
except json.JSONDecodeError:
|
|
||||||
return JsonResponse({'status': 'error', 'message': 'Неверный формат данных'}, status=400)
|
|
||||||
except Exception as e:
|
|
||||||
return JsonResponse({'status': 'error', 'message': str(e)}, status=500)
|
|
||||||
|
|
||||||
return JsonResponse({'status': 'error', 'message': 'Метод запроса должен быть POST'}, status=405)
|
return JsonResponse({'status': 'error', 'message': 'Метод запроса должен быть POST'}, status=405)
|
||||||
|
|
||||||
def generate_qr_code(request, service_id):
|
def generate_qr_code(request, service_id):
|
||||||
@@ -220,62 +135,66 @@ def generate_qr_code(request, service_id):
|
|||||||
client_phone = data.get('client_phone')
|
client_phone = data.get('client_phone')
|
||||||
client_name = data.get('client_name')
|
client_name = data.get('client_name')
|
||||||
|
|
||||||
# Проверка на наличие всех необходимых данных
|
|
||||||
if not all([client_email, client_phone, client_name]):
|
if not all([client_email, client_phone, client_name]):
|
||||||
logger.error("Не все поля заполнены.")
|
logger.error("Все поля должны быть заполнены")
|
||||||
return JsonResponse({'error': 'Все поля должны быть заполнены'}, status=400)
|
return JsonResponse({'error': 'Все поля должны быть заполнены'}, status=400)
|
||||||
|
|
||||||
except json.JSONDecodeError as e:
|
# Используем транзакцию для предотвращения конкурентного создания дубликатов
|
||||||
logger.error(f"Ошибка JSONDecodeError: {str(e)}")
|
with transaction.atomic():
|
||||||
return JsonResponse({'error': 'Неверный формат данных'}, status=400)
|
user, user_created = User.objects.select_for_update().get_or_create(
|
||||||
|
email=client_email,
|
||||||
|
defaults={
|
||||||
|
"username": f"{client_email.split('@')[0]}_{get_random_string(5)}",
|
||||||
|
"first_name": client_name.split()[0] if client_name else "",
|
||||||
|
"last_name": client_name.split()[-1] if len(client_name.split()) > 1 else ""
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if not user_created:
|
||||||
|
# Обновляем информацию о пользователе, если он уже существует
|
||||||
|
user.first_name = client_name.split()[0] if client_name else ""
|
||||||
|
user.last_name = client_name.split()[-1] if len(client_name.split()) > 1 else ""
|
||||||
|
user.save()
|
||||||
|
|
||||||
# Создание или получение клиента
|
client, client_created = Client.objects.select_for_update().get_or_create(
|
||||||
try:
|
email=client_email,
|
||||||
user, created = User.objects.get_or_create(
|
defaults={
|
||||||
username=f"{client_email.split('@')[0]}_{get_random_string(5)}",
|
'user': user,
|
||||||
defaults={"email": client_email}
|
'first_name': user.first_name,
|
||||||
)
|
'last_name': user.last_name,
|
||||||
user.first_name = client_name.split()[0] if client_name else ""
|
'phone_number': client_phone
|
||||||
user.last_name = client_name.split()[-1] if len(client_name.split()) > 1 else ""
|
}
|
||||||
user.save()
|
)
|
||||||
|
|
||||||
client, _ = Client.objects.get_or_create(
|
if not client_created:
|
||||||
email=client_email,
|
# Обновляем информацию о клиенте, если он уже существует
|
||||||
defaults={
|
client.first_name = user.first_name
|
||||||
'user': user,
|
client.last_name = user.last_name
|
||||||
'first_name': user.first_name,
|
client.phone_number = client_phone
|
||||||
'last_name': user.last_name,
|
client.save()
|
||||||
'phone_number': client_phone
|
|
||||||
}
|
|
||||||
)
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Ошибка при создании или получении клиента: {str(e)}")
|
|
||||||
return JsonResponse({'error': f'Ошибка при создании клиента: {str(e)}'}, status=500)
|
|
||||||
|
|
||||||
# Создание новой заявки на услугу
|
# Проверка на существование активной заявки
|
||||||
try:
|
|
||||||
service = get_object_or_404(Service, pk=service_id)
|
service = get_object_or_404(Service, pk=service_id)
|
||||||
token = uuid.uuid4().hex
|
existing_requests = ServiceRequest.objects.filter(client=client, service=service, is_verified=False)
|
||||||
|
if existing_requests.exists():
|
||||||
|
return JsonResponse({
|
||||||
|
'status': 'existing_request',
|
||||||
|
'message': 'У вас уже есть активная заявка на данную услугу. Пожалуйста, проверьте ваш Telegram для завершения процесса.'
|
||||||
|
})
|
||||||
|
|
||||||
|
# Создаем новую заявку на услугу
|
||||||
|
token = uuid.uuid4().hex
|
||||||
service_request = ServiceRequest.objects.create(
|
service_request = ServiceRequest.objects.create(
|
||||||
service=service,
|
service=service,
|
||||||
client=client,
|
client=client,
|
||||||
token=token
|
token=token,
|
||||||
|
is_verified=False
|
||||||
)
|
)
|
||||||
except Exception as e:
|
logger.info(f"Создана новая заявка: {service_request.id} для клиента: {client.email}")
|
||||||
logger.error(f"Ошибка при создании заявки: {str(e)}")
|
|
||||||
return JsonResponse({'error': f'Ошибка при создании заявки: {str(e)}'}, status=500)
|
|
||||||
|
|
||||||
# Генерация ссылки для регистрации в Telegram
|
# Генерация ссылки и QR-кода для Telegram
|
||||||
try:
|
|
||||||
telegram_settings = get_object_or_404(TelegramSettings, pk=1)
|
telegram_settings = get_object_or_404(TelegramSettings, pk=1)
|
||||||
registration_link = f'https://t.me/{telegram_settings.bot_name}?start=request_{service_request.id}_token_{urlsafe_base64_encode(force_bytes(token))}'
|
registration_link = f'https://t.me/{telegram_settings.bot_name}?start=request_{service_request.id}_token_{urlsafe_base64_encode(force_bytes(token))}'
|
||||||
except TelegramSettings.DoesNotExist:
|
|
||||||
logger.error("Не удалось получить настройки Telegram.")
|
|
||||||
return JsonResponse({'error': 'Не удалось получить настройки Telegram'}, status=500)
|
|
||||||
|
|
||||||
# Генерация QR-кода
|
|
||||||
try:
|
|
||||||
qr = qrcode.make(registration_link)
|
qr = qrcode.make(registration_link)
|
||||||
qr_code_dir = os.path.join(settings.STATICFILES_DIRS[0], 'qr_codes')
|
qr_code_dir = os.path.join(settings.STATICFILES_DIRS[0], 'qr_codes')
|
||||||
qr_code_path = os.path.join(qr_code_dir, f"request_{service_request.id}.png")
|
qr_code_path = os.path.join(qr_code_dir, f"request_{service_request.id}.png")
|
||||||
@@ -285,11 +204,14 @@ def generate_qr_code(request, service_id):
|
|||||||
os.makedirs(qr_code_dir)
|
os.makedirs(qr_code_dir)
|
||||||
|
|
||||||
qr.save(qr_code_path)
|
qr.save(qr_code_path)
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Ошибка при генерации QR-кода: {str(e)}")
|
|
||||||
return JsonResponse({'error': f'Ошибка при генерации QR-кода: {str(e)}'}, status=500)
|
|
||||||
|
|
||||||
# Возвращаем ответ, включающий все необходимые данные
|
except IntegrityError as e:
|
||||||
|
logger.error(f"Ошибка целостности данных при создании пользователя или клиента: {str(e)}")
|
||||||
|
return JsonResponse({'error': 'Ошибка при обработке данных. Пожалуйста, попробуйте позже.'}, status=500)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Ошибка при обработке запроса: {str(e)}")
|
||||||
|
return JsonResponse({'error': f'Ошибка: {str(e)}'}, status=500)
|
||||||
|
|
||||||
return JsonResponse({
|
return JsonResponse({
|
||||||
'registration_link': registration_link,
|
'registration_link': registration_link,
|
||||||
'qr_code_url': f"/{external_qr_link}",
|
'qr_code_url': f"/{external_qr_link}",
|
||||||
@@ -298,104 +220,57 @@ def generate_qr_code(request, service_id):
|
|||||||
'client_phone': client_phone,
|
'client_phone': client_phone,
|
||||||
'client_name': client_name
|
'client_name': client_name
|
||||||
})
|
})
|
||||||
else:
|
return JsonResponse({'error': 'Метод запроса должен быть POST'}, status=405)
|
||||||
logger.error("Неправильный метод запроса")
|
|
||||||
return JsonResponse({'error': 'Метод запроса должен быть POST'}, status=405)
|
|
||||||
|
|
||||||
|
|
||||||
def complete_registration(request, request_id):
|
|
||||||
# Завершение регистрации по идентификатору заявки
|
|
||||||
service_request = get_object_or_404(ServiceRequest, pk=request_id)
|
|
||||||
if request.method == 'POST':
|
|
||||||
client_email = request.POST.get('client_email', service_request.client.email)
|
|
||||||
client_phone = request.POST.get('client_phone', service_request.client.phone_number)
|
|
||||||
chat_id = request.POST.get('chat_id', service_request.chat_id)
|
|
||||||
|
|
||||||
# Проверка корректности данных
|
|
||||||
if not all([client_email, client_phone, chat_id]):
|
|
||||||
return JsonResponse({'status': 'error', 'message': 'Все поля должны быть заполнены.'}, status=400)
|
|
||||||
|
|
||||||
# Обновляем данные клиента
|
|
||||||
client = service_request.client
|
|
||||||
client.email = client_email
|
|
||||||
client.phone_number = client_phone
|
|
||||||
client.save()
|
|
||||||
|
|
||||||
# Обновляем заявку
|
|
||||||
service_request.chat_id = chat_id
|
|
||||||
service_request.save()
|
|
||||||
|
|
||||||
return JsonResponse({'status': 'success', 'message': 'Регистрация успешно завершена.'})
|
|
||||||
|
|
||||||
return render(request, 'web/complete_registration.html', {'service_request': service_request})
|
|
||||||
|
|
||||||
|
|
||||||
return render(request, 'web/complete_registration.html', {'service_request': service_request})
|
|
||||||
def request_status(request, service_id):
|
def request_status(request, service_id):
|
||||||
try:
|
try:
|
||||||
# Получаем заявку на услугу по ID
|
|
||||||
service_request = get_object_or_404(ServiceRequest, pk=service_id)
|
service_request = get_object_or_404(ServiceRequest, pk=service_id)
|
||||||
|
|
||||||
# Получаем объект клиента через связанное поле client
|
|
||||||
client = service_request.client
|
client = service_request.client
|
||||||
|
is_verified = service_request.is_verified
|
||||||
|
|
||||||
# Проверка, что клиент существует и его Telegram chat_id заполнен
|
|
||||||
is_verified = bool(client and client.chat_id)
|
|
||||||
|
|
||||||
# Возвращаем данные клиента и статус верификации
|
|
||||||
return JsonResponse({
|
return JsonResponse({
|
||||||
'is_verified': is_verified,
|
'is_verified': is_verified,
|
||||||
'client_name': client.first_name if client else "Неизвестно",
|
'client_name': client.first_name if client else "Неизвестно",
|
||||||
'client_chat_id': client.chat_id if client else None,
|
'client_chat_id': client.chat_id if client else None,
|
||||||
})
|
})
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
logger.error(f"Ошибка при получении статуса заявки: {str(e)}")
|
||||||
return JsonResponse({'error': str(e)}, status=500)
|
return JsonResponse({'error': str(e)}, status=500)
|
||||||
|
|
||||||
def complete_registration_basic(request):
|
@csrf_exempt
|
||||||
# Базовая регистрация без идентификатора заявки
|
def send_telegram_notification(request):
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
client_name = request.POST.get('client_name')
|
|
||||||
client_email = request.POST.get('client_email')
|
|
||||||
client_phone = request.POST.get('client_phone')
|
|
||||||
|
|
||||||
return redirect('home')
|
|
||||||
|
|
||||||
return render(request, 'web/complete_registration_basic.html')
|
|
||||||
|
|
||||||
def check_service_request_data(request, token=None, request_id=None):
|
|
||||||
# Проверка наличия данных в таблице ServiceRequest по токену или номеру заявки
|
|
||||||
service_request = None
|
|
||||||
if token:
|
|
||||||
try:
|
try:
|
||||||
service_request = ServiceRequest.objects.get(token=token)
|
data = json.loads(request.body)
|
||||||
except ServiceRequest.DoesNotExist:
|
|
||||||
service_request = None
|
|
||||||
elif request_id:
|
|
||||||
try:
|
|
||||||
service_request = ServiceRequest.objects.get(id=request_id)
|
|
||||||
except ServiceRequest.DoesNotExist:
|
|
||||||
service_request = None
|
|
||||||
|
|
||||||
if service_request:
|
# Логируем полученные данные для отладки
|
||||||
return JsonResponse({
|
logging.info(f"Полученные данные для подтверждения заявки: {data}")
|
||||||
'exists': True,
|
|
||||||
'client_name': service_request.client_name,
|
|
||||||
'client_email': service_request.client_email,
|
|
||||||
'client_phone': service_request.client_phone,
|
|
||||||
'chat_id': service_request.chat_id
|
|
||||||
})
|
|
||||||
else:
|
|
||||||
return JsonResponse({'exists': False})
|
|
||||||
|
|
||||||
def order_detail(request, pk):
|
service_request_id = data.get('service_request_id')
|
||||||
order = get_object_or_404(Order, pk=pk)
|
client_chat_id = data.get('client_chat_id')
|
||||||
return render(request, 'web/order_detail.html', {'order': order})
|
client_name = data.get('client_name')
|
||||||
|
|
||||||
@login_required
|
if not service_request_id or not client_chat_id:
|
||||||
def client_orders(request):
|
return JsonResponse({'error': 'Недостаточно данных для подтверждения'}, status=400)
|
||||||
client = request.user.client_profile
|
|
||||||
orders = client.related_orders.all()
|
# Проверяем существование заявки
|
||||||
return render(request, 'web/client_orders.html', {'orders': orders})
|
service_request = ServiceRequest.objects.filter(id=service_request_id).first()
|
||||||
|
if not service_request:
|
||||||
|
return JsonResponse({'error': 'Заявка не найдена'}, status=404)
|
||||||
|
|
||||||
|
# Обновляем заявку с chat_id, если все верно
|
||||||
|
service_request.chat_id = client_chat_id
|
||||||
|
service_request.is_verified = True
|
||||||
|
service_request.save()
|
||||||
|
|
||||||
|
return JsonResponse({'status': 'Уведомление успешно отправлено в Telegram'})
|
||||||
|
|
||||||
|
except json.JSONDecodeError as e:
|
||||||
|
logging.error(f"Ошибка при декодировании JSON: {e}")
|
||||||
|
return JsonResponse({'error': 'Неверный формат данных'}, status=400)
|
||||||
|
|
||||||
|
logging.error(f"Неподдерживаемый метод запроса: {request.method}")
|
||||||
|
return JsonResponse({'error': 'Метод запроса должен быть POST'}, status=405)
|
||||||
|
|
||||||
|
|
||||||
def generate_secure_token(service_request_id, secret_key):
|
def generate_secure_token(service_request_id, secret_key):
|
||||||
@@ -403,48 +278,24 @@ def generate_secure_token(service_request_id, secret_key):
|
|||||||
data = f'{service_request_id}:{secret_key}'
|
data = f'{service_request_id}:{secret_key}'
|
||||||
return hmac.new(secret_key.encode(), data.encode(), hashlib.sha256).hexdigest()
|
return hmac.new(secret_key.encode(), data.encode(), hashlib.sha256).hexdigest()
|
||||||
|
|
||||||
@csrf_exempt
|
def complete_registration(request, request_id):
|
||||||
def send_telegram_notification(request):
|
service_request = get_object_or_404(ServiceRequest, pk=request_id)
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
try:
|
client_email = request.POST.get('client_email', service_request.client.email)
|
||||||
data = json.loads(request.body)
|
client_phone = request.POST.get('client_phone', service_request.client.phone_number)
|
||||||
service_request_id = data.get('service_request_id')
|
chat_id = request.POST.get('chat_id', service_request.chat_id)
|
||||||
provided_token = data.get('token')
|
|
||||||
|
|
||||||
# Проверка корректности переданных данных
|
if not all([client_email, client_phone, chat_id]):
|
||||||
if not service_request_id or not provided_token:
|
return JsonResponse({'status': 'error', 'message': 'Все поля должны быть заполнены.'}, status=400)
|
||||||
return JsonResponse({'error': 'Недостаточно данных для подтверждения'}, status=400)
|
|
||||||
|
|
||||||
# Получение заявки
|
client = service_request.client
|
||||||
service_request = ServiceRequest.objects.filter(id=service_request_id).first()
|
client.email = client_email
|
||||||
if not service_request:
|
client.phone_number = client_phone
|
||||||
return JsonResponse({'error': 'Заявка не найдена'}, status=404)
|
client.save()
|
||||||
|
|
||||||
# Генерация токена и сравнение
|
service_request.chat_id = chat_id
|
||||||
secret_key = settings.SECRET_KEY # Используем секретный ключ из настроек
|
service_request.save()
|
||||||
expected_token = generate_secure_token(service_request_id, secret_key)
|
|
||||||
|
|
||||||
if not hmac.compare_digest(provided_token, expected_token):
|
return JsonResponse({'status': 'success', 'message': 'Регистрация успешно завершена.'})
|
||||||
return JsonResponse({'error': 'Неверный токен. Доступ запрещен.'}, status=403)
|
|
||||||
|
|
||||||
# Отправка сообщения в Telegram
|
return render(request, 'web/complete_registration.html', {'service_request': service_request})
|
||||||
chat_id = service_request.chat_id
|
|
||||||
if not chat_id:
|
|
||||||
return JsonResponse({'error': 'Нет chat_id для отправки сообщения'}, status=400)
|
|
||||||
|
|
||||||
# Составление и отправка сообщения
|
|
||||||
message = (
|
|
||||||
f"Здравствуйте, {service_request.client.first_name}!\n"
|
|
||||||
f"Ваша заявка на услугу '{service_request.service.name}' успешно зарегистрирована."
|
|
||||||
)
|
|
||||||
|
|
||||||
bot.send_telegram_message(chat_id=chat_id, message=message)
|
|
||||||
|
|
||||||
return JsonResponse({'status': 'Уведомление успешно отправлено в Telegram'})
|
|
||||||
|
|
||||||
except json.JSONDecodeError:
|
|
||||||
return JsonResponse({'error': 'Неверный формат данных'}, status=400)
|
|
||||||
except Exception as e:
|
|
||||||
return JsonResponse({'error': str(e)}, status=500)
|
|
||||||
|
|
||||||
return JsonResponse({'error': 'Метод запроса должен быть POST'}, status=405)
|
|
||||||
|
|||||||