178 lines
5.9 KiB
Python
178 lines
5.9 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
from typing import Iterable
|
|
|
|
from app.db import Database
|
|
from app.models import (
|
|
ApplicationCreate,
|
|
ApplicationEventRecord,
|
|
ApplicationRecord,
|
|
ExternalSyncStatus,
|
|
utc_now_iso,
|
|
)
|
|
|
|
|
|
class ApplicationRepository:
|
|
def __init__(self, db: Database) -> None:
|
|
self._db = db
|
|
|
|
def create(self, payload: ApplicationCreate) -> ApplicationRecord:
|
|
now = utc_now_iso()
|
|
with self._db.connect() as conn:
|
|
cursor = conn.execute(
|
|
"""
|
|
INSERT INTO applications (
|
|
customer_id, customer_name, chat_id, category, description,
|
|
attachments_json, status, external_sync_status, source, created_at, updated_at
|
|
) VALUES (?, ?, ?, ?, ?, ?, 'new', ?, ?, ?, ?)
|
|
""",
|
|
(
|
|
payload.customer_id,
|
|
payload.customer_name,
|
|
payload.chat_id,
|
|
payload.category,
|
|
payload.description,
|
|
payload.attachments_json,
|
|
ExternalSyncStatus.NOT_SENT.value,
|
|
payload.source,
|
|
now,
|
|
now,
|
|
),
|
|
)
|
|
app_id = cursor.lastrowid
|
|
self.add_event(
|
|
conn=conn,
|
|
application_id=app_id,
|
|
event_type="created",
|
|
actor=payload.source,
|
|
details={"category": payload.category},
|
|
)
|
|
row = conn.execute("SELECT * FROM applications WHERE id = ?", (app_id,)).fetchone()
|
|
conn.commit()
|
|
return ApplicationRecord(**dict(row))
|
|
|
|
def get(self, application_id: int) -> ApplicationRecord | None:
|
|
with self._db.connect() as conn:
|
|
row = conn.execute("SELECT * FROM applications WHERE id = ?", (application_id,)).fetchone()
|
|
return ApplicationRecord(**dict(row)) if row else None
|
|
|
|
def list(
|
|
self,
|
|
status: str | None = None,
|
|
search: str | None = None,
|
|
limit: int = 100,
|
|
offset: int = 0,
|
|
) -> list[ApplicationRecord]:
|
|
clauses: list[str] = []
|
|
params: list[object] = []
|
|
if status:
|
|
clauses.append("status = ?")
|
|
params.append(status)
|
|
if search:
|
|
clauses.append("(customer_name LIKE ? OR description LIKE ? OR CAST(id AS TEXT) LIKE ?)")
|
|
like = f"%{search}%"
|
|
params.extend([like, like, like])
|
|
where_sql = f"WHERE {' AND '.join(clauses)}" if clauses else ""
|
|
params.extend([limit, offset])
|
|
sql = f"""
|
|
SELECT * FROM applications
|
|
{where_sql}
|
|
ORDER BY created_at DESC
|
|
LIMIT ? OFFSET ?
|
|
"""
|
|
with self._db.connect() as conn:
|
|
rows = conn.execute(sql, params).fetchall()
|
|
return [ApplicationRecord(**dict(row)) for row in rows]
|
|
|
|
def update_status(
|
|
self,
|
|
application_id: int,
|
|
status: str,
|
|
actor: str,
|
|
reason: str | None = None,
|
|
) -> ApplicationRecord | None:
|
|
now = utc_now_iso()
|
|
with self._db.connect() as conn:
|
|
exists = conn.execute("SELECT id FROM applications WHERE id = ?", (application_id,)).fetchone()
|
|
if not exists:
|
|
return None
|
|
conn.execute(
|
|
"UPDATE applications SET status = ?, updated_at = ? WHERE id = ?",
|
|
(status, now, application_id),
|
|
)
|
|
self.add_event(
|
|
conn=conn,
|
|
application_id=application_id,
|
|
event_type="status_changed",
|
|
actor=actor,
|
|
details={"status": status, "reason": reason},
|
|
)
|
|
row = conn.execute("SELECT * FROM applications WHERE id = ?", (application_id,)).fetchone()
|
|
conn.commit()
|
|
return ApplicationRecord(**dict(row))
|
|
|
|
def update_external_sync(
|
|
self,
|
|
application_id: int,
|
|
sync_status: str,
|
|
external_id: str | None,
|
|
external_error: str | None,
|
|
) -> None:
|
|
now = utc_now_iso()
|
|
with self._db.connect() as conn:
|
|
conn.execute(
|
|
"""
|
|
UPDATE applications
|
|
SET external_sync_status = ?, external_id = ?, external_error = ?, updated_at = ?
|
|
WHERE id = ?
|
|
""",
|
|
(sync_status, external_id, external_error, now, application_id),
|
|
)
|
|
self.add_event(
|
|
conn=conn,
|
|
application_id=application_id,
|
|
event_type="external_sync",
|
|
actor="external_api",
|
|
details={
|
|
"sync_status": sync_status,
|
|
"external_id": external_id,
|
|
"external_error": external_error,
|
|
},
|
|
)
|
|
conn.commit()
|
|
|
|
def get_events(self, application_id: int) -> list[ApplicationEventRecord]:
|
|
with self._db.connect() as conn:
|
|
rows = conn.execute(
|
|
"""
|
|
SELECT * FROM application_events
|
|
WHERE application_id = ?
|
|
ORDER BY created_at DESC
|
|
""",
|
|
(application_id,),
|
|
).fetchall()
|
|
return [ApplicationEventRecord(**dict(row)) for row in rows]
|
|
|
|
@staticmethod
|
|
def add_event(
|
|
conn,
|
|
application_id: int,
|
|
event_type: str,
|
|
actor: str,
|
|
details: dict[str, object] | None = None,
|
|
) -> None:
|
|
conn.execute(
|
|
"""
|
|
INSERT INTO application_events (application_id, event_type, actor, details_json, created_at)
|
|
VALUES (?, ?, ?, ?, ?)
|
|
""",
|
|
(
|
|
application_id,
|
|
event_type,
|
|
actor,
|
|
json.dumps(details or {}, ensure_ascii=False),
|
|
utc_now_iso(),
|
|
),
|
|
)
|
|
|