diff --git a/services/api-server/src/api_server/import_quality_models.py b/services/api-server/src/api_server/import_quality_models.py new file mode 100644 index 0000000..faed6bb --- /dev/null +++ b/services/api-server/src/api_server/import_quality_models.py @@ -0,0 +1,23 @@ +from __future__ import annotations + +from pydantic import BaseModel, Field + +from api_server.normalized_project_models import NormalizedProjectSummary + + +class ImportQualityCheck(BaseModel): + code: str + title: str + severity: str = "INFO" + passed: bool = True + message: str + value: int | str | None = None + + +class ImportQualityResponse(BaseModel): + project_id: str + status: str + score: int = 0 + ready_for_ide: bool = False + summary: NormalizedProjectSummary | None = None + checks: list[ImportQualityCheck] = Field(default_factory=list) diff --git a/services/api-server/src/api_server/import_quality_service.py b/services/api-server/src/api_server/import_quality_service.py new file mode 100644 index 0000000..c961e5d --- /dev/null +++ b/services/api-server/src/api_server/import_quality_service.py @@ -0,0 +1,111 @@ +from __future__ import annotations + +from api_server.import_quality_models import ImportQualityCheck, ImportQualityResponse +from api_server.normalized_project_models import NormalizedProjectSummary + + +def import_quality_response( + *, + project_id: str, + status: str, + summary: NormalizedProjectSummary | None, + indexed_status: str, +) -> ImportQualityResponse: + checks: list[ImportQualityCheck] = [] + checks.append( + _quality_check( + "normalized_project", + "NormalizedProject", + summary is not None, + "NormalizedProject сохранен" if summary is not None else "NormalizedProject не найден", + summary.project_id if summary is not None else None, + severity="ERROR", + ) + ) + if summary is not None: + checks.extend( + [ + _quality_check( + "metadata_groups", + "Metadata groups", + summary.group_count >= 5, + f"Найдено групп metadata: {summary.group_count}", + summary.group_count, + ), + _quality_check( + "metadata_objects", + "Metadata objects", + summary.object_count > 0, + f"Найдено объектов: {summary.object_count}", + summary.object_count, + severity="ERROR", + ), + _quality_check( + "forms", + "Forms", + summary.form_count > 0, + f"Найдено форм: {summary.form_count}", + summary.form_count, + ), + _quality_check( + "modules", + "Modules", + summary.module_count > 0, + f"Найдено модулей: {summary.module_count}", + summary.module_count, + ), + _quality_check( + "roles", + "Roles", + summary.role_count > 0, + f"Найдено ролей: {summary.role_count}", + summary.role_count, + ), + _quality_check( + "rights", + "Rights", + summary.rights_count > 0, + f"Найдено прав: {summary.rights_count}", + summary.rights_count, + ), + _quality_check( + "extensions", + "Extensions", + True, + f"Найдено расширений: {summary.extension_count}", + summary.extension_count, + severity="INFO", + ), + ] + ) + + weighted_checks = [check for check in checks if check.code != "extensions"] + passed = sum(1 for check in weighted_checks if check.passed) + score = round((passed / len(weighted_checks)) * 100) if weighted_checks else 0 + ready_for_ide = status == indexed_status and all(check.passed for check in checks if check.severity == "ERROR") + return ImportQualityResponse( + project_id=project_id, + status=status, + score=score, + ready_for_ide=ready_for_ide, + summary=summary, + checks=checks, + ) + + +def _quality_check( + code: str, + title: str, + passed: bool, + message: str, + value: int | str | None = None, + severity: str = "WARNING", +) -> ImportQualityCheck: + return ImportQualityCheck( + code=code, + title=title, + severity="INFO" if passed else severity, + passed=passed, + message=message, + value=value, + ) diff --git a/services/api-server/src/api_server/main.py b/services/api-server/src/api_server/main.py index 603d2ae..0408c87 100644 --- a/services/api-server/src/api_server/main.py +++ b/services/api-server/src/api_server/main.py @@ -94,6 +94,8 @@ from api_server.html5_setup_controller import ( html5_setup_source as _html5_setup_source, html5_setup_summary as _html5_setup_summary, ) +from api_server.import_quality_models import ImportQualityResponse +from api_server.import_quality_service import import_quality_response as _build_import_quality_response from api_server.metadata_tree_controller import ( metadata_tree as _metadata_tree, metadata_tree_children as _metadata_tree_children, @@ -967,24 +969,6 @@ class ImportSummary(BaseModel): sync_preview: ImportSyncPreview | None = None -class ImportQualityCheck(BaseModel): - code: str - title: str - severity: str = "INFO" - passed: bool = True - message: str - value: int | str | None = None - - -class ImportQualityResponse(BaseModel): - project_id: str - status: str - score: int = 0 - ready_for_ide: bool = False - summary: NormalizedProjectSummary | None = None - checks: list[ImportQualityCheck] = Field(default_factory=list) - - class ProjectSetupResponse(BaseModel): project_id: str status: ProjectSetupStatus @@ -7378,111 +7362,16 @@ def _load_normalized_project(project_id: str) -> NormalizedProject | None: return normalized -def _quality_check( - code: str, - title: str, - passed: bool, - message: str, - value: int | str | None = None, - severity: str = "WARNING", -) -> ImportQualityCheck: - return ImportQualityCheck( - code=code, - title=title, - severity="INFO" if passed else severity, - passed=passed, - message=message, - value=value, - ) - - def _import_quality_response(project_id: str) -> ImportQualityResponse: normalized = _load_normalized_project(project_id) summary = _normalized_project_summary(normalized) if normalized is not None else None state = _project_setup.get(project_id, {}) status = str(state.get("status", ProjectSetupStatus.NOT_CONFIGURED.value)) - checks: list[ImportQualityCheck] = [] - - checks.append( - _quality_check( - "normalized_project", - "NormalizedProject", - summary is not None, - "NormalizedProject сохранен" if summary is not None else "NormalizedProject не найден", - summary.project_id if summary is not None else None, - severity="ERROR", - ) - ) - if summary is not None: - checks.extend( - [ - _quality_check( - "metadata_groups", - "Metadata groups", - summary.group_count >= 5, - f"Найдено групп metadata: {summary.group_count}", - summary.group_count, - ), - _quality_check( - "metadata_objects", - "Metadata objects", - summary.object_count > 0, - f"Найдено объектов: {summary.object_count}", - summary.object_count, - severity="ERROR", - ), - _quality_check( - "forms", - "Forms", - summary.form_count > 0, - f"Найдено форм: {summary.form_count}", - summary.form_count, - ), - _quality_check( - "modules", - "Modules", - summary.module_count > 0, - f"Найдено модулей: {summary.module_count}", - summary.module_count, - ), - _quality_check( - "roles", - "Roles", - summary.role_count > 0, - f"Найдено ролей: {summary.role_count}", - summary.role_count, - ), - _quality_check( - "rights", - "Rights", - summary.rights_count > 0, - f"Найдено прав: {summary.rights_count}", - summary.rights_count, - ), - _quality_check( - "extensions", - "Extensions", - True, - f"Найдено расширений: {summary.extension_count}", - summary.extension_count, - severity="INFO", - ), - ] - ) - - weighted_checks = [check for check in checks if check.code != "extensions"] - passed = sum(1 for check in weighted_checks if check.passed) - score = round((passed / len(weighted_checks)) * 100) if weighted_checks else 0 - ready_for_ide = status == ProjectSetupStatus.INDEXED.value and all( - check.passed for check in checks if check.severity == "ERROR" - ) - return ImportQualityResponse( + return _build_import_quality_response( project_id=project_id, status=status, - score=score, - ready_for_ide=ready_for_ide, summary=summary, - checks=checks, + indexed_status=ProjectSetupStatus.INDEXED.value, )