Compare commits

..

7 Commits

Author SHA1 Message Date
20aefeb110 add 'job_title' column to workers table
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2025-08-26 22:04:13 +03:00
173e8959ea rearranged db_port to env 2025-08-20 19:36:48 +03:00
d405e74aad change worker.telegram_id type (INTEGER>>BIGINT) 2025-08-20 19:35:41 +03:00
c0f4be1179 change worker.telegram_id type (INTEGER>>BIGINT)
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone Build is failing
2025-07-28 23:48:33 +03:00
4748127399 Fixed reg_confirm
admins_ids value type
2025-07-28 23:47:17 +03:00
1148d91598 - change worker_id choice
- append possibility to stop create order
- change inline keyboard text
2025-07-28 23:45:40 +03:00
cbb33f6da8 Fixed reg_confirm -\n admins_ids value type \n 2025-07-28 23:39:27 +03:00
7 changed files with 71 additions and 45 deletions

View File

@@ -1,5 +1,4 @@
from .database_engine import async_session_
from .models import Worker,Component, Order
from .models import Worker, Component, Order, job_title
__all__ = ["Worker", "Component", "Order", "async_session_"]
__all__ = ["Worker", "Component", "Order", "async_session_", "job_title"]

View File

@@ -8,7 +8,7 @@ import dotenv
dotenv.load_dotenv(".env")
DATABASE_URL = (f"postgresql+asyncpg://{os.getenv('DB_USER')}:{os.getenv('DB_PASSWORD')}@"
f"{os.getenv('DB_HOST')}:9432/{os.getenv('DATABASE')}")
f"{os.getenv('DB_HOST')}/{os.getenv('DATABASE')}")
print(DATABASE_URL)
engine = create_async_engine(DATABASE_URL, echo=True)
async_session_ = async_sessionmaker(bind=engine, expire_on_commit=False)

View File

@@ -1,8 +1,9 @@
from sqlalchemy import Column, Integer, String, Date, ForeignKey, func, Null
from sqlalchemy import Column, Integer, String, Date, ForeignKey, func, Null, BIGINT
from sqlalchemy.dialects.postgresql import ENUM
from sqlalchemy.orm import relationship, DeclarativeBase
status_enum = ENUM('Выполнено', 'В процессе', 'Создано', 'Ожидание комплектующих', name='status')
job_title = ENUM('Начальник цеха', 'Мастер', 'Сборщик', name='job_title')
class Base(DeclarativeBase):
@@ -22,10 +23,11 @@ class Worker(Base):
__tablename__ = "workers"
id = Column(Integer, primary_key=True, autoincrement=True)
telegram_id = Column(Integer, unique=True, nullable=False)
telegram_id = Column(BIGINT, unique=True, nullable=False)
name = Column(String, nullable=False)
email = Column(String, nullable=True)
phone_number = Column(String, nullable=False)
phone_number = Column(String, default=None)
job_title = Column(job_title, default='Сборщик'),
created_at = Column(Date, server_default=func.now())
updated_at = Column(Date, onupdate=func.now())
@@ -47,7 +49,7 @@ class Order(Base):
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String)
worker_id = Column(Integer, ForeignKey('workers.telegram_id'), nullable=False)
worker_id = Column(BIGINT, ForeignKey('workers.telegram_id'), nullable=False)
status_id = Column(status_enum)
counterparty = Column(String)
customer = Column(String, nullable=False)

View File

@@ -11,8 +11,7 @@ admin_router = Router()
admin_router.message.filter(IsAdmin())
regex = re.compile(r'(del|reg) @.+')
regex = re.compile(r'(del|reg)_@.+')
@admin_router.callback_query(lambda x: re.fullmatch(regex, x.data))
@@ -30,5 +29,3 @@ async def send_message_command(message: Message, bot: Bot):
chat_id = re.search(r'(\d+)', message.text).group()
print(chat_id)
await bot.send_message(text='Ronis->' + message.text.strip('@msg_' + chat_id), chat_id=chat_id)

View File

@@ -4,10 +4,11 @@ from pathlib import Path
import re
from aiogram import Router, Bot, F
from aiogram.filters import CommandStart, Command
from aiogram.types import Message, CallbackQuery, FSInputFile, InputMediaPhoto, InputMediaVideo
from aiogram.types import Message, CallbackQuery, FSInputFile, InputMediaPhoto, InputMediaVideo, ReplyKeyboardRemove
from aiogram.exceptions import AiogramError
from aiogram.fsm.state import State, StatesGroup
from aiogram.fsm.context import FSMContext
from sqlalchemy import select, insert
from loguru import logger
from filters import IsAdmin
@@ -60,22 +61,28 @@ async def orders_menu(message: Message):
@orders_router.callback_query(lambda x: x.data.startswith("create_order"))
async def get_order_worker_id(callback: CallbackQuery, state: FSMContext):
await state.set_state(OrderForm.worker_id)
await callback.message.answer("Введите id сборщика который будет собирать заказ:",
reply_markup=create_inline_kb(**{f"{callback.from_user.id}": "Ввести мой id"}))
async with async_session_() as session:
result = await session.execute(select(Worker.name, Worker.telegram_id).where(Worker.job_title == "Сборщик"))
workers = result.all()
await callback.message.answer("Введите сборщика ответственного за заказ:",
reply_markup=create_inline_kb(
**{f"set_worker_in_order_{tg_id}": name for name, tg_id in workers}))
await callback.message.delete()
@orders_router.message(F.text == "❌ Прервать создание заказа")
async def order_description(message: Message, state: FSMContext):
await state.clear()
await message.answer("Создание заказа прервано", reply_markup=ReplyKeyboardRemove())
@orders_router.callback_query(OrderForm.worker_id)
async def get_order_counterparty(message: Message | CallbackQuery, state: FSMContext):
if isinstance(message, Message):
worker_id = int(message.text)
msg = message
else:
worker_id = int(message.data)
msg = message.message
await msg.answer("Введите данные заказчика ")
await msg.delete()
await state.update_data(worker_id=worker_id)
async def get_order_customer(callback: CallbackQuery, state: FSMContext):
worker_tg_id = int(re.search(r"(\d+)", callback.data).group())
await callback.message.answer("Введите данные заказчика ",
reply_markup=button_create(["❌ Прервать создание заказа"]))
await callback.message.delete()
await state.update_data(worker_id=worker_tg_id)
await state.set_state(OrderForm.customer)
@@ -84,8 +91,9 @@ async def get_order_counterparty(message: Message | CallbackQuery, state: FSMCon
#
@orders_router.message(OrderForm.customer)
async def create_order(message: Message, state: FSMContext):
async def order_description(message: Message, state: FSMContext):
await message.answer("Введите описание заказа в виде ключевых слов (АВР, ПСС, НКУ и т.д.) )")
await message.delete()
await state.update_data(customer=message.text)
await state.set_state(OrderForm.description)
@@ -99,7 +107,7 @@ async def create_order(message: Message, state: FSMContext):
session.add(Order(**order_))
await state.clear()
await message.answer("Заказ успешно создан ")
await message.answer("Заказ успешно создан ", reply_markup=ReplyKeyboardRemove())
@orders_router.callback_query(lambda x: x.data == "find_orders")
@@ -123,13 +131,18 @@ async def search_by_item(message: Message, state: FSMContext):
async with async_session_() as local_session:
search_opt = await state.get_value("search_option")
col = getattr(Order, search_opt)
await message.answer(message.text)
result = await local_session.execute(
select(Order).where(col.ilike(f"%{message.text}%") if search_opt != "id" else col == int(message.text)))
selected_orders = result.scalars().all()
if selected_orders:
await message.answer(text="Список заказов", reply_markup=create_inline_kb(width=1, **dict(
(f"show_order_{order.id}", order.description or "Отсутствует") for order in selected_orders)))
await message.answer(text="Список найденных заказов: ",
reply_markup=create_inline_kb(width=1, **dict(
(f"show_order_{order.id}", f"Описание: {order.description or "Отсутствует"}"
f"Заказ: №{order.id}\n"
f"Заказчик: {order.customer}\n"
) for order in
selected_orders)))
await state.update_data(search_result=selected_orders)
await state.set_state(SearchForm.search_result)
else:

View File

@@ -1,12 +1,11 @@
import os
from asyncio import Event
from asyncio import Event, wait_for, TimeoutError
from aiogram import Router, Bot
from aiogram.filters import CommandStart
from aiogram.types import Message, User
from sqlalchemy import insert, select
from sqlalchemy.orm import selectinload
from keyboards import create_inline_kb
from database import async_session_, Worker
@@ -20,10 +19,11 @@ user_info_template = ("Новый пользователь ждет регист
"Юзернейм: @{}\n"
"ID: @msg_{}\n")
admins_ids = list(map(int, os.getenv("BOT_ADMINS").split(",")))
@registration_router.message(CommandStart())
async def registration_command(message: Message, bot: Bot):
admins_ids = os.getenv("BOT_ADMINS").split(",")
async with async_session_() as session:
async with session.begin():
result = await session.execute(select(Worker).where(Worker.telegram_id == message.from_user.id))
@@ -31,20 +31,29 @@ async def registration_command(message: Message, bot: Bot):
if not user:
user = message.from_user
dict_for_inline = {f'reg @{user.id}': 'Allow', f'del @{user.id}': 'Reject'}
dict_for_inline = {f'reg_@{user.id}': 'Allow', f'del_@{user.id}': 'Reject'}
user_info = user_info_template.format(user.first_name, user.last_name if user.last_name else 'Не указана',
user.username if user.username else 'Не указан', user.id)
for admin in admins_ids:
await bot.send_message(chat_id=admin, text=user_info)
await bot.send_message(chat_id=admin, text='Зарегистрировать пользователя',
reply_markup=create_inline_kb(width=2, **dict_for_inline))
try:
await bot.send_message(chat_id=admin, text=user_info)
await bot.send_message(chat_id=admin, text='Зарегистрировать пользователя',
reply_markup=create_inline_kb(width=2, **dict_for_inline))
except Exception as err:
pass
reg_confirm = Event()
registration_confirm[user.id] = reg_confirm
if await reg_confirm:
try:
await wait_for(reg_confirm.wait(), timeout=60)
async with async_session_() as local_session:
async with local_session.begin():
local_session.add(Worker(telegram_id=int(user.id), name=user.first_name))
del registration_confirm[user.id]
local_session.add(Worker(telegram_id=user.id, name=user.first_name))
await message.answer("Регистрация подтверждена")
except TimeoutError:
await message.answer("Время ожидания истекло.")
del registration_confirm[user.id]
else:
await message.answer("Работа бота возобновлена")

View File

@@ -1,21 +1,27 @@
CREATE TYPE job_title AS ENUM ('Начальник цеха','Мастер','Сборщик');
CREATE TYPE status AS ENUM ('Выполнено','В процессе','Создано','Ожидание комплектующих');
CREATE TABLE workers
(
id SERIAL PRIMARY KEY,
telegram_id INTEGER UNIQUE NOT NULL,
name VARCHAR NOT NULL,
telegram_id BIGINT UNIQUE NOT NULL,
name VARCHAR NOT NULL,
email VARCHAR(50),
phone_number VARCHAR(20) NOT NULL,
phone_number VARCHAR(20),
job_title job_title default 'Сборщик',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP
);
CREATE TYPE status AS ENUM ('Выполнено','В процессе','Создано','Ожидание комплектующих');
CREATE TABLE orders
(
id SERIAL PRIMARY KEY,
name VARCHAR,
worker_id INTEGER REFERENCES workers (telegram_id),
worker_id BIGINT REFERENCES workers (telegram_id),
status_id status DEFAULT 'Создано',
counterparty VARCHAR(50),
customer VARCHAR NOT NULL,