Files
k1nq d582f15681 feat: add tests for import polling, login page, money utilities, and query keys
- Implemented tests for import polling functionality, ensuring correct behavior for active and terminal import statuses.
- Created tests for the login page, validating user interactions and error handling.
- Added unit tests for money utility functions, covering parsing, formatting, and summation of monetary values.
- Developed tests for query keys, ensuring proper scoping and invalidation roots.

chore: setup testing environment and configuration

- Added setup file for testing with Vitest and Testing Library.
- Configured TypeScript and Vite for the frontend project.
- Created Docker and Nginx configurations for local development and production environments.
- Established a PostgreSQL initialization script for setting up application roles.

docs: add README and environment configuration for infra

- Included README for the infra directory, detailing local development setup and service descriptions.
- Created an example environment configuration file for local development with placeholders for sensitive information.
2026-09-14 09:26:33 +05:00

49 lines
1.5 KiB
Python

from typing import Any
class AppError(Exception):
"""Domain error rendered as a machine-readable JSON error payload."""
status_code: int = 400
code: str = "APP_ERROR"
def __init__(
self,
message: str,
*,
code: str | None = None,
status_code: int | None = None,
details: Any = None,
) -> None:
super().__init__(message)
self.message = message
if code is not None:
self.code = code
if status_code is not None:
self.status_code = status_code
self.details = details
def bad_request(code: str, message: str, details: Any = None) -> AppError:
return AppError(message, code=code, status_code=400, details=details)
def unauthorized(code: str, message: str, details: Any = None) -> AppError:
return AppError(message, code=code, status_code=401, details=details)
def forbidden(code: str, message: str, details: Any = None) -> AppError:
return AppError(message, code=code, status_code=403, details=details)
def not_found(code: str, message: str, details: Any = None) -> AppError:
return AppError(message, code=code, status_code=404, details=details)
def conflict(code: str, message: str, details: Any = None) -> AppError:
return AppError(message, code=code, status_code=409, details=details)
def unprocessable(code: str, message: str, details: Any = None) -> AppError:
return AppError(message, code=code, status_code=422, details=details)