Back to projects
PROJECT CASE / DJANGOv2.0.0 release

Retail Procurement API

A backend application for procurement between buyers and suppliers. It combines a catalogue, cart, order placement, price-list imports, user roles, and background operations.

Context
Diploma backend project
Domain
B2B procurement and orders
Foundation
Django · DRF · PostgreSQL
PROBLEM & CONSTRAINTS

An order is more than a row inserted into a database.

The core complexity sits at the boundary between the catalogue, cart, stock, permissions, and long-running background work.

01 / PROBLEM

Problem

A buyer needs a predictable path from catalogue to confirmed order, while a supplier needs control over products, stock, and incoming orders. Concurrent requests must not sell the same stock twice.

02 / CONSTRAINTS

Constraints

  • Stock validation and deduction must be atomic.
  • YAML imports, notifications, and image processing must not block HTTP requests.
  • Buyers, suppliers, and administrators have different permissions and workflows.
  • Catalogue cache entries must be invalidated when relevant data changes.
ARCHITECTURE

The synchronous purchase path is separated from background work.

DRF accepts the request, a service layer owns the business transaction, PostgreSQL protects stock, and Redis with Celery handles caching and long-running tasks.

Retail Procurement API flow: a client calls DRF, the service layer performs a PostgreSQL transaction, Redis serves cache and broker duties, and Celery processes background jobs.
  • transaction.atomic
  • select_for_update
  • cache invalidation
  • background tasks
PURCHASE FLOW

Order placement runs as an explicit business transaction.

The service layer keeps validation and state changes together instead of turning the controller into a container for business logic.

  1. Catalogue and cart

    The buyer filters the catalogue, adds products to a cart, and changes quantities. Catalogue reads can be served from Redis cache.

  2. Permissions and input validation

    DRF validates authentication, the user role, cart contents, and request shape before starting the transaction.

  3. Stock locking

    The order service opens transaction.atomic and selects stock rows with select_for_update to prevent concurrent deduction.

  4. Order creation

    After validation, stock is deducted and the order with its items is persisted as one consistent change.

  5. Background operations

    Email, price-list imports, and image processing are delegated to Celery instead of extending API response time.

KEY DECISIONS

Order reliability is supported by both code structure and the database.

Each tool addresses a concrete risk: concurrent stock changes, long-running work, and reusable business rules.

CONSISTENCY

Order service layer

Order placement is extracted from the view into one scenario that owns validation, locking, and related entity changes.

CONCURRENCY

PostgreSQL row locking

transaction.atomic and select_for_update protect stock while multiple carts are being confirmed.

LATENCY

Celery for long-running work

YAML imports, email, and image processing run outside the request-response cycle.

READ PATH

Redis catalogue cache

Frequently read data is cached, with explicit invalidation when products or categories change.

QUALITY & DELIVERY

Critical user journeys are covered by tests.

The suite covers individual API areas and an integration purchase flow from authentication to order placement.

TESTSpytest-django

Authentication, throttling, catalogue, cart, order placement, and an end-to-end purchase scenario.

API CONTRACTSwagger + ReDoc

drf-spectacular generates the API schema and exposes two documentation views.

DELIVERYDocker + GitHub Actions

A containerised environment and automated checks make local execution reproducible.

LIMITS & NEXT STEPS

The core is complete, while product-level capabilities can expand.

The case separates implemented mechanisms from the next layer of product and operational work.

NEXT

Status history and audit trail

Operational traceability would benefit from explicit order transition history and user action logs.

NEXT

Discounts and promotions

Pricing is not yet extracted into an extensible rules and campaign module.

NEXT

Load and concurrency scenarios

The next step is a reproducible benchmark for concurrent checkout and catalogue behaviour under load.

RESULT

The project presents a backend as a set of consistent business workflows.

The main result is not endpoint count, but a clear separation between HTTP handling, transactional checkout, caching, and background tasks.

  • Concurrent stock changes should be protected at both transaction and database level.
  • Long-running work should not become part of the user's HTTP response.
  • A service layer is useful when one workflow changes multiple related entities.
SOURCE CODE

Source code, tests, and documentation are available in the repository.

The README covers quick start, API workflows, project structure, and Docker Compose commands.