Add API for AI Agent

This commit is contained in:
2026-05-15 12:35:23 +02:00
parent 8caba9b85b
commit e4fa941fd6
7 changed files with 236 additions and 1 deletions
+93
View File
@@ -0,0 +1,93 @@
from typing import Optional
from ninja import Router, Schema
from django.db.models import Count
from django.shortcuts import get_object_or_404
from .models import Category, Product
router = Router()
class CategoryOut(Schema):
id: int
name: str
product_count: int
class ImageInfo(Schema):
url: str
alt: str
class ProductListOut(Schema):
id: int
name: str
sku: Optional[str] = None
briefdesc: str
price: float
price_with_vat: float
stock: int
category_id: int
category_name: str
primary_image: Optional[ImageInfo] = None
average_rating: float
reviews_count: int
class ProductDetailOut(ProductListOut):
description: str
secondary_images: list[ImageInfo]
def _image_info(img, request):
if not img:
return None
return ImageInfo(
url=request.build_absolute_uri(img.image.url),
alt=img.alt or img.name,
)
def _product_to_list_out(p, request):
return ProductListOut(
id=p.id,
name=p.name,
sku=p.sku,
briefdesc=p.briefdesc,
price=p.price,
price_with_vat=p.get_price_with_vat(),
stock=p.stock,
category_id=p.category_id,
category_name=p.category.name,
primary_image=_image_info(p.primary_image, request),
average_rating=p.get_average_rating(),
reviews_count=p.get_reviews_count(),
)
def _product_to_detail_out(p, request):
base = _product_to_list_out(p, request)
data = base.dict()
data["description"] = p.description
data["secondary_images"] = [
_image_info(img, request) for img in p.secondary_images.all()
]
return ProductDetailOut(**data)
@router.get("/categorias", response=list[CategoryOut])
def listar_categorias(request):
qs = Category.objects.annotate(product_count=Count("product"))
return [
CategoryOut(id=c.id, name=c.name, product_count=c.product_count)
for c in qs
]
@router.get("/productos", response=list[ProductListOut])
def listar_productos(request, categoria_id: Optional[int] = None):
qs = Product.objects.select_related("category", "primary_image")
if categoria_id:
qs = qs.filter(category_id=categoria_id)
return [_product_to_list_out(p, request) for p in qs]
@router.get("/productos/{product_id}", response=ProductDetailOut)
def detalle_producto(request, product_id: int):
p = get_object_or_404(
Product.objects.select_related("category", "primary_image")
.prefetch_related("secondary_images"),
id=product_id,
)
return _product_to_detail_out(p, request)
+20
View File
@@ -318,3 +318,23 @@ p.price {
overflow-wrap: break-word;
word-wrap: break-word;
}
:root {
--chat--color--primary: #513CB0;
--chat--color--primary-shade-50: #3f2a8f;
--chat--color--primary--shade-100: #361DA7;
--chat--color--secondary: #513CB0;
--chat--color-secondary-shade-50: #3f2a8f;
--chat--color--typing: #513CB0;
--chat--color-dark: #101330;
--chat--window--border-radius: 12px;
--chat--toggle--background: #513CB0;
--chat--toggle--hover--background: #3f2a8f;
--chat--toggle--active--background: #361DA7;
--chat--message--bot--background: #f0f0f0;
--chat--message--user--background: #513CB0;
--chat--header--background: #513CB0;
--chat--input--send--button--color: #513CB0;
--chat--input--send--button--color-hover: #3f2a8f;
--chat--close--button--color-hover: #FC3F44;
}
+22
View File
@@ -344,5 +344,27 @@
});
</script>
{% endcache %}
<link href="https://cdn.jsdelivr.net/npm/@n8n/chat/dist/style.css" rel="stylesheet" />
<script type="module">
import { createChat } from 'https://cdn.jsdelivr.net/npm/@n8n/chat/dist/chat.bundle.es.js';
createChat({
webhookUrl: 'https://n8n.elordenador.org/webhook/0e2cbe42-39d2-4e86-be62-c12542e246d4/chat',
initialMessages: [
'¡Hola! 👋',
'Soy el asistente virtual de Comercialmeria. ¿En qué puedo ayudarte?'
],
i18n: {
en: {
title: 'Chat de Soporte',
subtitle: 'Estamos aquí para ayudarte 24/7.',
footer: '',
getStarted: 'Nueva conversación',
inputPlaceholder: 'Escribe tu mensaje...',
},
},
});
</script>
</body>
</html>