streamlit6Etap / app.py
Aleksmorshen's picture
Update app.py
f125b5e verified
import streamlit as st
import pandas as pd
import sqlite3
import random
import string
from datetime import datetime, timedelta
import pytz
# Подключение к базе данных SQLite3
conn = sqlite3.connect('auth_system.db', check_same_thread=False)
c = conn.cursor()
# Создание таблиц, если они не существуют
c.execute('''
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL UNIQUE,
token TEXT NOT NULL
)
''')
conn.commit()
c.execute('''
CREATE TABLE IF NOT EXISTS products (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
description TEXT,
purchase_price REAL NOT NULL,
sale_price REAL NOT NULL,
quantity_in_stock INTEGER NOT NULL DEFAULT 0,
user_id INTEGER NOT NULL,
FOREIGN KEY(user_id) REFERENCES users(id)
)
''')
conn.commit()
c.execute('''
CREATE TABLE IF NOT EXISTS cart (
id INTEGER PRIMARY KEY AUTOINCREMENT,
product_id INTEGER NOT NULL,
quantity INTEGER NOT NULL,
UNIQUE(product_id)
)
''')
conn.commit()
c.execute('''
CREATE TABLE IF NOT EXISTS sales (
id INTEGER PRIMARY KEY AUTOINCREMENT,
sale_id TEXT NOT NULL,
product_id INTEGER NOT NULL,
quantity INTEGER NOT NULL,
sale_date TIMESTAMP NOT NULL,
total_amount REAL NOT NULL,
FOREIGN KEY(product_id) REFERENCES products(id)
)
''')
conn.commit()
# Функция для генерации случайного 13-значного токена
def generate_token():
return ''.join(random.choices(string.ascii_letters + string.digits, k=13))
# Функция для получения идентификатора пользователя по токену
def get_user_id_by_token(token):
c.execute("SELECT id FROM users WHERE token=?", (token,))
user = c.fetchone()
return user[0] if user else None
# Функция для получения товаров из корзины
def get_cart_summary(user_id):
c.execute('''
SELECT p.name, c.quantity, p.sale_price, c.quantity * p.sale_price
FROM cart c
JOIN products p ON c.product_id = p.id
WHERE p.user_id = ?
''', (user_id,))
items = c.fetchall()
total_quantity = sum(item[1] for item in items)
total_price = sum(item[3] for item in items)
return items, total_quantity, total_price
# Функция для добавления продажи в отчет
def record_sales():
sales_details = []
sale_id = ''.join(random.choices(string.ascii_letters + string.digits, k=8)) # Уникальный идентификатор сделки
sale_date = datetime.now(pytz.timezone('Asia/Bishkek')).strftime('%Y-%m-%d %H:%M:%S')
c.execute('SELECT product_id, quantity FROM cart')
cart_items = c.fetchall()
total_amount = 0.0
for product_id, quantity in cart_items:
# Получение цены за единицу товара
c.execute('SELECT sale_price FROM products WHERE id=?', (product_id,))
sale_price = c.fetchone()[0]
# Расчет общей суммы для этого товара
amount = quantity * sale_price
total_amount += amount
c.execute('''
INSERT INTO sales (sale_id, product_id, quantity, sale_date, total_amount)
VALUES (?, ?, ?, ?, ?)
''', (sale_id, product_id, quantity, sale_date, amount))
sales_details.append((product_id, quantity, amount, sale_date))
c.execute('DELETE FROM cart')
conn.commit()
return sales_details, sale_id, total_amount
# Функция для генерации отчета за месяц
def generate_monthly_report():
start_date = (datetime.now().replace(day=1)).strftime('%Y-%m-%d')
end_date = (datetime.now() + timedelta(days=31)).replace(day=1).strftime('%Y-%m-%d')
c.execute('''
SELECT p.name, SUM(s.quantity) AS total_quantity, p.sale_price, SUM(s.quantity) * p.sale_price AS total_sales,
SUM(s.quantity) * (p.sale_price - p.purchase_price) AS profit
FROM sales s
JOIN products p ON s.product_id = p.id
WHERE s.sale_date BETWEEN ? AND ?
GROUP BY p.id
''', (start_date, end_date))
sales_data = c.fetchall()
# Расчёт общей суммы продаж и прибыли
total_sales = sum(item[3] for item in sales_data)
total_profit = sum(item[4] for item in sales_data)
return sales_data, total_sales, total_profit
# Функция для получения всех сделок
def get_all_sales():
c.execute('''
SELECT DISTINCT sale_id, sale_date, SUM(total_amount) AS total_amount
FROM sales
GROUP BY sale_id, sale_date
ORDER BY sale_date DESC
''')
sales_data = c.fetchall()
return sales_data
# Функция для получения всех подробностей сделок
def get_sale_details(sale_id):
c.execute('''
SELECT p.name, s.quantity, p.sale_price, s.sale_date
FROM sales s
JOIN products p ON s.product_id = p.id
WHERE s.sale_id = ?
''', (sale_id,))
sale_details = c.fetchall()
return sale_details
# Страница регистрации
def register():
st.title('Регистрация')
username = st.text_input("Введите ваше имя пользователя")
admin_password = st.text_input("Введите пароль администратора", type="password")
if st.button("Зарегистрироваться"):
if admin_password == "1234":
token = generate_token()
try:
c.execute("INSERT INTO users (username, token) VALUES (?, ?)", (username, token))
conn.commit()
st.success(f"Регистрация успешна! Ваш токен: {token}")
except sqlite3.IntegrityError:
st.error("Это имя пользователя уже занято. Попробуйте другое.")
else:
st.error("Неверный пароль администратора!")
# Страница авторизации
def login():
st.title('Авторизация')
token_input = st.text_input("Введите ваш токен")
if st.button("Войти"):
user_id = get_user_id_by_token(token_input)
if user_id:
st.session_state.logged_in = True # Устанавливаем состояние авторизации
st.session_state.username = token_input
st.session_state.user_id = user_id
st.success("Добро пожаловать!")
else:
st.error("Неверный токен!")
# Форма добавления товара
def add_product():
st.title("Добавление товара")
product_name = st.text_input("Название товара").strip().lower() # Преобразование в нижний регистр
product_description = st.text_area("Описание товара")
purchase_price = st.number_input("Приходная цена", min_value=0.0, step=0.01) # Запрос приходной цены
sale_price = st.number_input("Отпускная цена", min_value=0.0, step=0.01) # Запрос отпускной цены
product_quantity = st.number_input("Количество на складе", min_value=0, step=1)
if st.button("Добавить товар"):
if product_name and sale_price:
c.execute("INSERT INTO products (name, description, purchase_price, sale_price, quantity_in_stock, user_id) VALUES (?, ?, ?, ?, ?, ?)",
(product_name, product_description, purchase_price, sale_price, product_quantity, st.session_state.user_id))
conn.commit()
st.success("Товар успешно добавлен!")
else:
st.error("Пожалуйста, введите все обязательные данные.")
# Форма редактирования и удаления товара
def edit_products():
st.title("Редактирование товара")
products = c.execute("SELECT id, name, description, purchase_price, sale_price, quantity_in_stock FROM products WHERE user_id=?",
(st.session_state.user_id,)).fetchall()
if products:
product_names = [p[1] for p in products]
product_id = st.selectbox("Выберите товар", product_names)
product = next(p for p in products if p[1] == product_id)
new_name = st.text_input("Новое название товара", product[1])
new_description = st.text_area("Новое описание товара", product[2])
new_purchase_price = st.number_input("Новая приходная цена", min_value=0.0, step=0.01, value=product[3])
new_sale_price = st.number_input("Новая отпускная цена", min_value=0.0, step=0.01, value=product[4])
new_quantity_in_stock = st.number_input("Новое количество на складе", min_value=0, step=1, value=product[5])
if st.button("Сохранить изменения"):
c.execute('''
UPDATE products
SET name = ?, description = ?, purchase_price = ?, sale_price = ?, quantity_in_stock = ?
WHERE id = ?
''', (new_name, new_description, new_purchase_price, new_sale_price, new_quantity_in_stock, product[0]))
conn.commit()
st.success("Товар успешно обновлен!")
if st.button("Удалить товар"):
c.execute("DELETE FROM products WHERE id=?", (product[0],))
conn.commit()
st.success("Товар успешно удален!")
# Форма отпуска товара
def add_to_cart():
st.title("Отпуск товара")
products = c.execute("SELECT id, name, sale_price, quantity_in_stock FROM products WHERE user_id=?",
(st.session_state.user_id,)).fetchall()
search_term = st.text_input("Поиск товара").strip().lower() # Преобразуем ввод в нижний регистр
# Поиск товаров по ключевому слову (без учета регистра)
c.execute("SELECT id, name, sale_price, quantity_in_stock FROM products WHERE user_id=? AND LOWER(name) LIKE ?",
(st.session_state.user_id, f"%{search_term}%"))
products = c.fetchall()
if products:
for product in products:
cols = st.columns(4)
with cols[0]:
st.write(product[1]) # Название товара
with cols[1]:
quantity = st.number_input(f"Количество для '{product[1]}'", min_value=1, max_value=product[3], key=f"quantity_{product[0]}")
with cols[2]:
add_button = st.button(f"Добавить в корзину", key=f"add_{product[0]}")
if add_button:
if quantity <= product[3]:
# Обработка добавления товара в корзину
c.execute('''
INSERT INTO cart (product_id, quantity)
VALUES (?, ?)
ON CONFLICT(product_id)
DO UPDATE SET quantity = quantity + excluded.quantity
''', (product[0], quantity))
# Уменьшаем количество на складе
c.execute("UPDATE products SET quantity_in_stock = quantity_in_stock - ? WHERE id=?",
(quantity, product[0]))
conn.commit()
st.success(f"Товар '{product[1]}' успешно добавлен в корзину!")
else:
st.error(f"Недостаточное количество товара '{product[1]}' на складе!")
with cols[3]:
remove_button = st.button(f"Удалить из корзины", key=f"remove_{product[0]}")
if remove_button:
if quantity > 0:
# Обработка удаления товара из корзины
current_quantity = c.execute("SELECT quantity FROM cart WHERE product_id=?", (product[0],)).fetchone()
if current_quantity:
new_quantity = current_quantity[0] - quantity
if new_quantity > 0:
c.execute('''
INSERT INTO cart (product_id, quantity)
VALUES (?, ?)
ON CONFLICT(product_id)
DO UPDATE SET quantity = excluded.quantity
''', (product[0], new_quantity))
else:
c.execute("DELETE FROM cart WHERE product_id=?", (product[0],))
# Увеличиваем количество на складе
c.execute("UPDATE products SET quantity_in_stock = quantity_in_stock + ? WHERE id=?",
(quantity, product[0]))
conn.commit()
st.success(f"Товар '{product[1]}' успешно удалён из корзины!")
else:
st.error(f"Товар '{product[1]}' не найден в корзине.")
else:
st.error(f"Введите количество для удаления товара '{product[1]}'.")
# Отображение состояния корзины
st.subheader("Состояние корзины")
items, total_quantity, total_price = get_cart_summary(st.session_state.user_id)
if items:
# Создание DataFrame для таблицы
df = pd.DataFrame(items, columns=["Название", "Количество", "Цена за единицу", "Итого"])
st.dataframe(df.style.format({"Цена за единицу": "{:.2f}", "Итого": "{:.2f}"}), use_container_width=True)
st.write(f"Общее количество: {total_quantity}, Общая стоимость: {total_price:.2f}")
# Добавляем кнопку "Пробить" для оформления продажи
if st.button("Пробить"):
sales_details, sale_id, total_amount = record_sales()
if sales_details:
st.write("**Детали сделок:**")
sale_details_df = pd.DataFrame(sales_details, columns=["ID товара", "Количество", "Сумма", "Дата и время"])
st.dataframe(sale_details_df.style.format({"Сумма": "{:.2f}", "Дата и время": lambda x: pd.to_datetime(x).strftime('%d-%m-%Y %H:%M:%S')}), use_container_width=True)
st.write(f"**Общая сумма сделки:** {total_amount:.2f}")
st.success("Корзина успешно пробита! Все товары добавлены в отчет и корзина очищена.")
# Кнопка для отображения сделок
if st.button("Сделки"):
sales_data = get_all_sales()
if sales_data:
sale_ids = [sale[0] for sale in sales_data]
for sale_id, sale_date, total_amount in sales_data:
st.write(f"**Сделка ID:** {sale_id} ({sale_date}) - **Общая сумма:** {total_amount:.2f}")
sale_details = get_sale_details(sale_id)
if sale_details:
df_sales = pd.DataFrame(sale_details, columns=["Название товара", "Количество", "Цена за единицу", "Дата и время"])
st.dataframe(df_sales.style.format({"Дата и время": lambda x: pd.to_datetime(x).strftime('%d-%m-%Y %H:%M:%S')}), use_container_width=True)
else:
st.info("Нет деталей для отображения.")
else:
st.info("Нет сделок для отображения.")
else:
st.info("Корзина пуста.")
# Страница отчета о продажах за месяц
def monthly_report():
st.title("Отчет о продажах за месяц")
sales_data, total_sales, total_profit = generate_monthly_report()
if sales_data:
# Создание DataFrame для отчета
df = pd.DataFrame(sales_data, columns=["Название", "Общее количество", "Отпускная цена", "Общие продажи", "Прибыль"])
st.write(f"**Отчет за {datetime.now().strftime('%B %Y')}**")
st.dataframe(df.style.format({"Отпускная цена": "{:.2f}", "Общие продажи": "{:.2f}", "Прибыль": "{:.2f}"}), use_container_width=True)
st.write(f"**Общая сумма продаж**: {total_sales:.2f}")
st.write(f"**Общая сумма прибыли**: {total_profit:.2f}")
# Кнопка для отображения сделок
if st.button("Сделки"):
sales_data = get_all_sales()
if sales_data:
sale_ids = [sale[0] for sale in sales_data]
for sale_id, sale_date, total_amount in sales_data:
st.write(f"**Сделка ID:** {sale_id} ({sale_date}) - **Общая сумма:** {total_amount:.2f}")
sale_details = get_sale_details(sale_id)
if sale_details:
df_sales = pd.DataFrame(sale_details, columns=["Название товара", "Количество", "Цена за единицу", "Дата и время"])
st.dataframe(df_sales.style.format({"Дата и время": lambda x: pd.to_datetime(x).strftime('%d-%m-%Y %H:%M:%S')}), use_container_width=True)
else:
st.info("Нет деталей для отображения.")
else:
st.info("Нет сделок для отображения.")
else:
st.info("Нет данных о продажах за этот месяц.")
# Главная функция приложения
def main():
if 'logged_in' not in st.session_state:
st.session_state.logged_in = False
if st.session_state.logged_in:
st.sidebar.title(f"Привет, {st.session_state.username}!")
option = st.sidebar.selectbox("Выберите действие", ["Добавить товар", "Отпуск товара", "Редактировать товары", "Отчет за месяц", "Выйти"])
if option == "Добавить товар":
add_product()
elif option == "Отпуск товара":
add_to_cart()
elif option == "Редактировать товары":
edit_products()
elif option == "Отчет за месяц":
monthly_report()
elif option == "Выйти":
st.session_state.logged_in = False
st.session_state.username = None
st.session_state.user_id = None
st.success("Вы вышли из системы!")
else:
page = st.sidebar.selectbox("Выберите страницу", ["Авторизация", "Регистрация"])
if page == "Регистрация":
register()
elif page == "Авторизация":
login()
if __name__ == "__main__":
main()