107 lines
3.9 KiB
Python
107 lines
3.9 KiB
Python
import uuid
|
|
|
|
from django.db import models
|
|
|
|
|
|
class SourceSystem(models.Model):
|
|
"""External system that supplies observations and business events."""
|
|
|
|
code = models.SlugField("Код", max_length=64, unique=True)
|
|
name = models.CharField("Название", max_length=128)
|
|
is_active = models.BooleanField("Активен", default=True)
|
|
metadata = models.JSONField("Настройки без секретов", default=dict, blank=True)
|
|
created_at = models.DateTimeField("Создано", auto_now_add=True)
|
|
updated_at = models.DateTimeField("Обновлено", auto_now=True)
|
|
|
|
class Meta:
|
|
verbose_name = "Источник данных"
|
|
verbose_name_plural = "Источники данных"
|
|
ordering = ["name"]
|
|
|
|
def __str__(self):
|
|
return self.name
|
|
|
|
|
|
class SourceRecord(models.Model):
|
|
"""Latest source payload retained with provenance for repeatable imports."""
|
|
|
|
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
|
source = models.ForeignKey(
|
|
SourceSystem,
|
|
on_delete=models.PROTECT,
|
|
related_name="records",
|
|
verbose_name="Источник",
|
|
)
|
|
entity_type = models.CharField("Тип объекта", max_length=64)
|
|
external_id = models.CharField("Внешний ID", max_length=255)
|
|
payload = models.JSONField("Исходные данные", default=dict)
|
|
payload_hash = models.CharField("Хеш данных", max_length=64, editable=False)
|
|
source_updated_at = models.DateTimeField(
|
|
"Изменено в источнике", null=True, blank=True
|
|
)
|
|
received_at = models.DateTimeField("Получено", auto_now=True)
|
|
created_at = models.DateTimeField("Создано", auto_now_add=True)
|
|
|
|
class Meta:
|
|
verbose_name = "Исходная запись"
|
|
verbose_name_plural = "Исходные записи"
|
|
constraints = [
|
|
models.UniqueConstraint(
|
|
fields=["source", "entity_type", "external_id"],
|
|
name="commerce_source_record_identity",
|
|
)
|
|
]
|
|
indexes = [
|
|
models.Index(
|
|
fields=["source", "entity_type", "source_updated_at"],
|
|
name="commerce_source_record_sync",
|
|
)
|
|
]
|
|
|
|
def __str__(self):
|
|
return f"{self.source.code}:{self.entity_type}:{self.external_id}"
|
|
|
|
|
|
class ProductBinding(models.Model):
|
|
"""Maps an external product/offer identifier to the canonical product."""
|
|
|
|
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
|
product = models.ForeignKey(
|
|
"commerce.Product",
|
|
on_delete=models.CASCADE,
|
|
related_name="bindings",
|
|
verbose_name="Товар",
|
|
)
|
|
source = models.ForeignKey(
|
|
SourceSystem,
|
|
on_delete=models.PROTECT,
|
|
related_name="product_bindings",
|
|
verbose_name="Источник",
|
|
)
|
|
external_id = models.CharField("Внешний ID", max_length=255)
|
|
external_sku = models.CharField(
|
|
"Артикул в источнике", max_length=128, blank=True, db_index=True
|
|
)
|
|
is_primary = models.BooleanField("Основная привязка", default=False)
|
|
created_at = models.DateTimeField("Создано", auto_now_add=True)
|
|
updated_at = models.DateTimeField("Обновлено", auto_now=True)
|
|
|
|
class Meta:
|
|
verbose_name = "Привязка товара"
|
|
verbose_name_plural = "Привязки товаров"
|
|
constraints = [
|
|
models.UniqueConstraint(
|
|
fields=["source", "external_id"],
|
|
name="commerce_binding_source_external",
|
|
)
|
|
]
|
|
indexes = [
|
|
models.Index(
|
|
fields=["source", "external_sku"],
|
|
name="commerce_binding_source_sku",
|
|
)
|
|
]
|
|
|
|
def __str__(self):
|
|
return f"{self.product.sku} ← {self.source.code}:{self.external_id}"
|