Files
chatballs/apps/backend/hub_platform/orders/serializers.py
T
AndreyandClaude Opus 4.8 5b831e6cae feat(orders): commerce orders domain + real sales metrics
New orders app (ADR-HUB-0018: catalog & sale recorded in Hub, execution
in product backends):
- Order + OrderItem models with payment/fulfillment status; items snapshot
  offer + price version so the record is stable. Migration included.
- Services (create_order, mark_paid, cancel_order, set_fulfillment),
  selectors, serializers, REST API (list/create/detail + status actions)
  under IsAuthenticated/IsOwner, org-scoped. Tests: 6 green.
- seed_orders management command for local demo (idempotent).

Wired real numbers into the spots that were "—":
- Sales overview: Продажи / Выручка / Конверсия + per-product sales/revenue.
- Clients list: orders count and purchases total per contact.
- Client detail: Заказы tab + summary (orders, purchases).

Full backend suite: 91/91.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 22:30:04 +03:00

33 lines
1.2 KiB
Python

from hub_platform.orders.models import Order, OrderItem
def order_item_payload(item: OrderItem) -> dict[str, object]:
return {
"id": item.id,
"offerCode": item.offer.code,
"title": item.title,
"quantity": item.quantity,
"amountMinor": item.amount_minor,
"currency": item.currency,
}
def order_payload(order: Order, *, with_items: bool = False) -> dict[str, object]:
payload = {
"id": order.id,
"code": order.code,
"contact": {"id": order.contact_id, "name": order.contact.name},
"conversationId": order.conversation_id,
"product": {"code": order.product.code, "name": order.product.name} if order.product_id else None,
"channel": order.channel.name if order.channel_id else None,
"paymentStatus": order.payment_status,
"fulfillmentStatus": order.fulfillment_status,
"amountMinor": order.amount_minor,
"currency": order.currency,
"createdAt": order.created_at.isoformat(),
"paidAt": order.paid_at.isoformat() if order.paid_at else None,
}
if with_items:
payload["items"] = [order_item_payload(item) for item in order.items.all()]
return payload