Aleksmorshen commited on
Commit
ef8a53b
·
verified ·
1 Parent(s): 7f64997

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +414 -0
app.py ADDED
@@ -0,0 +1,414 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import sqlite3
4
+ import random
5
+ import string
6
+ from datetime import datetime, timedelta
7
+ import pytz
8
+
9
+ # Подключение к базе данных SQLite3
10
+ conn = sqlite3.connect('auth_system.db', check_same_thread=False)
11
+ c = conn.cursor()
12
+
13
+ # Создание таблиц, если они не существуют
14
+ c.execute('''
15
+ CREATE TABLE IF NOT EXISTS users (
16
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
17
+ username TEXT NOT NULL UNIQUE,
18
+ token TEXT NOT NULL
19
+ )
20
+ ''')
21
+ conn.commit()
22
+
23
+ c.execute('''
24
+ CREATE TABLE IF NOT EXISTS products (
25
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
26
+ name TEXT NOT NULL,
27
+ description TEXT,
28
+ purchase_price REAL NOT NULL,
29
+ sale_price REAL NOT NULL,
30
+ quantity_in_stock INTEGER NOT NULL DEFAULT 0,
31
+ user_id INTEGER NOT NULL,
32
+ FOREIGN KEY(user_id) REFERENCES users(id)
33
+ )
34
+ ''')
35
+ conn.commit()
36
+
37
+ c.execute('''
38
+ CREATE TABLE IF NOT EXISTS cart (
39
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
40
+ product_id INTEGER NOT NULL,
41
+ quantity INTEGER NOT NULL,
42
+ UNIQUE(product_id)
43
+ )
44
+ ''')
45
+ conn.commit()
46
+
47
+ c.execute('''
48
+ CREATE TABLE IF NOT EXISTS sales (
49
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
50
+ sale_id TEXT NOT NULL,
51
+ product_id INTEGER NOT NULL,
52
+ quantity INTEGER NOT NULL,
53
+ sale_date TIMESTAMP NOT NULL,
54
+ total_amount REAL NOT NULL,
55
+ FOREIGN KEY(product_id) REFERENCES products(id)
56
+ )
57
+ ''')
58
+ conn.commit()
59
+
60
+ # Функция для генерации случайного 13-значного токена
61
+ def generate_token():
62
+ return ''.join(random.choices(string.ascii_letters + string.digits, k=13))
63
+
64
+ # Функция для получения идентификатора пользователя по токену
65
+ def get_user_id_by_token(token):
66
+ c.execute("SELECT id FROM users WHERE token=?", (token,))
67
+ user = c.fetchone()
68
+ return user[0] if user else None
69
+
70
+ # Функция для получения товаров из корзины
71
+ def get_cart_summary(user_id):
72
+ c.execute('''
73
+ SELECT p.name, c.quantity, p.sale_price, c.quantity * p.sale_price
74
+ FROM cart c
75
+ JOIN products p ON c.product_id = p.id
76
+ WHERE p.user_id = ?
77
+ ''', (user_id,))
78
+ items = c.fetchall()
79
+ total_quantity = sum(item[1] for item in items)
80
+ total_price = sum(item[3] for item in items)
81
+ return items, total_quantity, total_price
82
+
83
+ # Функция для добавления продажи в отчет
84
+ def record_sales():
85
+ sales_details = []
86
+ sale_id = ''.join(random.choices(string.ascii_letters + string.digits, k=8)) # Уникальный идентификатор сделки
87
+ sale_date = datetime.now(pytz.timezone('Asia/Bishkek')).strftime('%Y-%m-%d %H:%M:%S')
88
+
89
+ c.execute('SELECT product_id, quantity FROM cart')
90
+ cart_items = c.fetchall()
91
+
92
+ total_amount = 0.0
93
+ for product_id, quantity in cart_items:
94
+ # Получение цены за единицу товара
95
+ c.execute('SELECT sale_price FROM products WHERE id=?', (product_id,))
96
+ sale_price = c.fetchone()[0]
97
+
98
+ # Расчет общей суммы для этого товара
99
+ amount = quantity * sale_price
100
+ total_amount += amount
101
+
102
+ c.execute('''
103
+ INSERT INTO sales (sale_id, product_id, quantity, sale_date, total_amount)
104
+ VALUES (?, ?, ?, ?, ?)
105
+ ''', (sale_id, product_id, quantity, sale_date, amount))
106
+ sales_details.append((product_id, quantity, amount, sale_date))
107
+
108
+ c.execute('DELETE FROM cart')
109
+ conn.commit()
110
+ return sales_details, sale_id, total_amount
111
+
112
+ # Функция для генерации отчета за месяц
113
+ def generate_monthly_report(user_id):
114
+ start_date = (datetime.now().replace(day=1)).strftime('%Y-%m-%d')
115
+ end_date = (datetime.now() + timedelta(days=31)).replace(day=1).strftime('%Y-%m-%d')
116
+
117
+ c.execute('''
118
+ SELECT p.name, SUM(s.quantity) AS total_quantity, p.sale_price, SUM(s.quantity) * p.sale_price AS total_sales,
119
+ SUM(s.quantity) * (p.sale_price - p.purchase_price) AS profit
120
+ FROM sales s
121
+ JOIN products p ON s.product_id = p.id
122
+ WHERE s.sale_date BETWEEN ? AND ? AND p.user_id = ?
123
+ GROUP BY p.id
124
+ ''', (start_date, end_date, user_id))
125
+
126
+ sales_data = c.fetchall()
127
+
128
+ total_sales = sum(item[3] for item in sales_data)
129
+ total_profit = sum(item[4] for item in sales_data)
130
+
131
+ return sales_data, total_sales, total_profit
132
+
133
+
134
+ # Функция для получения всех сделок
135
+ def get_all_sales(user_id):
136
+ c.execute('''
137
+ SELECT DISTINCT sale_id, sale_date, SUM(total_amount) AS total_amount
138
+ FROM sales s
139
+ JOIN products p ON s.product_id = p.id
140
+ WHERE p.user_id = ?
141
+ GROUP BY sale_id, sale_date
142
+ ORDER BY sale_date DESC
143
+ ''', (user_id,))
144
+ sales_data = c.fetchall()
145
+ return sales_data
146
+
147
+
148
+ # Функция для получения всех подробностей сделок
149
+ def get_sale_details(sale_id):
150
+ c.execute('''
151
+ SELECT p.name, s.quantity, p.sale_price, s.sale_date
152
+ FROM sales s
153
+ JOIN products p ON s.product_id = p.id
154
+ WHERE s.sale_id = ?
155
+ ''', (sale_id,))
156
+ sale_details = c.fetchall()
157
+ return sale_details
158
+
159
+ # Страница регистрации
160
+ def register():
161
+ st.title('Регистрация')
162
+ username = st.text_input("Введите ваше имя пользователя")
163
+ admin_password = st.text_input("Введите пароль администратора", type="password")
164
+
165
+ if st.button("Зарегистрироваться"):
166
+ if admin_password == "morshenfullsumflpol":
167
+ token = generate_token()
168
+ try:
169
+ c.execute("INSERT INTO users (username, token) VALUES (?, ?)", (username, token))
170
+ conn.commit()
171
+ st.success(f"Регистрация успешна! Ваш токен: {token}")
172
+ except sqlite3.IntegrityError:
173
+ st.error("Это имя пользователя уже занято. Попробуйте другое.")
174
+ else:
175
+ st.error("Неверный пароль администратора!")
176
+
177
+ # Страница авторизации
178
+ def login():
179
+ st.title('Авторизация')
180
+ token_input = st.text_input("Введите ваш токен")
181
+
182
+ if st.button("Войти"):
183
+ user_id = get_user_id_by_token(token_input)
184
+ if user_id:
185
+ st.session_state.logged_in = True # Устанавливаем состояние авторизации
186
+ st.session_state.username = token_input
187
+ st.session_state.user_id = user_id
188
+ st.success("Добро пожаловать!")
189
+ else:
190
+ st.error("Неверный токен!")
191
+
192
+ # Форма добавления товара
193
+ def add_product():
194
+ st.title("Добавление товара")
195
+ product_name = st.text_input("Название товара").strip().lower() # Преобразование в нижний регистр
196
+ product_description = st.text_area("Описание товара")
197
+ purchase_price = st.number_input("Приходная цена", min_value=0.0, step=0.01) # Запрос приходной цены
198
+ sale_price = st.number_input("Отпускная цена", min_value=0.0, step=0.01) # Запрос отпускной цены
199
+ product_quantity = st.number_input("Количество на складе", min_value=0, step=1)
200
+
201
+ if st.button("Добавить товар"):
202
+ if product_name and sale_price:
203
+ c.execute("INSERT INTO products (name, description, purchase_price, sale_price, quantity_in_stock, user_id) VALUES (?, ?, ?, ?, ?, ?)",
204
+ (product_name, product_description, purchase_price, sale_price, product_quantity, st.session_state.user_id))
205
+ conn.commit()
206
+ st.success("Товар успешно добавлен!")
207
+ else:
208
+ st.error("Пожалуйста, введите все обязательные данные.")
209
+
210
+ # Форма редактирования и удаления товара
211
+ def edit_products():
212
+ st.title("Редактирование товара")
213
+ products = c.execute("SELECT id, name, description, purchase_price, sale_price, quantity_in_stock FROM products WHERE user_id=?",
214
+ (st.session_state.user_id,)).fetchall()
215
+
216
+ if products:
217
+ product_names = [p[1] for p in products]
218
+ product_id = st.selectbox("Выберите товар", product_names)
219
+ product = next(p for p in products if p[1] == product_id)
220
+
221
+ new_name = st.text_input("Новое название товара", product[1])
222
+ new_description = st.text_area("Новое описание товара", product[2])
223
+ new_purchase_price = st.number_input("Новая приходная цена", min_value=0.0, step=0.01, value=product[3])
224
+ new_sale_price = st.number_input("Новая отпускная цена", min_value=0.0, step=0.01, value=product[4])
225
+ new_quantity_in_stock = st.number_input("Новое количество на складе", min_value=0, step=1, value=product[5])
226
+
227
+ if st.button("Сохранить изменения"):
228
+ c.execute('''
229
+ UPDATE products
230
+ SET name = ?, description = ?, purchase_price = ?, sale_price = ?, quantity_in_stock = ?
231
+ WHERE id = ?
232
+ ''', (new_name, new_description, new_purchase_price, new_sale_price, new_quantity_in_stock, product[0]))
233
+ conn.commit()
234
+ st.success("Товар успешно обновлен!")
235
+
236
+ if st.button("Удалить товар"):
237
+ c.execute("DELETE FROM products WHERE id=?", (product[0],))
238
+ conn.commit()
239
+ st.success("Товар успешно удален!")
240
+
241
+ # Форма отпуска товара
242
+ def add_to_cart():
243
+ st.title("Отпуск товара")
244
+ products = c.execute("SELECT id, name, sale_price, quantity_in_stock FROM products WHERE user_id=?",
245
+ (st.session_state.user_id,)).fetchall()
246
+ search_term = st.text_input("Поиск товара").strip().lower() # Преобразуем ввод в нижний регистр
247
+
248
+ # Поиск товаров по ключевому слову (без учета регистра)
249
+ c.execute("SELECT id, name, sale_price, quantity_in_stock FROM products WHERE user_id=? AND LOWER(name) LIKE ?",
250
+ (st.session_state.user_id, f"%{search_term}%"))
251
+ products = c.fetchall()
252
+
253
+ if products:
254
+ for product in products:
255
+ cols = st.columns(4)
256
+ with cols[0]:
257
+ st.write(product[1]) # Название товара
258
+ st.write(f"**Отпускная цена**: {product[2]:.2f}") # Показываем только отпускную цену
259
+ st.write(f"**Остаток на складе**: {product[3]}")
260
+
261
+ with cols[1]:
262
+ quantity = st.number_input(f"Количество для '{product[1]}'", min_value=0, max_value=product[3], key=f"quantity_{product[0]}")
263
+
264
+ with cols[2]:
265
+ add_button = st.button(f"Добавить в корзину", key=f"add_{product[0]}")
266
+
267
+ if add_button:
268
+ if quantity <= product[3]:
269
+ # Обработка добавления товара в корзину
270
+ c.execute('''
271
+ INSERT INTO cart (product_id, quantity)
272
+ VALUES (?, ?)
273
+ ON CONFLICT(product_id)
274
+ DO UPDATE SET quantity = quantity + excluded.quantity
275
+ ''', (product[0], quantity))
276
+
277
+ # Уменьшаем количество на складе
278
+ c.execute("UPDATE products SET quantity_in_stock = quantity_in_stock - ? WHERE id=?",
279
+ (quantity, product[0]))
280
+ conn.commit()
281
+ st.success(f"Товар '{product[1]}' успешно добавлен в корзину!")
282
+ else:
283
+ st.error(f"Недостаточное количество товара '{product[1]}' на складе!")
284
+
285
+ with cols[3]:
286
+ remove_button = st.button(f"Удалить из корзины", key=f"remove_{product[0]}")
287
+
288
+ if remove_button:
289
+ if quantity > 0:
290
+ # Обработка удаления товара из корзины
291
+ current_quantity = c.execute("SELECT quantity FROM cart WHERE product_id=?", (product[0],)).fetchone()
292
+ if current_quantity:
293
+ new_quantity = current_quantity[0] - quantity
294
+ if new_quantity > 0:
295
+ c.execute('''
296
+ INSERT INTO cart (product_id, quantity)
297
+ VALUES (?, ?)
298
+ ON CONFLICT(product_id)
299
+ DO UPDATE SET quantity = excluded.quantity
300
+ ''', (product[0], new_quantity))
301
+ else:
302
+ c.execute("DELETE FROM cart WHERE product_id=?", (product[0],))
303
+
304
+ # Увеличиваем количество на складе
305
+ c.execute("UPDATE products SET quantity_in_stock = quantity_in_stock + ? WHERE id=?",
306
+ (quantity, product[0]))
307
+ conn.commit()
308
+ st.success(f"Товар '{product[1]}' успешно удалён из корзины!")
309
+ else:
310
+ st.error(f"Товар '{product[1]}' не найден в корзине.")
311
+ else:
312
+ st.error(f"Введите количество для удаления товара '{product[1]}'.")
313
+
314
+ # Отображение состояния корзины
315
+ st.subheader("Состояние корзины")
316
+ items, total_quantity, total_price = get_cart_summary(st.session_state.user_id)
317
+
318
+ if items:
319
+ # Создание DataFrame для таблицы
320
+ df = pd.DataFrame(items, columns=["Название", "Количество", "Цена за единицу", "Итого"])
321
+ st.dataframe(df.style.format({"Цена за единицу": "{:.2f}", "Итого": "{:.2f}"}), use_container_width=True)
322
+
323
+ st.write(f"Общее количество: {total_quantity}, Общая стоимость: {total_price:.2f}")
324
+
325
+ # Добавляем кнопку "Пробить" для оформления продажи
326
+ if st.button("Пробить"):
327
+ sales_details, sale_id, total_amount = record_sales()
328
+ if sales_details:
329
+ st.write("**Детали сделок:**")
330
+ sale_details_df = pd.DataFrame(sales_details, columns=["ID товара", "Количество", "Сумма", "Дата и время"])
331
+ 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)
332
+ st.write(f"**Общая сумма сделки:** {total_amount:.2f}")
333
+ st.success("Корзина успешно пробита! Все товары добавлены в отчет и корзина очищена.")
334
+
335
+ # Кнопка для отображения сделок
336
+ if st.button("Сделки"):
337
+ sales_data = get_all_sales()
338
+ if sales_data:
339
+ sale_ids = [sale[0] for sale in sales_data]
340
+ for sale_id, sale_date, total_amount in sales_data:
341
+ st.write(f"**Сделка ID:** {sale_id} ({sale_date}) - **Общая сумма:** {total_amount:.2f}")
342
+ sale_details = get_sale_details(sale_id)
343
+ if sale_details:
344
+ df_sales = pd.DataFrame(sale_details, columns=["Название товара", "Количество", "Цена за единицу", "Дата и время"])
345
+ st.dataframe(df_sales.style.format({"Дата и время": lambda x: pd.to_datetime(x).strftime('%d-%m-%Y %H:%M:%S')}), use_container_width=True)
346
+ else:
347
+ st.info("Нет деталей для отображения.")
348
+ else:
349
+ st.info("Нет сделок для отображения.")
350
+ else:
351
+ st.info("Корзина пуста.")
352
+
353
+ # Страница отчета о продажах за месяц
354
+ def monthly_report():
355
+ st.title("Отчет о продажах за месяц")
356
+ sales_data, total_sales, total_profit = generate_monthly_report(st.session_state.user_id)
357
+ if sales_data:
358
+ # Создание DataFrame для отчета
359
+ df = pd.DataFrame(sales_data, columns=["Название", "Общее количество", "Отпускная цена", "Общие продажи", "Прибыль"])
360
+ st.write(f"**Отчет за {datetime.now().strftime('%B %Y')}**")
361
+ st.dataframe(df.style.format({"Отпускная цена": "{:.2f}", "Общие продажи": "{:.2f}", "Прибыль": "{:.2f}"}), use_container_width=True)
362
+
363
+ st.write(f"**Общая сумма продаж**: {total_sales:.2f}")
364
+ st.write(f"**Общая сумма прибыли**: {total_profit:.2f}")
365
+
366
+ # Кнопка для отображения сделок
367
+ if st.button("Сделки"):
368
+ sales_data = get_all_sales(st.session_state.user_id)
369
+ if sales_data:
370
+ sale_ids = [sale[0] for sale in sales_data]
371
+ for sale_id, sale_date, total_amount in sales_data:
372
+ st.write(f"**Сделка ID:** {sale_id} ({sale_date}) - **Общая сумма:** {total_amount:.2f}")
373
+ sale_details = get_sale_details(sale_id)
374
+ if sale_details:
375
+ df_sales = pd.DataFrame(sale_details, columns=["Название товара", "Количество", "Цена за единицу", "Дата и время"])
376
+ st.dataframe(df_sales.style.format({"Дата и время": lambda x: pd.to_datetime(x).strftime('%d-%m-%Y %H:%M:%S')}), use_container_width=True)
377
+ else:
378
+ st.info("Нет деталей для отображения.")
379
+ else:
380
+ st.info("Нет сделок для отображения.")
381
+ else:
382
+ st.info("Нет данных о продажах за этот месяц.")
383
+
384
+ # Главная функция приложения
385
+ def main():
386
+ if 'logged_in' not in st.session_state:
387
+ st.session_state.logged_in = False
388
+
389
+ if st.session_state.logged_in:
390
+ st.sidebar.title(f"Привет, {st.session_state.username}!")
391
+ option = st.sidebar.selectbox("Выберите действие", ["Добавить товар", "Отпуск товара", "Редактировать товары", "Отчет за месяц", "Выйти"])
392
+
393
+ if option == "Добавить товар":
394
+ add_product()
395
+ elif option == "Отпуск товара":
396
+ add_to_cart()
397
+ elif option == "Редактировать товары":
398
+ edit_products()
399
+ elif option == "Отчет за месяц":
400
+ monthly_report()
401
+ elif option == "Выйти":
402
+ st.session_state.logged_in = False
403
+ st.session_state.username = None
404
+ st.session_state.user_id = None
405
+ st.success("Вы вышли из системы!")
406
+ else:
407
+ page = st.sidebar.selectbox("Выберите страницу", ["Авторизация", "Регистрация"])
408
+ if page == "Регистрация":
409
+ register()
410
+ elif page == "Авторизация":
411
+ login()
412
+
413
+ if __name__ == "__main__":
414
+ main()