Case study · 04 / 09

Katrin

B2B ordering & promotions platform

Order campaigns, point budgets, promotions, warehouse and ERP integrations for a manufacturer and its sales network — rebuilt from a legacy app on a strict, secure modern stack.

  • B2B
  • Security
  • Integrations

Partner

Manufacturer & its distribution network

Industry

FMCG · B2B sales

Platform

Web app (React SPA + API)

Our role

Rebuild, end to end

The product

What it does

Three roles share one platform. Admins run order campaigns with point budgets per key-account manager, promotions with distributor balances and vouchers, the warehouse and integrations. KAMs manage their distributors. Distributors order and join promotions — on desktop or phone.

Our part

What we built

We rewrote the old Laravel 9 + React 17 app from scratch: a React 19 + TypeScript (strict) SPA and a Laravel 13 pure-API backend in CQRS with domain models separated from Eloquent, architecture tests and PHPStan at max level.

Under the hood

The hard parts

  1. 01

    CQRS with guard rails

    Commands and queries go through a Tactician bus, domain models stay independent of the ORM, and Pest architecture tests stop layers from leaking into each other.

  2. 02

    Tokens done carefully

    Access token only in memory, refresh token in an httpOnly cookie, and an axios interceptor that folds parallel 401s into a single refresh.

  3. 03

    Webhooks the ERP can trust

    HMAC-SHA256 signed payloads, exponential backoff from 30 seconds to 6 hours over five attempts, a full delivery log, manual retry and secret rotation.

  4. 04

    Security and GDPR built in

    TOTP two-factor with recovery codes, time-boxed “log in as” for support with a required reason and audit trail, and an activity log that hides personal data by default.

The outcome

A legacy order system rebuilt as a secure, testable platform for the whole sales network.

Inside the product

7 screens, explained

Demo data · click any screen to enlarge

01

Admin dashboard

KPIs, 30/90-day charts from our own SVG component, distributor and KAM rankings and alerts. Each panel is its own TanStack Query; reports sit in a multi-level Redis cache.

02

Campaign lifecycle and budgets

Status driven by a state machine — draft, active, finished, archived — with point budgets for each assigned KAM. The active tab lives in the URL and lifecycle actions refresh the cache by themselves.

03

Webhook delivery log

Every delivery to the external ERP: HTTP code, attempts, full JSON payload and response, with manual retry and secret rotation. Signed with HMAC-SHA256 and retried with exponential backoff in the queue.

04

GDPR-safe activity log

Domain events with actor, aggregate and description, loaded with cursor pagination. Personal data is hidden unless explicitly revealed, and CSV export runs as a background job.

05

Audited “log in as”

Support impersonation needs a reason and a 1–240 minute lifetime. Sessions can be ended early, and the backend closes expired ones on its own.

06

Two-factor sign-in

Six TOTP boxes that jump between fields, handle backspace and pasting the whole code, with resend countdown and recovery codes — verified by Laravel Fortify.

07

Distributor home on mobile

Same app, different role: banners, featured promotion, KPIs and recent orders, collapsing to one column with a slide-out drawer menu.

Stack

Frontend

  • React 19
  • TypeScript (strict)
  • Vite 8
  • MUI 6
  • Tailwind 4
  • TanStack Query 5
  • Zustand 5
  • React Hook Form + Zod

Backend

  • Laravel 13 / PHP 8.4
  • CQRS (Tactician)
  • Sanctum
  • Fortify 2FA
  • dompdf

Data

  • MariaDB
  • Redis
  • Queues

Quality

  • Vitest
  • Playwright
  • Pest
  • PHPStan (max)
  • Docker

Next case

IUSVitae →

E-learning platform for law students

Want a product
like this?

Get a free estimate