diff --git a/site/app.py b/site/app.py index 18c4d64..4547ec6 100644 --- a/site/app.py +++ b/site/app.py @@ -18,8 +18,30 @@ from api import api_bp load_dotenv() -def _save_file_to_db(filename, file_bytes, mime, contract_id): - """Сохранить один файл в БД: documents + supplements. Возвращает doc_id или None.""" +def _save_file_to_db(filename, file_bytes, mime, contract_id, conn=None): + """Сохранить файл в БД. Если conn передан — использовать его, иначе свои подключения.""" + if conn: + cur = conn.cursor() + cur.execute( + "INSERT INTO documents (filename, mime_type, original_bytes, status) VALUES (%s,%s,%s,'uploaded')", + (filename, mime, file_bytes), + ) + cur.execute( + "SELECT id FROM documents WHERE filename=%s AND status='uploaded' ORDER BY created_at DESC LIMIT 1", + (filename,), + ) + row = cur.fetchone() + doc_id = row[0] if row else None + if doc_id: + cur.execute( + "INSERT INTO supplements (contract_id, document_id, type) VALUES (%s,%s,'initial')", + (str(contract_id), str(doc_id)), + ) + conn.commit() + cur.close() + return doc_id + + # Без соединения — каждое действие со своим (старый режим) db.execute( "INSERT INTO documents (filename, mime_type, original_bytes, status) VALUES (%s,%s,%s,'uploaded')", (filename, mime, file_bytes), @@ -129,43 +151,58 @@ class ContractsApp: if received == total_chunks: try: + # ОДНО соединение на всю сборку + сохранение + conn, err = db.connect() + if err: + return jsonify({"error": f"БД: {err}"}), 500 + cur = conn.cursor() + # Собрать все чанки по порядку - rows_res, _ = db.query( + cur.execute( "SELECT chunk_data FROM chunks WHERE upload_id=%s ORDER BY chunk_index", (upload_id,), ) - file_bytes = b"".join(r[0] for r in rows_res["rows"]) + file_bytes = b"".join(r[0] for r in cur.fetchall()) - # Получить метаданные из первой записи - meta, _ = db.query_one( + # Метаданные + cur.execute( "SELECT filename, mime, cid FROM chunks WHERE upload_id=%s LIMIT 1", (upload_id,), ) - fname = meta["filename"] if meta else filename - fmime = meta["mime"] if meta else mime - fcid = meta["cid"] if meta else cid + meta = cur.fetchone() + fname = meta[0] if meta else filename + fmime = meta[1] if meta else mime + fcid = meta[2] if meta else cid - # Создать контракт если нет + # Контракт если нет if fcid: contract_id = fcid else: - conn, err = db.connect() - if err: - return jsonify({"error": f"БД: {err}"}), 500 - cur = conn.cursor() cur.execute( "INSERT INTO contracts (number, client) VALUES (%s, %s) RETURNING id", ("б/н " + __import__("datetime").datetime.now().strftime("%Y%m%d-%H%M"), ""), ) contract_id = cur.fetchone()[0] - conn.commit() + + conn.commit() + + # Сохранить файл через то же соединение + doc_id = _save_file_to_db(fname, file_bytes, fmime, str(contract_id), conn=conn) + if not doc_id: + conn.rollback() cur.close() conn.close() - - doc_id = _save_file_to_db(fname, file_bytes, fmime, str(contract_id)) - if not doc_id: return jsonify({"error": "Не удалось сохранить файл в БД"}), 500 + + cur.close() + conn.close() except Exception as e: + try: conn.rollback() + except: pass + try: cur.close() + except: pass + try: conn.close() + except: pass return jsonify({"error": f"Сборка: {e}"}), 500 finally: db.execute("DELETE FROM chunks WHERE upload_id=%s", (upload_id,)) diff --git a/site/templates/upload.html b/site/templates/upload.html index f8b0e79..3155703 100644 --- a/site/templates/upload.html +++ b/site/templates/upload.html @@ -59,7 +59,7 @@