we need in ScriptValidationRuleService.create_validation_rule extra step, we return from self.repo.create_validation_rule data without uuid, but to pass data to ReadSchema we need them, we need to get uuid for all this data.
so for script_id, field_id, firm_id and id in entity: <ScriptValidationRule(id=1, script_id=7, firm_id=3, field_id=6)> we need to get uuid! we need then for return to user correct ReadSchema with uuid 

code:

T = TypeVar("T", bound=BaseAlchemyModel)


class BaseRepo(Generic[T,]):
    def __init__(self, model: Type[T]):
        self.model = model

    async def create(self, db: AsyncSession, data: dict) -> T:
        try:
            new_item = self.model(**data)
            db.add(new_item)
            await db.commit()
            await db.refresh(new_item)
            return new_item
        except Exception as e:
            await db.rollback()
            logger.error(f"Transaction rolled back. Error: {e}", exc_info=True)
            raise

    async def get_by_id(
        self,
        db: AsyncSession,
        id: int,
        get_deleted: bool = False,
    ) -> T | None:
        if get_deleted:
            stmt = select(self.model).where(self.model.id == id)
        else:
            stmt = select(self.model).where(
                self.model.id == id,
                self.model.enabled.is_(True),
            )
        result = await db.execute(stmt)
        return result.scalars().first()

    async def get_by_uuid(
        self,
        db: AsyncSession,
        uuid: UUID,
        include_relations: bool = False,
        relation_model: Type[BaseAlchemyModel] | None = None,
    ) -> T | None:
        stmt = select(self.model).where(
            self.model.uuid == uuid,
            self.model.enabled.is_(True),  # TODO: check for soft_delete
        )
        if include_relations and relation_model:
            # Get all relationship attributes of the model
            relationships = [
                attr
                for attr in dir(self.model)
                if isinstance(
                    getattr(self.model, attr).property,
                    RelationshipProperty,
                )
                and getattr(self.model, attr).property.mapper.class_
                == relation_model
            ]

            # Add selectinload for each relationship
            for rel in relationships:
                stmt = stmt.options(selectinload(getattr(self.model, rel)))

        result = await db.execute(stmt)
        return result.scalars().first()

    async def get_id_by_uuid(
        self,
        db: AsyncSession,
        uuid: UUID,
        get_deleted: bool = False,
    ) -> int | None:
        """Retrieves the internal ID of an object based on its UUID."""
        if get_deleted:
            stmt = select(self.model.id).where(
                self.model.uuid == uuid,
            )
        else:
            stmt = select(self.model.id).where(
                self.model.uuid == uuid,
                self.model.enabled.is_(True),
            )
        result = await db.execute(stmt)
        return result.scalar()

    async def get_by_name(self, db: AsyncSession, name: str) -> T | None:
        stmt = select(self.model).where(
            self.model.name == name,
            self.model.enabled.is_(True),
        )
        result = await db.execute(stmt)
        return result.scalars().first()

    async def update(
        self,
        db: AsyncSession,
        id: int,
        data: dict,
    ) -> T | None:
        data["updated_at"] = get_current_datetime()
        stmt = (
            update(self.model)
            .where(
                self.model.id == id,
            )  # don't need self.model.enabled.is_(True), check in service
            .values(**data)
            .returning(self.model)
        )
        result = await db.execute(stmt)
        await db.commit()
        return result.scalars().first()

    async def soft_delete(self, db: AsyncSession, id: int) -> T | None:
        stmt = (
            update(self.model)
            .where(self.model.id == id, self.model.enabled.is_(True))
            .values(deleted_at=get_current_datetime(), enabled=False)
            .returning(self.model)
        )
        result = await db.execute(stmt)
        await db.commit()
        return result.scalars().first()

    async def hard_delete(self, db: AsyncSession, id: int) -> bool:
        stmt = delete(self.model).where(self.model.id == id)
        result = await db.execute(stmt)
        await db.commit()
        return result.rowcount > 0

    async def get_multi(
        self,
        db: AsyncSession,
        *,
        skip: int = 0,
        limit: int = 100,
        filter_by: dict[str, Any] | None = None,
        order_by: list[str] | None = None,
    ) -> Sequence[T]:
        try:
            stmt = select(self.model)
            if filter_by:
                filters = self._build_filters(filter_by)
                stmt = stmt.filter(filters)
            if order_by:
                for field in order_by:
                    if field.startswith("-"):
                        stmt = stmt.order_by(
                            getattr(self.model, field[1:]).desc(),
                        )
                    else:
                        stmt = stmt.order_by(getattr(self.model, field).asc())

            stmt = (
                stmt.where(self.model.enabled.is_(True))
                .offset(skip)
                .limit(limit)
            )
            result = await db.execute(stmt)
            return result.scalars().all()
        except Exception as e:
            logger.error(
                f"BaseRepo - get_multi skip: {skip}, limit: {limit}, filter_by: {filter_by}, order_by: {order_by} - e: {e}",
            )

    async def count(
        self,
        db: AsyncSession,
        filter_by: dict[str, Any] | None = None,
    ) -> int:
        stmt = select(func.count()).select_from(self.model)
        if filter_by:
            logger.debug(
                f"Filter Criteria: {filter_by}",
            )  # Log the filter criteria
            filters = self._build_filters(filter_by)  # Use _build_filters here
            stmt = stmt.filter(filters)
            logger.debug(
                f"SQL Query: {stmt.compile(compile_kwargs={'literal_binds': True})}",
            )  # Log the query
        result = await db.execute(stmt)
        count = result.scalar_one()  # Get the single count value directly
        logger.info(f"Number of items found: {count}")
        return count

    async def exists(self, db: AsyncSession, id: int) -> bool:
        stmt = (
            select(self.model)
            .where(self.model.enabled.is_(True))
            .filter(self.model.id == id)
        )
        result = await db.execute(stmt)
        return result.first() is not None

    async def get_or_create(
        self,
        db: AsyncSession,
        defaults: dict[str, Any] | None = None,
        **kwargs,
    ) -> Tuple[T, bool]:
        instance = await self.get_by_filters(db, **kwargs)
        if instance:
            return instance, False
        if defaults:
            kwargs.update(defaults)
        new_instance = await self.create(db, kwargs)
        return new_instance, True

    async def update_or_create(
        self,
        db: AsyncSession,
        defaults: dict[str, Any] | None = None,
        **kwargs,
    ) -> Tuple[T, bool]:
        # Use only the unique criteria for filtering in get_by_filters
        unique_criteria = {
            k: v
            for k, v in kwargs.items()
            if k in self.model.__table__.primary_key.columns
        }
        instance = await self.get_by_filters(db, **unique_criteria)
        if instance:
            update_data = defaults or {}
            # Prioritize kwargs updates
            for (
                key,
                value,
            ) in update_data.items():  # Update from defaults first
                setattr(instance, key, value)
            for (
                key,
                value,
            ) in (
                kwargs.items()
            ):  # Then update from kwargs (overrides defaults)
                if hasattr(instance, key):
                    setattr(instance, key, value)
            await db.commit()
            await db.refresh(instance)
            return instance, False
        if defaults:
            kwargs.update(defaults)
        new_instance = await self.create(db, kwargs)
        return new_instance, True

    async def get_by_filters(self, db: AsyncSession, **kwargs) -> T | None:
        logger.debug(f"get_by_filters called with kwargs: {kwargs}")
        stmt = select(self.model).where(self.model.enabled.is_(True))
        for key, value in kwargs.items():
            logger.debug(f"Adding filter for {key}={value}")
            # Handle enum values:
            if isinstance(value, Enum):
                stmt = stmt.filter(getattr(self.model, key) == value.value)
            else:
                stmt = stmt.filter(getattr(self.model, key) == value)
        logger.debug(
            f"Generated SQL query: {stmt.compile(compile_kwargs={'literal_binds': True})}",
        )
        result = await db.execute(stmt)
        instance = result.scalars().first()

        if instance:
            logger.debug(f"Found instance with ID: {instance.id}")
        else:
            logger.warning(f"No instance found matching filters: {kwargs}")

        return instance

    def _build_filters(self, filter_by: dict) -> BinaryExpression:
        if "or_" in filter_by:
            return or_(*[self._build_filters(f) for f in filter_by["or_"]])
        elif "and_" in filter_by:
            return and_(*[self._build_filters(f) for f in filter_by["and_"]])
        else:
            filters = []
            for key, value in filter_by.items():
                if isinstance(value, dict):
                    op = list(value.keys())[0]
                    if op == "like":
                        filters.append(
                            getattr(self.model, key).like(value[op]),
                        )
                    elif op == "lt":
                        if isinstance(getattr(self.model, key).type, Date):
                            filters.append(
                                func.date(getattr(self.model, key))
                                < func.date(bindparam(key, value[op])),
                            )
                        else:
                            filters.append(
                                getattr(self.model, key)
                                < bindparam(key, value[op]),
                            )
                    # Add more operators as needed
                else:
                    filters.append(getattr(self.model, key) == value)
            return and_(*filters)