commit 09e4edee6bd7185d795a7825c239068b82f86fec Author: Андрей Цой Date: Fri Dec 6 09:27:06 2024 +0900 init commit diff --git a/bot/__init__.py b/bot/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/bot/__pycache__/__init__.cpython-311.pyc b/bot/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 00000000..5080794f Binary files /dev/null and b/bot/__pycache__/__init__.cpython-311.pyc differ diff --git a/bot/__pycache__/admin.cpython-311.pyc b/bot/__pycache__/admin.cpython-311.pyc new file mode 100644 index 00000000..ef863636 Binary files /dev/null and b/bot/__pycache__/admin.cpython-311.pyc differ diff --git a/bot/__pycache__/apps.cpython-311.pyc b/bot/__pycache__/apps.cpython-311.pyc new file mode 100644 index 00000000..4d2f554a Binary files /dev/null and b/bot/__pycache__/apps.cpython-311.pyc differ diff --git a/bot/__pycache__/models.cpython-311.pyc b/bot/__pycache__/models.cpython-311.pyc new file mode 100644 index 00000000..d4871555 Binary files /dev/null and b/bot/__pycache__/models.cpython-311.pyc differ diff --git a/bot/admin.py b/bot/admin.py new file mode 100644 index 00000000..8c38f3f3 --- /dev/null +++ b/bot/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/bot/apps.py b/bot/apps.py new file mode 100644 index 00000000..1cd7ff2e --- /dev/null +++ b/bot/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class BotConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'bot' diff --git a/bot/bot.py b/bot/bot.py new file mode 100644 index 00000000..e50bfaf1 --- /dev/null +++ b/bot/bot.py @@ -0,0 +1,39 @@ +from telegram import Update +from telegram.ext import Updater, CommandHandler, CallbackContext +from users.models import User, UserConfirmation +import uuid + +def start(update: Update, context: CallbackContext): + user_id = update.message.from_user.id + chat_id = update.message.chat_id + + user, created = User.objects.get_or_create(telegram_id=user_id, defaults={'chat_id': chat_id}) + if not user.confirmed: + confirmation_code = str(uuid.uuid4()) + UserConfirmation.objects.create(user=user, confirmation_code=confirmation_code) + update.message.reply_text(f"Ваш код подтверждения: {confirmation_code}") + else: + update.message.reply_text("Вы уже зарегистрированы!") + +def confirm(update: Update, context: CallbackContext): + user_id = update.message.from_user.id + code = ' '.join(context.args) + + try: + confirmation = UserConfirmation.objects.get(user__telegram_id=user_id, confirmation_code=code) + confirmation.user.confirmed = True + confirmation.user.save() + confirmation.delete() + update.message.reply_text("Регистрация подтверждена!") + except UserConfirmation.DoesNotExist: + update.message.reply_text("Неверный код подтверждения!") + +def main(): + updater = Updater("YOUR_TELEGRAM_BOT_TOKEN") + dispatcher = updater.dispatcher + + dispatcher.add_handler(CommandHandler("start", start)) + dispatcher.add_handler(CommandHandler("confirm", confirm)) + + updater.start_polling() + updater.idle() diff --git a/bot/migrations/__init__.py b/bot/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/bot/migrations/__pycache__/__init__.cpython-311.pyc b/bot/migrations/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 00000000..9dee3209 Binary files /dev/null and b/bot/migrations/__pycache__/__init__.cpython-311.pyc differ diff --git a/bot/models.py b/bot/models.py new file mode 100644 index 00000000..71a83623 --- /dev/null +++ b/bot/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/bot/tests.py b/bot/tests.py new file mode 100644 index 00000000..7ce503c2 --- /dev/null +++ b/bot/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/bot/urls.py b/bot/urls.py new file mode 100644 index 00000000..e69de29b diff --git a/bot/views.py b/bot/views.py new file mode 100644 index 00000000..91ea44a2 --- /dev/null +++ b/bot/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/hotels/__init__.py b/hotels/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hotels/__pycache__/__init__.cpython-311.pyc b/hotels/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 00000000..ffc96a93 Binary files /dev/null and b/hotels/__pycache__/__init__.cpython-311.pyc differ diff --git a/hotels/__pycache__/admin.cpython-311.pyc b/hotels/__pycache__/admin.cpython-311.pyc new file mode 100644 index 00000000..a1eea691 Binary files /dev/null and b/hotels/__pycache__/admin.cpython-311.pyc differ diff --git a/hotels/__pycache__/apps.cpython-311.pyc b/hotels/__pycache__/apps.cpython-311.pyc new file mode 100644 index 00000000..95bfd2aa Binary files /dev/null and b/hotels/__pycache__/apps.cpython-311.pyc differ diff --git a/hotels/__pycache__/models.cpython-311.pyc b/hotels/__pycache__/models.cpython-311.pyc new file mode 100644 index 00000000..83c2ccaa Binary files /dev/null and b/hotels/__pycache__/models.cpython-311.pyc differ diff --git a/hotels/__pycache__/urls.cpython-311.pyc b/hotels/__pycache__/urls.cpython-311.pyc new file mode 100644 index 00000000..8c482786 Binary files /dev/null and b/hotels/__pycache__/urls.cpython-311.pyc differ diff --git a/hotels/admin.py b/hotels/admin.py new file mode 100644 index 00000000..09fe2327 --- /dev/null +++ b/hotels/admin.py @@ -0,0 +1,17 @@ +from django.contrib import admin +from .models import Hotel, UserHotel + +@admin.register(Hotel) +class HotelAdmin(admin.ModelAdmin): + list_display = ('name', 'pms_type', 'created_at') + search_fields = ('name',) + list_filter = ('pms_type',) + ordering = ('-created_at',) + +@admin.register(UserHotel) +class UserHotelAdmin(admin.ModelAdmin): + list_display = ('user', 'hotel') + search_fields = ('user', 'hotel') + list_filter = ('hotel',) + ordering = ('-hotel',) + \ No newline at end of file diff --git a/hotels/apps.py b/hotels/apps.py new file mode 100644 index 00000000..d8bd62fa --- /dev/null +++ b/hotels/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class HotelsConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'hotels' diff --git a/hotels/migrations/0001_initial.py b/hotels/migrations/0001_initial.py new file mode 100644 index 00000000..3df5b4c0 --- /dev/null +++ b/hotels/migrations/0001_initial.py @@ -0,0 +1,33 @@ +# Generated by Django 5.1.4 on 2024-12-05 23:39 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Hotel', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255, verbose_name='Hotel Name')), + ('pms_type', models.CharField(choices=[('bnovo', 'Bnovo'), ('travelline', 'Travel Line')], max_length=50, verbose_name='PMS Type')), + ('api_key', models.CharField(blank=True, max_length=255, null=True, verbose_name='API Key')), + ('public_key', models.CharField(blank=True, max_length=255, null=True, verbose_name='Public Key')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), + ], + ), + migrations.CreateModel( + name='UserHotel', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('hotel', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='hotels.hotel', verbose_name='Hotel')), + ], + ), + ] diff --git a/hotels/migrations/0002_initial.py b/hotels/migrations/0002_initial.py new file mode 100644 index 00000000..bd71123e --- /dev/null +++ b/hotels/migrations/0002_initial.py @@ -0,0 +1,22 @@ +# Generated by Django 5.1.4 on 2024-12-05 23:39 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('hotels', '0001_initial'), + ('users', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='userhotel', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.user', verbose_name='User'), + ), + ] diff --git a/hotels/migrations/__init__.py b/hotels/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hotels/migrations/__pycache__/0001_initial.cpython-311.pyc b/hotels/migrations/__pycache__/0001_initial.cpython-311.pyc new file mode 100644 index 00000000..d4dde08a Binary files /dev/null and b/hotels/migrations/__pycache__/0001_initial.cpython-311.pyc differ diff --git a/hotels/migrations/__pycache__/0002_initial.cpython-311.pyc b/hotels/migrations/__pycache__/0002_initial.cpython-311.pyc new file mode 100644 index 00000000..67bac23f Binary files /dev/null and b/hotels/migrations/__pycache__/0002_initial.cpython-311.pyc differ diff --git a/hotels/migrations/__pycache__/__init__.cpython-311.pyc b/hotels/migrations/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 00000000..b2513105 Binary files /dev/null and b/hotels/migrations/__pycache__/__init__.cpython-311.pyc differ diff --git a/hotels/models.py b/hotels/models.py new file mode 100644 index 00000000..ac8453df --- /dev/null +++ b/hotels/models.py @@ -0,0 +1,23 @@ +from django.db import models +from users.models import User + +class Hotel(models.Model): + name = models.CharField(max_length=255, verbose_name="Hotel Name") + pms_type = models.CharField( + max_length=50, + choices=[('bnovo', 'Bnovo'), ('travelline', 'Travel Line')], + verbose_name="PMS Type" + ) + api_key = models.CharField(max_length=255, blank=True, null=True, verbose_name="API Key") + public_key = models.CharField(max_length=255, blank=True, null=True, verbose_name="Public Key") + created_at = models.DateTimeField(auto_now_add=True, verbose_name="Created At") + + def __str__(self): + return self.name + +class UserHotel(models.Model): + user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="User") + hotel = models.ForeignKey(Hotel, on_delete=models.CASCADE, verbose_name="Hotel") + + def __str__(self): + return f"{self.user.username} - {self.hotel.name}" \ No newline at end of file diff --git a/hotels/tests.py b/hotels/tests.py new file mode 100644 index 00000000..7ce503c2 --- /dev/null +++ b/hotels/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/hotels/urls.py b/hotels/urls.py new file mode 100644 index 00000000..e69de29b diff --git a/hotels/views.py b/hotels/views.py new file mode 100644 index 00000000..91ea44a2 --- /dev/null +++ b/hotels/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/manage.py b/manage.py new file mode 100755 index 00000000..850eae6b --- /dev/null +++ b/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'touchh.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/req.txt b/req.txt new file mode 100644 index 00000000..89b7714f --- /dev/null +++ b/req.txt @@ -0,0 +1,25 @@ +anyio==4.6.2.post1 +asgiref==3.8.1 +certifi==2024.8.30 +Django==5.1.4 +django-filter==24.3 +django-jazzmin==3.0.1 +django-jet==1.0.8 +et_xmlfile==2.0.0 +h11==0.14.0 +httpcore==1.0.7 +httpx==0.28.0 +idna==3.10 +numpy==2.1.3 +openpyxl==3.1.5 +pandas==2.2.3 +pillow==11.0.0 +python-dateutil==2.9.0.post0 +python-dotenv==1.0.1 +python-telegram-bot==21.8 +pytz==2024.2 +PyYAML==6.0.2 +six==1.17.0 +sniffio==1.3.1 +sqlparse==0.5.2 +tzdata==2024.2 diff --git a/touchh/__init__.py b/touchh/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/touchh/__pycache__/__init__.cpython-311.pyc b/touchh/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 00000000..59b5ca49 Binary files /dev/null and b/touchh/__pycache__/__init__.cpython-311.pyc differ diff --git a/touchh/__pycache__/settings.cpython-311.pyc b/touchh/__pycache__/settings.cpython-311.pyc new file mode 100644 index 00000000..e0bf537f Binary files /dev/null and b/touchh/__pycache__/settings.cpython-311.pyc differ diff --git a/touchh/__pycache__/urls.cpython-311.pyc b/touchh/__pycache__/urls.cpython-311.pyc new file mode 100644 index 00000000..7db3fc6c Binary files /dev/null and b/touchh/__pycache__/urls.cpython-311.pyc differ diff --git a/touchh/__pycache__/wsgi.cpython-311.pyc b/touchh/__pycache__/wsgi.cpython-311.pyc new file mode 100644 index 00000000..34ce4bee Binary files /dev/null and b/touchh/__pycache__/wsgi.cpython-311.pyc differ diff --git a/touchh/asgi.py b/touchh/asgi.py new file mode 100644 index 00000000..f8d90caa --- /dev/null +++ b/touchh/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for touchh project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.1/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'touchh.settings') + +application = get_asgi_application() diff --git a/touchh/settings.py b/touchh/settings.py new file mode 100644 index 00000000..0f8991a4 --- /dev/null +++ b/touchh/settings.py @@ -0,0 +1,151 @@ +""" +Django settings for touchh project. + +Generated by 'django-admin startproject' using Django 5.1.4. + +For more information on this file, see +https://docs.djangoproject.com/en/5.1/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/5.1/ref/settings/ +""" + +from pathlib import Path + +import os + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'django-insecure-l_8uu8#p*^zf)9zry80)6u+!+2g1a4tg!wx7@^!uw(+^axyh&h' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = ['0.0.0.0', '192.168.219.140', '127.0.0.1'] + + +# Application definition + +INSTALLED_APPS = [ + 'jazzmin', + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'bot', + 'hotels', + 'users', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'touchh.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'touchh.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/5.1/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'db.sqlite3', + } +} + + +# Password validation +# https://docs.djangoproject.com/en/5.1/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/5.1/topics/i18n/ + +LANGUAGE_CODE = 'ru-RU' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/5.1/howto/static-files/ +STATIC_ROOT = BASE_DIR / 'staticfiles' + +STATIC_URL = '/static/' +STATICFILES_DIRS = [BASE_DIR / 'static'] + + +# Default primary key field type +# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + + +JAZZMIN_SETTINGS = { + "site_title": "TOUCHH admin", + "site_header": "My Administration", + "site_brand": "Touchh", + "welcome_sign": "Welcome to system adminitration center", + "show_sidebar": True, + "navigation_expanded": True, + "icons": { + "auth": "fas fa-users-cog", + "users": "fas fa-users", + "bot": "fas fa-cogs", + }, + "footer": { + "copyright": False, # Убирает надпись Copyright + "version": False, # Убирает информацию о версии Jazzmin + } +} diff --git a/touchh/urls.py b/touchh/urls.py new file mode 100644 index 00000000..7aff8672 --- /dev/null +++ b/touchh/urls.py @@ -0,0 +1,6 @@ +from django.contrib import admin +from django.urls import path, include + +urlpatterns = [ + path('admin/', admin.site.urls), +] \ No newline at end of file diff --git a/touchh/wsgi.py b/touchh/wsgi.py new file mode 100644 index 00000000..d5f0e3ee --- /dev/null +++ b/touchh/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for touchh project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.1/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'touchh.settings') + +application = get_wsgi_application() diff --git a/users/__init__.py b/users/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/users/__pycache__/__init__.cpython-311.pyc b/users/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 00000000..75d05496 Binary files /dev/null and b/users/__pycache__/__init__.cpython-311.pyc differ diff --git a/users/__pycache__/admin.cpython-311.pyc b/users/__pycache__/admin.cpython-311.pyc new file mode 100644 index 00000000..64088bb0 Binary files /dev/null and b/users/__pycache__/admin.cpython-311.pyc differ diff --git a/users/__pycache__/apps.cpython-311.pyc b/users/__pycache__/apps.cpython-311.pyc new file mode 100644 index 00000000..6d7cfa4f Binary files /dev/null and b/users/__pycache__/apps.cpython-311.pyc differ diff --git a/users/__pycache__/models.cpython-311.pyc b/users/__pycache__/models.cpython-311.pyc new file mode 100644 index 00000000..f8ec046e Binary files /dev/null and b/users/__pycache__/models.cpython-311.pyc differ diff --git a/users/__pycache__/urls.cpython-311.pyc b/users/__pycache__/urls.cpython-311.pyc new file mode 100644 index 00000000..0f784b8a Binary files /dev/null and b/users/__pycache__/urls.cpython-311.pyc differ diff --git a/users/admin.py b/users/admin.py new file mode 100644 index 00000000..3d03faec --- /dev/null +++ b/users/admin.py @@ -0,0 +1,15 @@ +from django.contrib import admin +from .models import User, UserConfirmation + +@admin.register(User) +class UserAdmin(admin.ModelAdmin): + list_display = ('username', 'telegram_id', 'chat_id', 'role', 'confirmed') + search_fields = ('username', 'telegram_id', 'chat_id') + list_filter = ('role', 'confirmed') + ordering = ('-id',) + +@admin.register(UserConfirmation) +class UserConfirmationAdmin(admin.ModelAdmin): + list_display = ('user', 'confirmation_code', 'created_at') + search_fields = ('user__username', 'confirmation_code') + list_filter = ('created_at',) diff --git a/users/apps.py b/users/apps.py new file mode 100644 index 00000000..72b14010 --- /dev/null +++ b/users/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class UsersConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'users' diff --git a/users/migrations/0001_initial.py b/users/migrations/0001_initial.py new file mode 100644 index 00000000..67cccc82 --- /dev/null +++ b/users/migrations/0001_initial.py @@ -0,0 +1,59 @@ +# Generated by Django 5.1.4 on 2024-12-05 23:39 + +import django.contrib.auth.models +import django.contrib.auth.validators +import django.db.models.deletion +import django.utils.timezone +import uuid +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + ] + + operations = [ + migrations.CreateModel( + name='User', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('password', models.CharField(max_length=128, verbose_name='password')), + ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), + ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), + ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')), + ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')), + ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')), + ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')), + ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), + ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), + ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), + ('telegram_id', models.BigIntegerField(blank=True, null=True, unique=True, verbose_name='Telegram ID')), + ('chat_id', models.BigIntegerField(blank=True, null=True, unique=True, verbose_name='Chat ID')), + ('role', models.CharField(choices=[('admin', 'Administrator'), ('hotel_user', 'Hotel User')], default='hotel_user', max_length=20, verbose_name='Role')), + ('confirmed', models.BooleanField(default=False, verbose_name='Confirmed')), + ('groups', models.ManyToManyField(blank=True, related_name='custom_user_set', to='auth.group')), + ('user_permissions', models.ManyToManyField(blank=True, related_name='custom_user_set', to='auth.permission')), + ], + options={ + 'verbose_name': 'user', + 'verbose_name_plural': 'users', + 'abstract': False, + }, + managers=[ + ('objects', django.contrib.auth.models.UserManager()), + ], + ), + migrations.CreateModel( + name='UserConfirmation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('confirmation_code', models.UUIDField(default=uuid.uuid4, verbose_name='Confirmation Code')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.user', verbose_name='User')), + ], + ), + ] diff --git a/users/migrations/__init__.py b/users/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/users/migrations/__pycache__/0001_initial.cpython-311.pyc b/users/migrations/__pycache__/0001_initial.cpython-311.pyc new file mode 100644 index 00000000..12dca8e9 Binary files /dev/null and b/users/migrations/__pycache__/0001_initial.cpython-311.pyc differ diff --git a/users/migrations/__pycache__/__init__.cpython-311.pyc b/users/migrations/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 00000000..2c694291 Binary files /dev/null and b/users/migrations/__pycache__/__init__.cpython-311.pyc differ diff --git a/users/models.py b/users/models.py new file mode 100644 index 00000000..4760f274 --- /dev/null +++ b/users/models.py @@ -0,0 +1,51 @@ +from django.contrib.auth.models import AbstractUser +from django.db import models +import uuid + +class User(AbstractUser): + TELEGRAM_ROLES = [ + ('admin', 'Administrator'), + ('hotel_user', 'Hotel User'), + ] + + telegram_id = models.BigIntegerField( + unique=True, + null=True, + blank=True, + verbose_name="Telegram ID" + ) + chat_id = models.BigIntegerField( + unique=True, + null=True, + blank=True, + verbose_name="Chat ID" + ) + role = models.CharField( + max_length=20, + choices=TELEGRAM_ROLES, + default='hotel_user', + verbose_name="Role" + ) + confirmed = models.BooleanField(default=False, verbose_name="Confirmed") + + groups = models.ManyToManyField( + 'auth.Group', + related_name='custom_user_set', # Уникальное имя для обратной связи + blank=True + ) + user_permissions = models.ManyToManyField( + 'auth.Permission', + related_name='custom_user_set', # Уникальное имя для обратной связи + blank=True + ) + + def __str__(self): + return self.username or f"Telegram User {self.telegram_id}" + +class UserConfirmation(models.Model): + user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="User") + confirmation_code = models.UUIDField(default=uuid.uuid4, verbose_name="Confirmation Code") + created_at = models.DateTimeField(auto_now_add=True, verbose_name="Created At") + + def __str__(self): + return f"Confirmation for {self.user.username} - {self.confirmation_code}" \ No newline at end of file diff --git a/users/tests.py b/users/tests.py new file mode 100644 index 00000000..7ce503c2 --- /dev/null +++ b/users/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/users/urls.py b/users/urls.py new file mode 100644 index 00000000..e69de29b diff --git a/users/views.py b/users/views.py new file mode 100644 index 00000000..91ea44a2 --- /dev/null +++ b/users/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here.