"""Синхронизация локальной очереди заказов с CRM и работа с ней.""" from __future__ import annotations from datetime import UTC, datetime from decimal import Decimal from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.db.models.order import Order from app.services.crm.client import CrmClient _CRM_STATUS = "APPROVED" def _to_kopecks(amount: str) -> int: return int((Decimal(amount) * 100).to_integral_value()) def _parse_crm_datetime(value: str) -> datetime: return datetime.strptime(value, "%Y-%m-%d %H:%M:%S") async def sync_orders_from_crm(session: AsyncSession, crm: CrmClient) -> None: """Подтягивает заказы CRM (статус APPROVED) в локальную таблицу. Уже скрытые (`is_deleted`) заказы не восстанавливаются и не перезаписываются — иначе кнопка «Удалить» переставала бы работать при следующем открытии дашборда, т.к. CRM продолжает возвращать эти заказы как есть. """ crm_orders = await crm.get_orders(status=_CRM_STATUS) if not crm_orders: return existing = await session.scalars( select(Order).where(Order.id.in_(order.id for order in crm_orders)) ) existing_by_id = {order.id: order for order in existing} for crm_order in crm_orders: local = existing_by_id.get(crm_order.id) if local is not None: if local.is_deleted: continue else: local = Order(id=crm_order.id) session.add(local) local.create_date_time = _parse_crm_datetime(crm_order.create_date_time) local.recipient_name = crm_order.recipient_name local.recipient_phone = crm_order.recipient_phone local.recipient_email = crm_order.recipient_email local.waybill_number = crm_order.waybill_number local.notes = crm_order.notes local.total_amount_kopecks = _to_kopecks(crm_order.total.amount) local.goods = [good.model_dump(by_alias=False) for good in crm_order.goods] await session.commit() async def list_orders(session: AsyncSession, *, has_receipt: bool) -> list[Order]: receipt_filter = ( Order.receipt_created_at.is_not(None) if has_receipt else Order.receipt_created_at.is_(None) ) result = await session.scalars( select(Order) .where(Order.is_deleted.is_(False)) .where(receipt_filter) .order_by(Order.create_date_time.desc()) ) return list(result) async def delete_order(session: AsyncSession, order_id: str) -> Order | None: order = await session.get(Order, order_id) if order is None or order.is_deleted: return None order.is_deleted = True order.deleted_at = datetime.now(UTC) return order