Files
smartsoltech_site/smartsoltech/web/models.py

344 lines
17 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from django.db import models
from django.contrib.auth.models import AbstractUser, User
import uuid
from django.urls import reverse
class Category(models.Model):
name = models.CharField(max_length=100)
description = models.TextField(default='Описание категории')
class Meta:
verbose_name = 'Категория'
verbose_name_plural = 'Категории'
ordering = ['name']
def __str__(self):
return self.name
class Service(models.Model):
name = models.CharField(max_length=200)
description = models.TextField(default='Описание услуги')
price = models.DecimalField(max_digits=10, decimal_places=2)
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, related_name='services')
image = models.ImageField(upload_to='static/img/services/', blank=True, null=True)
class Meta:
verbose_name = 'Услуга'
verbose_name_plural = 'Услуги'
ordering = ['name']
def __str__(self):
return self.name
def average_rating(self):
reviews = self.reviews.all()
if reviews:
return sum(review.rating for review in reviews) / reviews.count()
return 0
def review_count(self):
return self.reviews.count()
class Client(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='client_profile', null=True, blank=True)
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
email = models.EmailField(unique=True)
phone_number = models.CharField(max_length=15, unique=True)
image = models.ImageField(upload_to='static/img/customer/', blank=True, null=True)
chat_id = models.CharField(max_length=100, blank=True, null=True) # Telegram chat ID
class Meta:
verbose_name = 'Клиент'
verbose_name_plural = 'Клиенты'
ordering = ['last_name', 'first_name']
def __str__(self):
return f"{self.first_name} {self.last_name} {self.chat_id}"
class BlogPost(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
published_date = models.DateTimeField(auto_now_add=True)
image = models.ImageField(upload_to='static/img/blog/', blank=True, null=True)
class Meta:
verbose_name = 'Блог'
verbose_name_plural = 'Блоги'
ordering = ['-published_date']
def __str__(self):
return self.title
class ServiceRequest(models.Model):
service = models.ForeignKey(Service, on_delete=models.CASCADE)
client = models.ForeignKey(Client, on_delete=models.CASCADE, related_name='related_service_requests', null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
token = models.UUIDField(default=uuid.uuid4, unique=True) # Генерация уникального токена
chat_id = models.CharField(max_length=100, blank=True, null=True) # Telegram chat ID
is_verified = models.BooleanField(default=False)
class Meta:
verbose_name = 'Заявка на услугу'
verbose_name_plural = 'Заявки на услуги'
ordering = ['-is_verified', '-created_at']
def __str__(self):
return f"Request for {self.service.name} by {self.client.first_name}"
class Order(models.Model):
service_request = models.OneToOneField(ServiceRequest, on_delete=models.CASCADE, related_name='related_order')
client = models.ForeignKey(Client, on_delete=models.CASCADE, related_name='related_orders')
service = models.ForeignKey(Service, on_delete=models.CASCADE, related_name='related_orders')
message = models.TextField(blank=True, null=True)
order_date = models.DateTimeField(auto_now_add=True)
status = models.CharField(
max_length=50,
choices=[
('pending', 'Ожидание'),
('in_progress', 'В процессе'),
('completed', 'Завершен'),
('cancelled', 'Отменён')
],
default='pending'
)
class Meta:
ordering = ['-order_date']
verbose_name = 'Заказ'
verbose_name_plural = 'Заказы'
def __str__(self):
return f"Order #{self.id} by {self.client.first_name}"
def is_completed(self):
return self.status == 'completed'
def get_absolute_url(self):
return reverse('order_detail', kwargs={'pk': self.pk})
class Project(models.Model):
name = models.CharField(max_length=200)
description = models.TextField(default='Описание проекта')
completion_date = models.DateField(blank=True, null=True)
client = models.ForeignKey(Client, on_delete=models.CASCADE, related_name='projects')
service = models.ForeignKey(Service, on_delete=models.CASCADE, related_name='projects')
order = models.OneToOneField(Order, on_delete=models.CASCADE, related_name='project', null=True, blank=True)
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, blank=True)
image = models.ImageField(upload_to='static/img/project/', blank=True, null=True)
status = models.CharField(max_length=50, choices=[('in_progress', 'В процессе'), ('completed', 'Завершен')], default='in_progress')
class Meta:
verbose_name = 'Проект'
verbose_name_plural = 'Проекты'
ordering = ['-completion_date']
def __str__(self):
return self.name
class Review(models.Model):
client = models.ForeignKey(Client, on_delete=models.CASCADE, related_name='reviews')
service = models.ForeignKey(Service, on_delete=models.CASCADE, related_name='reviews')
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='reviews', blank=True, null=True)
rating = models.IntegerField()
comment = models.TextField()
review_date = models.DateTimeField(auto_now_add=True)
image = models.ImageField(upload_to='static/img/review/', blank=True, null=True)
class Meta:
verbose_name = 'Отзыв'
verbose_name_plural = 'Отзывы'
ordering = ['-review_date']
def __str__(self):
return f"Отзыв от {self.client.first_name} {self.client.last_name} for {self.service.name}"
class AboutPage(models.Model):
"""Модель для страницы 'О нас' - все данные управляются из админки"""
# Hero Section
hero_badge = models.CharField(max_length=100, default='🚀 О нас', verbose_name='Hero Badge')
hero_title = models.CharField(max_length=200, default='Мы создаем цифровое будущее', verbose_name='Заголовок Hero')
hero_description = models.TextField(default='SmartSolTech - это команда профессионалов...', verbose_name='Описание Hero')
# Statistics
stat_projects = models.IntegerField(default=50, verbose_name='Количество проектов')
stat_clients = models.IntegerField(default=30, verbose_name='Количество клиентов')
stat_years = models.IntegerField(default=3, verbose_name='Лет опыта')
stat_support = models.CharField(max_length=50, default='24/7', verbose_name='Поддержка')
# Mission Section
mission_badge = models.CharField(max_length=100, default='🎯 Наша миссия', verbose_name='Mission Badge')
mission_title = models.CharField(max_length=200, default='Делаем технологии доступными', verbose_name='Заголовок миссии')
mission_description = models.TextField(verbose_name='Описание миссии')
mission_point_1_title = models.CharField(max_length=200, default='Инновационные решения', verbose_name='Пункт миссии 1')
mission_point_1_text = models.TextField(default='Используем передовые технологии...', verbose_name='Текст пункта 1')
mission_point_2_title = models.CharField(max_length=200, default='Клиентоориентированность', verbose_name='Пункт миссии 2')
mission_point_2_text = models.TextField(default='Фокусируемся на потребностях...', verbose_name='Текст пункта 2')
mission_point_3_title = models.CharField(max_length=200, default='Непрерывное развитие', verbose_name='Пункт миссии 3')
mission_point_3_text = models.TextField(default='Постоянно совершенствуем...', verbose_name='Текст пункта 3')
# Vision Section
vision_badge = models.CharField(max_length=100, default='🔮 Наше видение', verbose_name='Vision Badge')
vision_title = models.CharField(max_length=200, default='Будущее начинается сегодня', verbose_name='Заголовок видения')
vision_description = models.TextField(verbose_name='Описание видения')
# Skills
skill_1_name = models.CharField(max_length=100, default='Веб-разработка', verbose_name='Навык 1')
skill_1_percent = models.IntegerField(default=95, verbose_name='Процент навыка 1')
skill_2_name = models.CharField(max_length=100, default='Мобильная разработка', verbose_name='Навык 2')
skill_2_percent = models.IntegerField(default=90, verbose_name='Процент навыка 2')
skill_3_name = models.CharField(max_length=100, default='UI/UX Дизайн', verbose_name='Навык 3')
skill_3_percent = models.IntegerField(default=85, verbose_name='Процент навыка 3')
skill_4_name = models.CharField(max_length=100, default='DevOps', verbose_name='Навык 4')
skill_4_percent = models.IntegerField(default=80, verbose_name='Процент навыка 4')
# Team Section
team_badge = models.CharField(max_length=100, default='👥 Команда', verbose_name='Team Badge')
team_title = models.CharField(max_length=200, default='Познакомьтесь с нашей командой', verbose_name='Заголовок команды')
team_description = models.TextField(default='Талантливые профессионалы...', verbose_name='Описание команды')
# Values Section
values_badge = models.CharField(max_length=100, default='💎 Наши ценности', verbose_name='Values Badge')
values_title = models.CharField(max_length=200, default='Что нами движет', verbose_name='Заголовок ценностей')
value_1_icon = models.CharField(max_length=50, default='fa-lightbulb', verbose_name='Иконка ценности 1')
value_1_title = models.CharField(max_length=100, default='Инновации', verbose_name='Ценность 1')
value_1_text = models.TextField(default='Мы постоянно ищем новые решения...', verbose_name='Текст ценности 1')
value_2_icon = models.CharField(max_length=50, default='fa-handshake', verbose_name='Иконка ценности 2')
value_2_title = models.CharField(max_length=100, default='Партнерство', verbose_name='Ценность 2')
value_2_text = models.TextField(default='Строим долгосрочные отношения...', verbose_name='Текст ценности 2')
value_3_icon = models.CharField(max_length=50, default='fa-chart-line', verbose_name='Иконка ценности 3')
value_3_title = models.CharField(max_length=100, default='Результат', verbose_name='Ценность 3')
value_3_text = models.TextField(default='Фокусируемся на достижении целей...', verbose_name='Текст ценности 3')
value_4_icon = models.CharField(max_length=50, default='fa-shield-alt', verbose_name='Иконка ценности 4')
value_4_title = models.CharField(max_length=100, default='Надежность', verbose_name='Ценность 4')
value_4_text = models.TextField(default='Гарантируем качество и безопасность...', verbose_name='Текст ценности 4')
# Contact Section
contact_title = models.CharField(max_length=200, default='Готовы начать проект?', verbose_name='Заголовок контактов')
contact_description = models.TextField(default='Свяжитесь с нами сегодня...', verbose_name='Описание контактов')
# Meta
is_active = models.BooleanField(default=True, verbose_name='Активна')
updated_at = models.DateTimeField(auto_now=True, verbose_name='Обновлено')
class Meta:
verbose_name = 'Страница О нас'
verbose_name_plural = 'Страницы О нас'
def __str__(self):
return f"О нас (обновлено: {self.updated_at.strftime('%d.%m.%Y')})"
def save(self, *args, **kwargs):
# Оставляем только одну активную запись
if self.is_active:
AboutPage.objects.exclude(pk=self.pk).update(is_active=False)
super().save(*args, **kwargs)
class FooterSettings(models.Model):
"""Настройки футера - все данные управляются из админки"""
# Company Info
company_name = models.CharField(max_length=100, default='SmartSolTech', verbose_name='Название компании')
company_description = models.TextField(
default='Мы создаем инновационные IT-решения, которые помогают бизнесу расти...',
verbose_name='Описание компании'
)
company_logo_icon = models.CharField(max_length=50, default='fa-code', verbose_name='Иконка компании')
# Social Links
telegram_url = models.URLField(blank=True, verbose_name='Telegram URL')
instagram_url = models.URLField(blank=True, verbose_name='Instagram URL')
linkedin_url = models.URLField(blank=True, verbose_name='LinkedIn URL')
github_url = models.URLField(blank=True, verbose_name='GitHub URL')
facebook_url = models.URLField(blank=True, verbose_name='Facebook URL')
twitter_url = models.URLField(blank=True, verbose_name='Twitter URL')
# Contact Info
email = models.EmailField(default='info@smartsoltech.kr', verbose_name='Email')
phone = models.CharField(max_length=50, default='+82-10-XXXX-XXXX', verbose_name='Телефон')
address = models.TextField(default='Seoul, South Korea', verbose_name='Адрес')
# Services Links (for footer menu)
show_services_menu = models.BooleanField(default=True, verbose_name='Показывать меню услуг')
services_title = models.CharField(max_length=100, default='Услуги', verbose_name='Заголовок меню услуг')
# Company Links (for footer menu)
show_company_menu = models.BooleanField(default=True, verbose_name='Показывать меню компании')
company_menu_title = models.CharField(max_length=100, default='Компания', verbose_name='Заголовок меню компании')
# Copyright
copyright_text = models.CharField(
max_length=200,
default='© 2025 SmartSolTech. Все права защищены.',
verbose_name='Текст Copyright'
)
# Integration Scripts
google_analytics = models.TextField(
blank=True,
verbose_name='Google Analytics',
help_text='Вставьте код Google Analytics (без тегов <script>)'
)
google_adsense = models.TextField(
blank=True,
verbose_name='Google AdSense',
help_text='Вставьте код Google AdSense (без тегов <script>)'
)
yandex_metrika = models.TextField(
blank=True,
verbose_name='Яндекс Метрика',
help_text='Вставьте код Яндекс Метрики (без тегов <script>)'
)
facebook_pixel = models.TextField(
blank=True,
verbose_name='Facebook Pixel',
help_text='Вставьте код Facebook Pixel (без тегов <script>)'
)
custom_head_scripts = models.TextField(
blank=True,
verbose_name='Скрипты в <head>',
help_text='Дополнительные скрипты для вставки в <head> (с тегами <script>)'
)
custom_body_scripts = models.TextField(
blank=True,
verbose_name='Скрипты перед </body>',
help_text='Дополнительные скрипты для вставки перед закрывающим </body> (с тегами <script>)'
)
# Meta
is_active = models.BooleanField(default=True, verbose_name='Активно')
updated_at = models.DateTimeField(auto_now=True, verbose_name='Обновлено')
class Meta:
verbose_name = 'Настройки футера'
verbose_name_plural = 'Настройки футера'
def __str__(self):
return f"Футер (обновлено: {self.updated_at.strftime('%d.%m.%Y')})"
def save(self, *args, **kwargs):
# Оставляем только одну активную запись
if self.is_active:
FooterSettings.objects.exclude(pk=self.pk).update(is_active=False)
super().save(*args, **kwargs)