Aleksmorshen commited on
Commit
9868ad4
·
verified ·
1 Parent(s): 5364a48

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +85 -90
app.py CHANGED
@@ -5,7 +5,6 @@ import json
5
  import random
6
  import string
7
  from datetime import datetime, timedelta
8
- import pytz
9
  import time
10
  import threading
11
  from huggingface_hub import HfApi, hf_hub_download
@@ -13,32 +12,34 @@ from huggingface_hub import HfApi, hf_hub_download
13
  # --- Настройки Hugging Face ---
14
  REPO_ID = "Testbase1/testsett" # Замените на ваш репозиторий
15
  DB_FILENAME = "auth_system.json" # JSON база данных
16
- HF_TOKEN_WRITE = os.getenv("HF_TOKEN") # Токен для записи (загрузки)
17
- HF_TOKEN_READ = os.getenv("HF_TOKEN_READ") # Токен для чтения (скачивания)
18
 
19
  # Глобальный блокировщик для доступа к JSON-файлу
20
  db_lock = threading.Lock()
21
 
22
- # Функция загрузки базы данных из JSON-файла
 
23
  def load_db():
 
24
  if not os.path.exists(DB_FILENAME):
25
  data = {"users": [], "products": [], "cart": [], "sales": []}
26
  save_db(data)
27
  return data
28
- with open(DB_FILENAME, "r", encoding="utf8") as f:
29
- try:
30
  data = json.load(f)
31
- except json.JSONDecodeError:
32
- data = {"users": [], "products": [], "cart": [], "sales": []}
33
- save_db(data)
34
  return data
35
 
36
- # Функция сохранения базы данных в JSON-файл
37
  def save_db(data):
38
- with open(DB_FILENAME, "w", encoding="utf8") as f:
39
- json.dump(data, f, ensure_ascii=False, indent=4)
 
 
40
 
41
- # --- Функция резервного копирования (загрузка базы на Hugging Face) ---
42
  def upload_db_to_hf():
43
  """Загружает JSON-файл базы данных в репозиторий Hugging Face."""
44
  try:
@@ -48,13 +49,13 @@ def upload_db_to_hf():
48
  path_in_repo=DB_FILENAME,
49
  repo_id=REPO_ID,
50
  repo_type="dataset",
51
- token=HF_TOKEN_WRITE
 
52
  )
53
  print("Резервная копия JSON базы успешно загружена на Hugging Face.")
54
  except Exception as e:
55
  print("Ошибка при загрузке резервной копии:", e)
56
 
57
- # --- Функция скачивания базы данных из Hugging Face ---
58
  def download_db_from_hf():
59
  """Скачивает JSON-файл базы данных из репозитория Hugging Face."""
60
  try:
@@ -72,10 +73,9 @@ def download_db_from_hf():
72
  print("Ошибка при скачивании JSON базы:", e)
73
  return False
74
 
75
- # --- Функция периодического резервного копирования ---
76
  def periodic_backup():
77
  """
78
- Каждые 30 минут (1800 секунд) вызывается функция upload_db_to_hf().
79
  """
80
  while True:
81
  upload_db_to_hf()
@@ -83,16 +83,16 @@ def periodic_backup():
83
 
84
  # --- Вспомогательные функции ---
85
  def generate_token():
 
86
  return ''.join(random.choices(string.ascii_letters + string.digits, k=13))
87
 
88
  def get_new_id(items):
 
89
  return max([item.get("id", 0) for item in items], default=0) + 1
90
 
91
  # --- Функции для работы с продажами ---
92
  def record_sales():
93
- """
94
- Записывает информацию о продажах, обновляет базу данных и очищает корзину.
95
- """
96
  with db_lock:
97
  data = load_db()
98
  cart_items = data["cart"]
@@ -111,7 +111,6 @@ def record_sales():
111
  total_amount += sale_amount
112
  sales_details.append([product["id"], item["quantity"], sale_amount, now])
113
 
114
- # Добавляем ��нформацию о продаже в базу данных
115
  new_sale_id = get_new_id(data["sales"])
116
  data["sales"].append({
117
  "id": new_sale_id,
@@ -122,15 +121,14 @@ def record_sales():
122
  "sale_date": now
123
  })
124
 
125
- # Очищаем корзину
126
  data["cart"] = []
127
  save_db(data)
128
 
129
  return sales_details, sale_id, total_amount
130
 
131
  # --- Страницы приложения ---
132
-
133
  def register():
 
134
  st.title('Регистрация')
135
  username = st.text_input("Введите ваше имя пользователя")
136
  admin_password = st.text_input("Введите пароль администратора", type="password")
@@ -151,13 +149,13 @@ def register():
151
  st.error("Неверный пароль администратора!")
152
 
153
  def login():
 
154
  st.title('Авторизация')
155
  token_input = st.text_input("Введите ваш токен")
156
 
157
  if st.button("Войти"):
158
- with db_lock:
159
- data = load_db()
160
- user = next((u for u in data["users"] if u["token"] == token_input), None)
161
  if user:
162
  st.session_state.logged_in = True
163
  st.session_state.username = user["username"]
@@ -167,6 +165,7 @@ def login():
167
  st.error("Неверный токен!")
168
 
169
  def add_product():
 
170
  st.title("Добавление товара")
171
  product_name = st.text_input("Название товара").strip().lower()
172
  product_description = st.text_area("Описание товара")
@@ -194,10 +193,10 @@ def add_product():
194
  st.error("Пожалуйста, введите все обязательные данные.")
195
 
196
  def edit_products():
 
197
  st.title("Редактирование товара")
198
- with db_lock:
199
- data = load_db()
200
- products = [p for p in data["products"] if p["user_id"] == st.session_state.user_id]
201
  if products:
202
  product_names = [p["name"] for p in products]
203
  selected_product_name = st.selectbox("Выберите товар", product_names)
@@ -233,11 +232,11 @@ def edit_products():
233
  st.info("У вас пока нет добавленных товаров.")
234
 
235
  def add_to_cart():
 
236
  st.title("Отпуск товара")
237
  search_term = st.text_input("Поиск товара").strip().lower()
238
- with db_lock:
239
- data = load_db()
240
- products = [p for p in data["products"] if p["user_id"] == st.session_state.user_id and search_term in p["name"].lower()]
241
  if products:
242
  for product in products:
243
  cols = st.columns(4)
@@ -253,7 +252,6 @@ def add_to_cart():
253
  if quantity <= product["quantity_in_stock"]:
254
  with db_lock:
255
  data = load_db()
256
- # Обновляем корзину: если товар уже есть – увеличиваем количество, иначе добавляем новый
257
  cart = data["cart"]
258
  existing = next((item for item in cart if item["product_id"] == product["id"]), None)
259
  if existing:
@@ -261,7 +259,6 @@ def add_to_cart():
261
  else:
262
  new_cart_id = get_new_id(cart)
263
  cart.append({"id": new_cart_id, "product_id": product["id"], "quantity": quantity})
264
- # Уменьшаем остаток товара
265
  for p in data["products"]:
266
  if p["id"] == product["id"]:
267
  p["quantity_in_stock"] -= quantity
@@ -283,7 +280,6 @@ def add_to_cart():
283
  existing["quantity"] -= quantity
284
  else:
285
  cart.remove(existing)
286
- # Возвращаем товар на склад
287
  for p in data["products"]:
288
  if p["id"] == product["id"]:
289
  p["quantity_in_stock"] += quantity
@@ -294,14 +290,13 @@ def add_to_cart():
294
  st.error(f"Введите количество для удаления товара '{product['name']}'.")
295
 
296
  st.subheader("Состояние корзины")
297
- with db_lock:
298
- data = load_db()
299
- cart_items = []
300
- for item in data["cart"]:
301
- prod = next((p for p in data["products"] if p["id"] == item["product_id"]), None)
302
- if prod:
303
- total = item["quantity"] * prod["sale_price"]
304
- cart_items.append([prod["name"], item["quantity"], prod["sale_price"], total])
305
  if cart_items:
306
  df = pd.DataFrame(cart_items, columns=["Название", "Количество", "Цена за единицу", "Итого"])
307
  st.dataframe(df.style.format({"Цена за единицу": "{:.2f}", "Итого": "{:.2f}"}), use_container_width=True)
@@ -314,7 +309,7 @@ def add_to_cart():
314
  if sales_details:
315
  st.write("**Детали сделок:**")
316
  sale_details_df = pd.DataFrame(sales_details, columns=["ID товара", "Количество", "Сумма", "Дата и время"])
317
- st.dataframe(sale_details_df.style.format({"Сумма": "{:.2f}",
318
  "Дата и время": lambda x: pd.to_datetime(x).strftime('%d-%m-%Y %H:%M:%S')}),
319
  use_container_width=True)
320
  st.write(f"**Общая сумма сделки:** {total_amount:.2f}")
@@ -325,39 +320,40 @@ def add_to_cart():
325
  st.info("По вашему запросу товары не найдены.")
326
 
327
  def monthly_report():
 
328
  st.title("Отчет о продажах за месяц")
329
- with db_lock:
330
- data = load_db()
331
- start_date = datetime.now().replace(day=1)
332
- end_date = (datetime.now() + timedelta(days=31)).replace(day=1)
333
- sales = []
334
- # Для каждого проданного товара ищем информацию о продукте
335
- for sale in data["sales"]:
336
- sale_date = datetime.strptime(sale["sale_date"], "%Y-%m-%d %H:%M:%S")
337
- if start_date <= sale_date < end_date:
338
- prod = next((p for p in data["products"] if p["id"] == sale["product_id"]), None)
339
- if prod and prod["user_id"] == st.session_state.user_id:
340
- sales.append({
341
- "name": prod["name"],
342
- "quantity": sale["quantity"],
343
- "sale_price": prod["sale_price"],
344
- "total_sales": sale["total_amount"],
345
- "profit": sale["quantity"] * (prod["sale_price"] - prod["purchase_price"])
346
- })
347
- # Группировка по имени товара
348
- report = {}
349
- for s in sales:
350
- key = s["name"]
351
- if key not in report:
352
- report[key] = {"quantity": 0, "sale_price": s["sale_price"], "total_sales": 0, "profit": 0}
353
- report[key]["quantity"] += s["quantity"]
354
- report[key]["total_sales"] += s["total_sales"]
355
- report[key]["profit"] += s["profit"]
356
- report_data = []
357
- for name, values in report.items():
358
- report_data.append([name, values["quantity"], values["sale_price"], values["total_sales"], values["profit"]])
359
- total_sales = sum(item[3] for item in report_data)
360
- total_profit = sum(item[4] for item in report_data)
361
  if report_data:
362
  df = pd.DataFrame(report_data, columns=["Название", "Общее количество", "Отпускная цена", "Общие продажи", "Прибыль"])
363
  st.write(f"Отчет за {datetime.now().strftime('%B %Y')}")
@@ -366,17 +362,16 @@ def monthly_report():
366
  st.write(f"**Общая сумма прибыли**: {total_profit:.2f}")
367
 
368
  if st.button("Сделки"):
369
- with db_lock:
370
- data = load_db()
371
- sales_grouped = {}
372
- for sale in data["sales"]:
373
- prod = next((p for p in data["products"] if p["id"] == sale["product_id"]), None)
374
- if prod and prod["user_id"] == st.session_state.user_id:
375
- key = sale["sale_id"]
376
- if key not in sales_grouped:
377
- sales_grouped[key] = {"sale_date": sale["sale_date"], "total_amount": 0, "details": []}
378
- sales_grouped[key]["total_amount"] += sale["total_amount"]
379
- sales_grouped[key]["details"].append([prod["name"], sale["quantity"], prod["sale_price"], sale["sale_date"]])
380
  for key, group in sales_grouped.items():
381
  st.write(f"**Сделка ID:** {key} ({group['sale_date']}) - **Общая сумма:** {group['total_amount']:.2f}")
382
  df_sales = pd.DataFrame(group["details"], columns=["Название товара", "Количество", "Цена за единицу", "Дата и время"])
@@ -387,6 +382,7 @@ def monthly_report():
387
 
388
  # --- Главная функция приложения ---
389
  def main():
 
390
  st.warning("Попытка скачивания базы данных из Hugging Face...")
391
  download_success = download_db_from_hf()
392
  if download_success:
@@ -403,7 +399,7 @@ def main():
403
  st.error("Не удалось скачать JSON базу и локальной базы нет. Будет создана новая база.")
404
  with open(DB_FILENAME, "w", encoding="utf8") as f:
405
  json.dump({"users": [], "products": [], "cart": [], "sales": []}, f, ensure_ascii=False, indent=4)
406
-
407
  if 'logged_in' not in st.session_state:
408
  st.session_state.logged_in = False
409
 
@@ -432,8 +428,7 @@ def main():
432
  login()
433
 
434
  if __name__ == "__main__":
435
- # Ждем 15 секунд после инициализации, затем запускаем фоновый поток резервного копирования
436
- time.sleep(15)
437
  backup_thread = threading.Thread(target=periodic_backup, daemon=True)
438
  backup_thread.start()
439
  main()
 
5
  import random
6
  import string
7
  from datetime import datetime, timedelta
 
8
  import time
9
  import threading
10
  from huggingface_hub import HfApi, hf_hub_download
 
12
  # --- Настройки Hugging Face ---
13
  REPO_ID = "Testbase1/testsett" # Замените на ваш репозиторий
14
  DB_FILENAME = "auth_system.json" # JSON база данных
15
+ HF_TOKEN_WRITE = os.getenv("HF_TOKEN") # Токен для записи (загрузки)
16
+ HF_TOKEN_READ = os.getenv("HF_TOKEN_READ") # Токен для чтения (скачивания)
17
 
18
  # Глобальный блокировщик для доступа к JSON-файлу
19
  db_lock = threading.Lock()
20
 
21
+ # --- Кеширование функций для повышения производительности ---
22
+ @st.cache_data
23
  def load_db():
24
+ """Загружает базу данных из JSON-файла."""
25
  if not os.path.exists(DB_FILENAME):
26
  data = {"users": [], "products": [], "cart": [], "sales": []}
27
  save_db(data)
28
  return data
29
+ try:
30
+ with open(DB_FILENAME, "r", encoding="utf8") as f:
31
  data = json.load(f)
32
+ except json.JSONDecodeError:
33
+ data = {"users": [], "products": [], "cart": [], "sales": []}
34
+ save_db(data)
35
  return data
36
 
 
37
  def save_db(data):
38
+ """Сохраняет базу данных в JSON-файл."""
39
+ with db_lock:
40
+ with open(DB_FILENAME, "w", encoding="utf8") as f:
41
+ json.dump(data, f, ensure_ascii=False, indent=4)
42
 
 
43
  def upload_db_to_hf():
44
  """Загружает JSON-файл базы данных в репозиторий Hugging Face."""
45
  try:
 
49
  path_in_repo=DB_FILENAME,
50
  repo_id=REPO_ID,
51
  repo_type="dataset",
52
+ token=HF_TOKEN_WRITE,
53
+ commit_message=f"Автоматическое резервное копирование базы данных {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
54
  )
55
  print("Резервная копия JSON базы успешно загружена на Hugging Face.")
56
  except Exception as e:
57
  print("Ошибка при загрузке резервной копии:", e)
58
 
 
59
  def download_db_from_hf():
60
  """Скачивает JSON-файл базы данных из репозитория Hugging Face."""
61
  try:
 
73
  print("Ошибка при скачивании JSON базы:", e)
74
  return False
75
 
 
76
  def periodic_backup():
77
  """
78
+ Периодически, каждые 15 секунд, вызывается функция upload_db_to_hf().
79
  """
80
  while True:
81
  upload_db_to_hf()
 
83
 
84
  # --- Вспомогательные функции ---
85
  def generate_token():
86
+ """Генерирует случайный токен."""
87
  return ''.join(random.choices(string.ascii_letters + string.digits, k=13))
88
 
89
  def get_new_id(items):
90
+ """Возвращает новый ID для элемента."""
91
  return max([item.get("id", 0) for item in items], default=0) + 1
92
 
93
  # --- Функции для работы с продажами ---
94
  def record_sales():
95
+ """Записывает информацию о продажах, обновляет базу данных и очищает корзину."""
 
 
96
  with db_lock:
97
  data = load_db()
98
  cart_items = data["cart"]
 
111
  total_amount += sale_amount
112
  sales_details.append([product["id"], item["quantity"], sale_amount, now])
113
 
 
114
  new_sale_id = get_new_id(data["sales"])
115
  data["sales"].append({
116
  "id": new_sale_id,
 
121
  "sale_date": now
122
  })
123
 
 
124
  data["cart"] = []
125
  save_db(data)
126
 
127
  return sales_details, sale_id, total_amount
128
 
129
  # --- Страницы приложения ---
 
130
  def register():
131
+ """Страница регистрации."""
132
  st.title('Регистрация')
133
  username = st.text_input("Введите ваше имя пользователя")
134
  admin_password = st.text_input("Введите пароль администратора", type="password")
 
149
  st.error("Неверный пароль администратора!")
150
 
151
  def login():
152
+ """Страница авторизации."""
153
  st.title('Авторизация')
154
  token_input = st.text_input("Введите ваш токен")
155
 
156
  if st.button("Войти"):
157
+ data = load_db()
158
+ user = next((u for u in data["users"] if u["token"] == token_input), None)
 
159
  if user:
160
  st.session_state.logged_in = True
161
  st.session_state.username = user["username"]
 
165
  st.error("Неверный токен!")
166
 
167
  def add_product():
168
+ """Страница добавления товара."""
169
  st.title("Добавление товара")
170
  product_name = st.text_input("Название товара").strip().lower()
171
  product_description = st.text_area("Описание товара")
 
193
  st.error("Пожалуйста, введите все обязательные данные.")
194
 
195
  def edit_products():
196
+ """Страница редактирования товара."""
197
  st.title("Редактирование товара")
198
+ data = load_db()
199
+ products = [p for p in data["products"] if p["user_id"] == st.session_state.user_id]
 
200
  if products:
201
  product_names = [p["name"] for p in products]
202
  selected_product_name = st.selectbox("Выберите товар", product_names)
 
232
  st.info("У вас пока нет добавленных товаров.")
233
 
234
  def add_to_cart():
235
+ """Страница добавления товара в корзину."""
236
  st.title("Отпуск товара")
237
  search_term = st.text_input("Поиск товара").strip().lower()
238
+ data = load_db()
239
+ products = [p for p in data["products"] if p["user_id"] == st.session_state.user_id and search_term in p["name"].lower()]
 
240
  if products:
241
  for product in products:
242
  cols = st.columns(4)
 
252
  if quantity <= product["quantity_in_stock"]:
253
  with db_lock:
254
  data = load_db()
 
255
  cart = data["cart"]
256
  existing = next((item for item in cart if item["product_id"] == product["id"]), None)
257
  if existing:
 
259
  else:
260
  new_cart_id = get_new_id(cart)
261
  cart.append({"id": new_cart_id, "product_id": product["id"], "quantity": quantity})
 
262
  for p in data["products"]:
263
  if p["id"] == product["id"]:
264
  p["quantity_in_stock"] -= quantity
 
280
  existing["quantity"] -= quantity
281
  else:
282
  cart.remove(existing)
 
283
  for p in data["products"]:
284
  if p["id"] == product["id"]:
285
  p["quantity_in_stock"] += quantity
 
290
  st.error(f"Введите количество для удаления товара '{product['name']}'.")
291
 
292
  st.subheader("Состояние корзины")
293
+ data = load_db()
294
+ cart_items = []
295
+ for item in data["cart"]:
296
+ prod = next((p for p in data["products"] if p["id"] == item["product_id"]), None)
297
+ if prod:
298
+ total = item["quantity"] * prod["sale_price"]
299
+ cart_items.append([prod["name"], item["quantity"], prod["sale_price"], total])
 
300
  if cart_items:
301
  df = pd.DataFrame(cart_items, columns=["Название", "Количество", "Цена за единицу", "Итого"])
302
  st.dataframe(df.style.format({"Цена за единицу": "{:.2f}", "Итого": "{:.2f}"}), use_container_width=True)
 
309
  if sales_details:
310
  st.write("**Детали сделок:**")
311
  sale_details_df = pd.DataFrame(sales_details, columns=["ID товара", "Количество", "Сумма", "Дата и время"])
312
+ st.dataframe(sale_details_df.style.format({"Сумма": "{:.2f}",
313
  "Дата и время": lambda x: pd.to_datetime(x).strftime('%d-%m-%Y %H:%M:%S')}),
314
  use_container_width=True)
315
  st.write(f"**Общая сумма сделки:** {total_amount:.2f}")
 
320
  st.info("По вашему запросу товары не найдены.")
321
 
322
  def monthly_report():
323
+ """Страница отчета о продажах за месяц."""
324
  st.title("Отчет о продажах за месяц")
325
+ data = load_db()
326
+ start_date = datetime.now().replace(day=1)
327
+ end_date = (datetime.now() + timedelta(days=31)).replace(day=1)
328
+ sales = []
329
+
330
+ for sale in data["sales"]:
331
+ sale_date = datetime.strptime(sale["sale_date"], "%Y-%m-%d %H:%M:%S")
332
+ if start_date <= sale_date < end_date:
333
+ prod = next((p for p in data["products"] if p["id"] == sale["product_id"]), None)
334
+ if prod and prod["user_id"] == st.session_state.user_id:
335
+ sales.append({
336
+ "name": prod["name"],
337
+ "quantity": sale["quantity"],
338
+ "sale_price": prod["sale_price"],
339
+ "total_sales": sale["total_amount"],
340
+ "profit": sale["quantity"] * (prod["sale_price"] - prod["purchase_price"])
341
+ })
342
+
343
+ report = {}
344
+ for s in sales:
345
+ key = s["name"]
346
+ if key not in report:
347
+ report[key] = {"quantity": 0, "sale_price": s["sale_price"], "total_sales": 0, "profit": 0}
348
+ report[key]["quantity"] += s["quantity"]
349
+ report[key]["total_sales"] += s["total_sales"]
350
+ report[key]["profit"] += s["profit"]
351
+ report_data = []
352
+ for name, values in report.items():
353
+ report_data.append([name, values["quantity"], values["sale_price"], values["total_sales"], values["profit"]])
354
+ total_sales = sum(item[3] for item in report_data)
355
+ total_profit = sum(item[4] for item in report_data)
356
+
357
  if report_data:
358
  df = pd.DataFrame(report_data, columns=["Название", "Общее количество", "Отпускная цена", "Общие продажи", "Прибыль"])
359
  st.write(f"Отчет за {datetime.now().strftime('%B %Y')}")
 
362
  st.write(f"**Общая сумма прибыли**: {total_profit:.2f}")
363
 
364
  if st.button("Сделки"):
365
+ data = load_db()
366
+ sales_grouped = {}
367
+ for sale in data["sales"]:
368
+ prod = next((p for p in data["products"] if p["id"] == sale["product_id"]), None)
369
+ if prod and prod["user_id"] == st.session_state.user_id:
370
+ key = sale["sale_id"]
371
+ if key not in sales_grouped:
372
+ sales_grouped[key] = {"sale_date": sale["sale_date"], "total_amount": 0, "details": []}
373
+ sales_grouped[key]["total_amount"] += sale["total_amount"]
374
+ sales_grouped[key]["details"].append([prod["name"], sale["quantity"], prod["sale_price"], sale["sale_date"]])
 
375
  for key, group in sales_grouped.items():
376
  st.write(f"**Сделка ID:** {key} ({group['sale_date']}) - **Общая сумма:** {group['total_amount']:.2f}")
377
  df_sales = pd.DataFrame(group["details"], columns=["Название товара", "Количество", "Цена за единицу", "Дата и время"])
 
382
 
383
  # --- Главная функция приложения ---
384
  def main():
385
+ """Главная функция приложения."""
386
  st.warning("Попытка скачивания базы данных из Hugging Face...")
387
  download_success = download_db_from_hf()
388
  if download_success:
 
399
  st.error("Не удалось скачать JSON базу и локальной базы нет. Будет создана новая база.")
400
  with open(DB_FILENAME, "w", encoding="utf8") as f:
401
  json.dump({"users": [], "products": [], "cart": [], "sales": []}, f, ensure_ascii=False, indent=4)
402
+
403
  if 'logged_in' not in st.session_state:
404
  st.session_state.logged_in = False
405
 
 
428
  login()
429
 
430
  if __name__ == "__main__":
431
+ # Запускаем фоновый поток резервного копирования сразу
 
432
  backup_thread = threading.Thread(target=periodic_backup, daemon=True)
433
  backup_thread.start()
434
  main()