chore: sync uncommitted working tree changes before clone cleanup

This commit is contained in:
CRM Bot
2026-06-10 20:52:56 +00:00
parent 3f5b7df178
commit 394a6e935d
44 changed files with 246 additions and 220 deletions
+2 -2
View File
@@ -11,7 +11,7 @@ router layer passes `current_user.org_id`.
from __future__ import annotations
from typing import Any, Optional
from typing import Any
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
@@ -44,7 +44,7 @@ class OrgScopedQuery:
self,
skip: int = 0,
limit: int = 20,
order_by: Optional[Any] = None,
order_by: Any | None = None,
**filters: Any,
) -> list[Any]:
"""List records scoped to org, with optional filters and pagination."""
+5 -7
View File
@@ -3,7 +3,6 @@
from __future__ import annotations
from datetime import UTC, datetime
from typing import Optional
from sqlalchemy.ext.asyncio import AsyncSession
@@ -19,7 +18,6 @@ async def create_account(
db: AsyncSession, payload: AccountCreate, *, org_id: int, owner_id: int
) -> Account:
"""Create a new account in the given org."""
from app.services._base import OrgScopedQuery
account = Account(
org_id=org_id,
@@ -38,7 +36,7 @@ async def create_account(
async def get_account(
db: AsyncSession, account_id: int, *, org_id: int
) -> Optional[Account]:
) -> Account | None:
"""Fetch a single account by id (org-scoped, not soft-deleted)."""
from app.services._base import OrgScopedQuery
@@ -52,10 +50,10 @@ async def list_accounts(
org_id: int,
skip: int = 0,
limit: int = 20,
industry: Optional[str] = None,
size: Optional[str] = None,
owner_id: Optional[int] = None,
q: Optional[str] = None,
industry: str | None = None,
size: str | None = None,
owner_id: int | None = None,
q: str | None = None,
) -> list[Account]:
"""List accounts with filters and search."""
from app.services._base import OrgScopedQuery
+8 -9
View File
@@ -3,7 +3,6 @@
from __future__ import annotations
from datetime import UTC, datetime
from typing import Optional
from sqlalchemy.ext.asyncio import AsyncSession
@@ -24,9 +23,9 @@ async def _validate_parents(
db: AsyncSession,
*,
org_id: int,
account_id: Optional[int],
contact_id: Optional[int],
deal_id: Optional[int],
account_id: int | None,
contact_id: int | None,
deal_id: int | None,
) -> None:
"""Ensure at least one parent is set and each provided id exists in org."""
if account_id is None and contact_id is None and deal_id is None:
@@ -81,7 +80,7 @@ async def create_activity(
async def get_activity(
db: AsyncSession, activity_id: int, *, org_id: int
) -> Optional[Activity]:
) -> Activity | None:
"""Fetch a single activity by id."""
q = OrgScopedQuery(Activity, db, org_id=org_id)
return await q.get(activity_id)
@@ -93,10 +92,10 @@ async def list_activities(
org_id: int,
skip: int = 0,
limit: int = 20,
type: Optional[ActivityType] = None,
owner_id: Optional[int] = None,
overdue: Optional[bool] = None,
completed: Optional[bool] = None,
type: ActivityType | None = None,
owner_id: int | None = None,
overdue: bool | None = None,
completed: bool | None = None,
) -> list[Activity]:
"""List activities with optional filters."""
scoped = OrgScopedQuery(Activity, db, org_id=org_id)
+1 -3
View File
@@ -2,8 +2,6 @@
from __future__ import annotations
from typing import Optional
from sqlalchemy import select
from sqlalchemy.exc import IntegrityError
from sqlalchemy.ext.asyncio import AsyncSession
@@ -94,7 +92,7 @@ async def register_user(
async def authenticate_user(
db: AsyncSession, email: str, password: str
) -> Optional[tuple[User, str]]:
) -> tuple[User, str] | None:
"""Verify credentials and return (user, token) on success, None on failure.
The endpoint wraps this and returns 401 on None — keeping the
+4 -5
View File
@@ -3,7 +3,6 @@
from __future__ import annotations
from datetime import UTC, datetime
from typing import Optional
from sqlalchemy.exc import IntegrityError
from sqlalchemy.ext.asyncio import AsyncSession
@@ -64,7 +63,7 @@ async def create_contact(
async def get_contact(
db: AsyncSession, contact_id: int, *, org_id: int
) -> Optional[Contact]:
) -> Contact | None:
"""Fetch a single contact by id."""
q = OrgScopedQuery(Contact, db, org_id=org_id)
return await q.get(contact_id)
@@ -76,9 +75,9 @@ async def list_contacts(
org_id: int,
skip: int = 0,
limit: int = 20,
account_id: Optional[int] = None,
owner_id: Optional[int] = None,
q: Optional[str] = None,
account_id: int | None = None,
owner_id: int | None = None,
q: str | None = None,
) -> list[Contact]:
"""List contacts with filters and search."""
scoped = OrgScopedQuery(Contact, db, org_id=org_id)
+5 -6
View File
@@ -5,7 +5,6 @@ from __future__ import annotations
from collections import defaultdict
from datetime import UTC, datetime
from decimal import Decimal
from typing import Optional
from sqlalchemy.exc import IntegrityError
from sqlalchemy.ext.asyncio import AsyncSession
@@ -77,7 +76,7 @@ async def create_deal(
async def get_deal(
db: AsyncSession, deal_id: int, *, org_id: int
) -> Optional[Deal]:
) -> Deal | None:
"""Fetch a single deal by id."""
q = OrgScopedQuery(Deal, db, org_id=org_id)
return await q.get(deal_id)
@@ -89,9 +88,9 @@ async def list_deals(
org_id: int,
skip: int = 0,
limit: int = 20,
stage: Optional[str] = None,
owner_id: Optional[int] = None,
account_id: Optional[int] = None,
stage: str | None = None,
owner_id: int | None = None,
account_id: int | None = None,
) -> list[Deal]:
"""List deals with optional filters."""
scoped = OrgScopedQuery(Deal, db, org_id=org_id)
@@ -126,7 +125,7 @@ async def update_stage(
new_stage: DealStage,
*,
changed_by: int,
reason: Optional[str] = None,
reason: str | None = None,
) -> Deal:
"""Change a deal's stage and append a DealStageHistory record."""
from_stage_str = _stage_value(deal.stage)
+3 -4
View File
@@ -3,7 +3,6 @@
from __future__ import annotations
from datetime import UTC, datetime
from typing import Optional
from sqlalchemy.ext.asyncio import AsyncSession
@@ -86,7 +85,7 @@ async def create_note(
async def get_note(
db: AsyncSession, note_id: int, *, org_id: int
) -> Optional[Note]:
) -> Note | None:
"""Fetch a single note by id."""
q = OrgScopedQuery(Note, db, org_id=org_id)
return await q.get(note_id)
@@ -98,8 +97,8 @@ async def list_notes(
org_id: int,
skip: int = 0,
limit: int = 20,
parent_type: Optional[str] = None,
parent_id: Optional[int] = None,
parent_type: str | None = None,
parent_id: int | None = None,
) -> list[Note]:
"""List notes with optional parent filters."""
scoped = OrgScopedQuery(Note, db, org_id=org_id)
+1 -2
View File
@@ -3,7 +3,6 @@
from __future__ import annotations
from datetime import UTC, datetime
from typing import Optional
from sqlalchemy.exc import IntegrityError
from sqlalchemy.ext.asyncio import AsyncSession
@@ -75,7 +74,7 @@ async def list_tags(db: AsyncSession, *, org_id: int) -> list[Tag]:
return await scoped.list(skip=0, limit=1000, order_by=Tag.id)
async def get_tag(db: AsyncSession, tag_id: int, *, org_id: int) -> Optional[Tag]:
async def get_tag(db: AsyncSession, tag_id: int, *, org_id: int) -> Tag | None:
"""Fetch a single tag by id."""
return await OrgScopedQuery(Tag, db, org_id=org_id).get(tag_id)
+4 -5
View File
@@ -2,8 +2,7 @@
from __future__ import annotations
from datetime import datetime, UTC
from typing import Optional
from datetime import UTC, datetime
from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession
@@ -21,7 +20,7 @@ class EmailAlreadyTaken(Exception):
"""Raised when attempting to create/update a user with an existing email."""
async def get_user_by_id(db: AsyncSession, user_id: int) -> Optional[User]:
async def get_user_by_id(db: AsyncSession, user_id: int) -> User | None:
"""Fetch a user by ID (active only, soft-deleted excluded)."""
result = await db.execute(
select(User).where(User.id == user_id, User.deleted_at.is_(None))
@@ -30,8 +29,8 @@ async def get_user_by_id(db: AsyncSession, user_id: int) -> Optional[User]:
async def get_user_by_email(
db: AsyncSession, email: str, org_id: Optional[int] = None
) -> Optional[User]:
db: AsyncSession, email: str, org_id: int | None = None
) -> User | None:
"""Fetch a user by email, optionally scoped to an org."""
stmt = select(User).where(
User.email == email.lower(),