Corp/backend/tests/commerce/test_api.py
2026-08-17 18:38:22 +03:00

140 lines
4.6 KiB
Python

from decimal import Decimal
import pytest
from django.urls import reverse
from django.utils import timezone
from rest_framework import status
from commerce.models import Cost, Product, Sale, SaleLine, SourceSystem, StockSnapshot
pytestmark = pytest.mark.django_db
def test_commerce_api_requires_authentication(api_client):
response = api_client.get(reverse("api:v1:commerce:product-list"))
assert response.status_code == status.HTTP_401_UNAUTHORIZED
def test_employee_can_read_but_cannot_create_product(api_client, user_factory):
user = user_factory()
Product.objects.create(sku="FISHKA", name="Фишка")
api_client.force_authenticate(user=user)
list_response = api_client.get(reverse("api:v1:commerce:product-list"))
create_response = api_client.post(
reverse("api:v1:commerce:product-list"),
{"sku": "NEW", "name": "Новый товар", "kind": "product"},
format="json",
)
assert list_response.status_code == status.HTTP_200_OK
assert list_response.data["count"] == 1
assert create_response.status_code == status.HTTP_403_FORBIDDEN
def test_staff_can_create_product(api_client, user_factory):
user = user_factory(staff=True)
api_client.force_authenticate(user=user)
response = api_client.post(
reverse("api:v1:commerce:product-list"),
{"sku": "NEW", "name": "Новый товар", "kind": "product"},
format="json",
)
assert response.status_code == status.HTTP_201_CREATED
assert Product.objects.filter(sku="NEW").exists()
def test_staff_can_manage_normalized_commerce_facts(api_client, user_factory):
user = user_factory(staff=True)
source = SourceSystem.objects.create(code="moysklad", name="МойСклад")
product = Product.objects.create(sku="FISHKA", name="Фишка")
api_client.force_authenticate(user=user)
sale_response = api_client.post(
reverse("api:v1:commerce:sale-list"),
{
"source": source.pk,
"external_id": "order-1",
"occurred_at": timezone.now().isoformat(),
},
format="json",
)
assert sale_response.status_code == status.HTTP_201_CREATED
line_response = api_client.post(
reverse("api:v1:commerce:saleline-list"),
{
"sale": sale_response.data["id"],
"product": product.pk,
"external_id": "line-1",
"quantity": "2",
"gross_amount": "500.00",
"discount_amount": "50.00",
"cost_amount": "200.00",
},
format="json",
)
assert line_response.status_code == status.HTTP_201_CREATED
cost_response = api_client.post(
reverse("api:v1:commerce:cost-list"),
{
"source": source.pk,
"product": product.pk,
"cost_type": "commission",
"amount": "25.00",
"occurred_at": timezone.now().isoformat(),
},
format="json",
)
assert cost_response.status_code == status.HTTP_201_CREATED, cost_response.data
stock_response = api_client.post(
reverse("api:v1:commerce:stocksnapshot-list"),
{
"source": source.pk,
"product": product.pk,
"warehouse_external_id": "main",
"quantity": "10",
"reserved": "2",
"captured_at": timezone.now().isoformat(),
},
format="json",
)
assert stock_response.status_code == status.HTTP_201_CREATED
assert SaleLine.objects.filter(pk=line_response.data["id"]).exists()
assert Cost.objects.filter(pk=cost_response.data["id"]).exists()
assert StockSnapshot.objects.filter(pk=stock_response.data["id"]).exists()
def test_product_analytics_endpoint(api_client, user_factory):
user = user_factory()
source = SourceSystem.objects.create(code="insales", name="InSales")
product = Product.objects.create(sku="FISHKA", name="Фишка")
sale = Sale.objects.create(
source=source,
external_id="order-1",
occurred_at=timezone.now(),
channel="site",
)
SaleLine.objects.create(
sale=sale,
product=product,
external_id="line-1",
quantity=Decimal("1"),
gross_amount=Decimal("500"),
cost_amount=Decimal("200"),
)
api_client.force_authenticate(user=user)
response = api_client.get(
reverse("api:v1:commerce:product-analytics", args=[product.pk])
)
assert response.status_code == status.HTTP_200_OK
assert response.data["product_id"] == product.pk
assert response.data["monetary"][0]["net_revenue"] == Decimal("500")
assert response.data["monetary"][0]["contribution_margin"] == Decimal("300")