Назад в блог
Кейс

Narciss CRM

Production-grade operating platform для цветочного ритейла

Django, PostgreSQL, Celery, Docker, CRM, ERP, POS и multichannel messaging

Техническая продуктовая статья на основе live production code и runtime state
Flower retail CRM, ERP и production system architecture
ТемаNarciss CRM
ФокусConnected Retail Operations
СтатусLIVE / PRODUCTION
NARCISS_PRODUCTION_RUNTIME.LOG
$ docker compose -f docker/docker-compose.yml ps
SERVICE         STATUS                 PORTS
web             Up 3 hours             8000/tcp
db              Up 2 weeks (healthy)   5432/tcp
redis           Up 2 weeks             6379/tcp
celery_worker   Up 3 hours             8000/tcp
celery_beat     Up 3 hours             8000/tcp
telegram-bot    Up 3 hours             8000/tcp
nginx           Up 3 hours             80/tcp, 443/tcp

$ docker compose -f docker/docker-compose.yml exec web python manage.py check
System check identified no issues (0 silenced).
Разбор

Обзор

Живая production CRM и ERP-платформа

Narciss CRM - не просто клиентская база и не универсальный трекер заказов. Это production CRM и операционная платформа для цветочного бизнеса, построенная вокруг ежедневной работы продаж, флористов, курьеров, менеджеров, клиентов, онлайн-заказов, склада, мессенджеров и внешних интеграций.

Система работает как Django 5 application с PostgreSQL, Redis, Celery, Gunicorn и Nginx. Операторский интерфейс в основном server-rendered, с partial updates, локальной интерактивностью и точечным JavaScript там, где операционным экранам нужен richer behavior.

Важная часть - масштаб. Codebase объединяет CRM, order lifecycle, stock control, bouquet recipes, supplier documents, delivery dispatching, POS surfaces, storefront flows, analytics, marketing, multichannel messaging, API access и integration control planes. На практике Narciss CRM ближе к business operating system для flower retail, чем к простому CRM-модулю.

Product model

Цикл customer, order, stock and delivery

Базовая модель построена вокруг flower retail operation, где коммуникация с клиентом, приём заказа, сборка, резерв склада, доставка и оплата связаны в один контур.

Customers хранят identity data, каналы связи, preferences, памятные даты, bonus balance, ответственных сотрудников и связи с Telegram, VK, MAX, Avito и другими channel-shaped sources.

Orders - главная бизнес-ось. Заказ может прийти из CRM, storefront, messenger, external API или integration intake. Он содержит status, pipeline stage, customer, store, recipient, delivery details, items, custom bouquet data, substitutions, responsible users, florist assignment, courier assignment, payment state и public token.

  • Customer identity влияет на messenger, intake и order history.
  • Orders могут содержать bouquet recipes, variants, custom components и substitutions.
  • Delivery имеет отдельную operational lane с зонами, курьерскими сменами и audited status logs.
  • Store, legal entity и retail point models переводят систему к multi-store operation.

Main workspace

Плотные operator screens вместо marketing pages

Narciss CRM организован вокруг плотных рабочих экранов оператора. Списки, фильтры, частичные обновления, модальные действия и контекстные панели находятся рядом, чтобы оператор мог работать без потери состояния.

Florist flow особенно специфичен для бизнеса. Assembly не трактуется как abstract manufacturing module. Он моделируется через order status и pipeline stages: paid order, transferred to florists, taken into assembly, assembled and ready for courier search, then courier assignment and delivery.

  • customers and customer detail workspaces
  • order list, board, calendar and intake screens
  • florist tablet screens for assembly work
  • delivery management and courier-facing flows
  • inventory procurement, warehouse, sales and settlement screens
  • analytics, P&L, marketing, messenger, integrations and POS surfaces

Orders and fulfillment

Бизнес-ось, где сходятся продуктовые домены

Заказ может быть создан вручную, через showcase checkout, из messenger conversation, из intake data или через external API. Он может включать bouquet recipes, variants, custom bouquet items, substitutions и delivery metadata.

Pipeline system настраивается через order pipeline stages и loss reasons. Это даёт бизнесу возможность формировать собственный sales and fulfillment process, сохраняя canonical order states для кода, отчётности и downstream services.

Assembly metadata из bouquet recipes, например estimated assembly minutes и complexity, может переноситься в order items. Это даёт платформе путь к workload planning и florist incentive calculation.

Inventory and recipe system

Глубина домена для perishable retail

Inventory - один из сильных сигналов, что Narciss CRM является domain product. Он отслеживает категории, units, products, variants, barcode ownership, locations, batches, movements, reservations, prices и daily snapshots.

Bouquet recipes являются first-class. Recipe может содержать components, packaging, labor cost, margin, variants, assembly time, complexity, dimensions, photos, external identifiers и publication flags.

Storefront publication связана с inventory. Bouquet recipes могут быть publication-requested и фактически published only when required components are available. Это важно в flower retail, где free stock быстро меняется, а online availability должна следовать operational reality.

  • supplier orders, bills, payments and returns
  • incoming invoices, allocations and stock receipts
  • markdown acts, inventory acts, regrade acts and transfer acts
  • internal demands, closed periods, import runs and document events

Multichannel messenger

Messaging как часть fulfillment, а не отдельный inbox

Messaging layer исторически назван вокруг WhatsApp, но production code показывает multichannel conversation system. Shared conversation model поддерживает Wappi/WhatsApp, Telegram, Telegram bot, MAX, MAX bot, VK, Avito, HH, SMS и webchat-shaped channels.

Messenger связан с customers, stores, orders и tasks. Thread можно привязать к клиенту, назначить, отметить прочитанным, использовать для задач, создания customer records и outbound messages.

Media access проходит через backend-controlled messenger endpoints, а не через public static files by default. Сообщения разных providers могут жить в одном operator experience без сведения каждого канала к phone number.

Integrations

Control plane and runtime plane

Integration layer намеренно разделён на control plane и runtime plane. Integrations hub даёт configuration surfaces для Wappi, YooKassa, Telegram, VK, MoySklad, Email, MAX, Amobit AI Pro, API keys и outbound webhooks.

Runtime code может жить в WhatsApp, Telegram bot, integrations, MoySklad, payments, webhooks, external API или developer platform modules. Многие integration configs движутся к per-store resolution, включая YooKassa, Tilda, VK, Telegram bot, MAX, MoySklad и Email.

External API имеет собственную idempotency model для order creation. API keys хранят hashes и prefixes вместо raw keys, а idempotency records связывают request keys с endpoint behavior, order records и response status.

  • Wappi/WhatsApp and shared messenger profiles
  • Telegram bot runtime and webhook failure journaling
  • MAX bot runtime and profile binding
  • VK callbacks and provider identity handling
  • YooKassa payments, MoySklad sync, Tilda intake and outbound webhooks
  • developer platform apps, installations, access tokens and webhooks

Store, legal entity and retail layer

От single-store CRM к store-aware operating platform

Production code показывает явный переход от single-store CRM к store-aware operating platform. Network layer определяет legal entities, stores, user-store assignments, retail points и retail sale documents.

Retail points добавляют store-floor dimension: cash registers, inventory locations, cashiers, receipt behavior, discount rules, offline behavior, product creation policies, order handoff и prepayment rules.

Это важно, потому что flower operations часто растут из одной точки в несколько branches, legal entities или countries. Store links уже есть на orders, payments, inventory locations, delivery zones, messenger profiles, conversations, integration configs и marketing broadcasts.

POS and fiscal workflows

Retail counter state and fiscal boundaries

POS subsystem рассчитан на реальную работу retail counter. Production models включают workstations, POS sessions, suspended carts, device events, sync batches, checkout records и bouquet assembly records.

Payments моделируются отдельно от orders и могут ссылаться на stores, cash registers, counterparties, POS sessions, allocations и fiscal operations. Cash register shifts and operations отслеживают open/close state, operation type, request payload, response payload и error messages.

Armenia fiscalization path отделяется через dedicated gateway boundary. Monolith остаётся source of business events and operator state, а country-specific fiscal protocol execution может жить вне core Django application.

API architecture

Internal, external and platform contracts

Narciss CRM exposes several API layers. Internal API использует DRF routers для customers, orders, product batches, legacy flower batches, bouquet recipes и delivery zones, плюс product-specific summary routes для prices, movements, reservations и batches.

External API under /api/v1/external/ designed for outside systems and storefront-style integrations. Он включает catalog list/detail, external order creation, Tilda form ingestion, Tilda order ingestion и order status style endpoints.

Platform API under /api/platform/v1/ поддерживает developer app concepts: app manifests, installations, authorization codes, access tokens, refresh tokens и webhooks. Это показывает, что продукт становится platform, которая может host or authorize additional apps.

Background jobs

Celery - часть production, а не placeholder

Production Compose stack запускает Celery worker, Celery Beat, Redis и django-celery-beat. Scheduled jobs включают customer avatar synchronization, expiring batch checks, memorable date checks, scheduled broadcast dispatch, MoySklad full sync и operations controller runs.

Это показывает, где должна жить background work: campaigns не должны блокировать web requests, stock warnings и date-based marketing должны выполняться asynchronously, ERP synchronization является periodic, а operational control loops могут идти по schedule.

Security and access model

Backend-side scoping, hashing and audit trails

Security видна на нескольких слоях. Session-authenticated operator routes защищены login-required middleware, Django sessions, CSRF protection, clickjacking protection, custom CSP middleware и django-axes login lockout behavior.

External API safety включает API-key authentication, explicit permissions, throttling, idempotency keys, allowed origins и key storage через hash/prefix/last4 style fields. Integration secrets хранятся в backend config models вместо exposure normal operator clients.

Ограничение по магазинам тоже важно для безопасности. Связи пользователей с магазинами ограничивают доступ между точками, а active-store middleware стабильно передаёт текущий магазин во все рабочие экраны.

Почему архитектура подходит flower retail

Бизнес-ограничения превращены в границы системы

У цветочного ритейла есть ограничения, которые обычные CRM редко моделируют хорошо: заказы часто начинаются в мессенджерах, покупатель и получатель подарка могут быть разными людьми, склад скоропортящийся и привязан к точке, замены нормальны, сборка букета - реальная работа флориста, доставка критична по времени, а публикация на витрине должна следовать фактическим остаткам.

Narciss CRM напрямую учитывает эти ограничения. Он соединяет customer identity, коммуникацию в каналах, создание заказа, состав букета, резерв склада, работу флориста, доставку и синхронизацию интеграций в один operational loop.

  • message can become an order
  • order consumes recipe stock
  • assembly creates florist work
  • delivery closes the operational chain
  • integrations keep storefronts, messengers, payments and external systems connected

Current status

Live system с production-shaped data

Статья основана на live production code и runtime state, проверенных 2026-05-12. CRM, orders, recipes, inventory, delivery, POS, messaging и integrations связаны. Production Django runtime на момент review не показал system-check issues.

Narciss CRM сейчас является live Django-based operating platform для цветочного бизнеса. Reviewed runtime подтверждает populated production data across stores, legal entities, customers, products, bouquet recipes, orders, chat threads, messages and integration profiles.

Самая сильная продуктовая идея в том, что customer communication, order creation, stock availability, bouquet composition, assembly work, delivery и external integrations - не отдельные tools. Они один operational loop.

EXTERNAL_API_IDEMPOTENCY.PY
class ExternalOrderCreateView(ExternalAPIViewMixin, generics.CreateAPIView):
    serializer_class = ExternalOrderCreateSerializer
    endpoint_name = "external_order_create"

    def _build_request_hash(self, data: dict) -> str:
        normalized = _normalize_idempotency_payload(data)
        payload = json.dumps(
            normalized,
            sort_keys=True,
            separators=(",", ":"),
            ensure_ascii=False,
        )
        return hashlib.sha256(payload.encode("utf-8")).hexdigest()