SFM/main.py
2026-09-14 17:25:05 +03:00

188 lines
7.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import streamlit as st
from dotenv import load_dotenv
from app.app_config import (
ACCESS_SUPPORT_CONTACT,
SFM_SMB_BASE_PATH,
resolve_opencloud_access_token,
resolve_user_id,
)
from app.auth.service import AuthService, clear_session
from app.opencloud_access import OpenCloudDriveResolutionError, resolve_personal_drive
from app.path_settings import (
close_path_editor,
ensure_user_path_state,
get_resolved_input_dir,
open_path_editor,
render_path_editor,
)
from app.path_store import set_user_path
from app.pipeline.config import join_path
from app.pipeline.service import BatchResult, run_batch
from app.samba_access import check_access_and_list_files, diagnose_smb_access
def main() -> None:
load_dotenv()
st.set_page_config(page_title="СФМ", page_icon=":lock:", layout="wide")
st.title("СФМ")
if not AuthService().run():
return
_, center_col, _ = st.columns([1, 2, 1])
with center_col:
user_id = resolve_user_id()
current_input_dir = ensure_user_path_state(user_id)
st.subheader("Подключение к сетевому диску")
samba_user = st.text_input(
"Логин SAMBA",
placeholder="Ivanov-IIv",
help="Логин учетной записи для доступа к SMB-шаре.",
)
samba_password = st.text_input(
"Пароль SAMBA",
type="password",
placeholder="12345abc",
help="Пароль учетной записи для доступа к SMB-шаре.",
)
if st.button("Изменить путь", use_container_width=True):
open_path_editor(current_input_dir)
edited_path = render_path_editor()
if edited_path is not None:
edited_input_dir = join_path(edited_path, "Input")
ok, message, _ = check_access_and_list_files(
smb_base_path=SFM_SMB_BASE_PATH,
input_dir=edited_input_dir,
samba_user=samba_user,
samba_password=samba_password,
)
if ok:
set_user_path(user_id, edited_path)
close_path_editor()
st.success("Путь сохранен.")
st.rerun()
else:
st.error(_format_access_error(message))
resolved_input_dir = get_resolved_input_dir(user_id)
processing_input_dir = join_path(resolved_input_dir, "Input")
st.caption(f"Текущий путь: `{resolved_input_dir}`")
st.caption(f"Папка чтения XML: `{processing_input_dir}`")
if st.button(
"Запустить обработку xml в excel",
type="primary",
use_container_width=True,
):
with st.spinner("Выполняется обработка..."):
launcher_name = samba_user.strip() or user_id
access_token = resolve_opencloud_access_token()
opencloud_space_id = None
opencloud_error = None
if access_token:
try:
opencloud_space_id = resolve_personal_drive(access_token)["id"]
except OpenCloudDriveResolutionError as exc:
opencloud_error = str(exc)
if opencloud_error:
batch_result = BatchResult(
status="error",
processed=0,
partial=0,
errors=1,
report_path="",
protocol_path="",
log_path="",
messages=[opencloud_error],
)
else:
batch_result = run_batch(
smb_base_path=SFM_SMB_BASE_PATH,
input_dir=processing_input_dir,
samba_user=samba_user,
samba_password=samba_password,
launcher=launcher_name,
opencloud_space_id=opencloud_space_id,
opencloud_access_token=access_token,
artifacts_dir=resolved_input_dir,
)
if batch_result.status == "success":
st.success("Обработка завершена успешно.")
elif batch_result.status == "partial":
st.warning("Обработка завершена частично.")
else:
st.error("Обработка завершена с ошибками.")
st.write(
{
"processed": batch_result.processed,
"partial": batch_result.partial,
"errors": batch_result.errors,
"report_path": batch_result.report_path,
"protocol_path": batch_result.protocol_path,
"log_path": batch_result.log_path,
}
)
if batch_result.messages:
st.caption("Последние сообщения обработки:")
for message in batch_result.messages:
st.write(f"- {message}")
if st.button("Проверить доступ к папке", use_container_width=True):
ok, message, files = check_access_and_list_files(
smb_base_path=SFM_SMB_BASE_PATH,
input_dir=processing_input_dir,
samba_user=samba_user,
samba_password=samba_password,
)
if not ok:
st.error(_format_access_error(message))
else:
if files:
st.success(f"Папка доступна. Найдено файлов: {len(files)}")
st.write(files)
else:
st.info("Папка доступна, но пуста.")
if st.button("Диагностика SMB", use_container_width=True):
with st.spinner("Выполняется диагностика SMB..."):
diagnostic = diagnose_smb_access(
smb_base_path=SFM_SMB_BASE_PATH,
parent_dir=resolved_input_dir,
samba_user=samba_user,
samba_password=samba_password,
)
st.caption(f"Тестовая папка: `{diagnostic.test_path}`")
for step in diagnostic.steps:
message = f"{step.stage}: {step.details}"
if step.status == "ok":
st.success(message)
elif step.status == "error":
st.error(message)
else:
st.info(message)
if st.button("Выйти", type="secondary"):
clear_session()
st.rerun()
def _format_access_error(message: str) -> str:
lowered = (message or "").lower()
user_input_keywords = (
"логин",
"парол",
"status_logon_failure",
"logon",
"authentication",
"auth",
)
if any(keyword in lowered for keyword in user_input_keywords):
return message
return f"{message} Обратитесь к {ACCESS_SUPPORT_CONTACT}."
if __name__ == "__main__":
main()