Back to Systems

Wasilio COD Operations & Risk Platform

A multi-tenant COD platform for Moroccan ecommerce merchants that manages confirmation and courier workflows while building toward order risk scoring and fraud detection.

June 1, 2026
Domain Driven DesignRisk ScoringFraud DetectionOrder ManagementSpring Boot

The Problem

Moroccan COD merchants lose money when risky orders are shipped by default, then fail through refusal, unreachable customers, fake intent, bad addresses, or suspicious repeat patterns.

The Solution

Wasilio centralizes confirmation, courier, and failure workflows, then turns order outcomes into signals for risk scoring, fraud detection, and smarter pre-shipment decisions.

What It Solves

  • Helps merchants avoid paying shipping for predictable failed deliveries.
  • Turns confirmation attempts and delivery outcomes into reusable risk signals.
  • Gives teams queues for confirmation, pickup, delivery, failure handling, and review.

Architecture

  • Spring Boot modular monolith with PostgreSQL and Flyway.
  • Event log plus read projections for order timelines and queues.
  • Risk scoring layer can consume order history, customer patterns, failure reasons, and courier outcomes.

Trade-Offs

  • Modular monolith over microservices for early product speed.
  • Event log adds complexity but creates the history needed for scoring.
  • Fraud scores must explain risk without silently blocking legitimate customers.

Problem Evidence

Operational gaps turned into product surfaces

Each feature maps to a recurring COD failure mode, including the cost of shipping risky orders.

Failure

New orders wait in chat threads

Slow confirmation and lost intent

Response

Confirmation queue

Failure

Customers ask for later callbacks

Follow-ups disappear

Response

Scheduled callback workflow

Failure

Couriers receive informal assignments

Ownership is unclear

Response

Assignment and pickup queues

Failure

Failed deliveries have no structure

Teams cannot learn from failure reasons

Response

Delivery failure capture

Failure

Risky orders ship by default

Merchants pay delivery cost before risk is visible

Response

Order risk score and fraud signals

Workflow Design

From COD intent to collected cash

Wasilio converts scattered post-checkout work into owned queues and turns failed outcomes into risk signals for the next order.

Merchant Intake

  1. Order created
  2. Customer details captured
  3. Confirmation requested

Risk Review

  1. History checked
  2. Risk signals scored
  3. Ship or reconfirm

COD Confirmation

  1. Call attempt recorded
  2. Callback scheduled
  3. Confirmed or rejected

Courier Operations

  1. Courier assigned
  2. Pickup tracked
  3. Delivered or failed

Domain Boundary

Order lifecycle as business control

1
Created
Merchant

Order enters the workspace.

2
Awaiting Confirmation
Agent

Call attempts and callbacks are tracked.

3
Confirmed
Agent

Customer intent becomes operational work.

4
Assigned
Operator

Courier ownership is explicit.

5
Picked Up
Courier

Package leaves merchant control.

6
Delivered / Failed
Courier

Outcome is captured with audit context.

Architecture Evidence

Event log plus projection

Command Side

OrderLifecycleService validates every transition before appending an event.

Event Log

domain_events stores the facts behind each order timeline.

Read Projection

orders projection powers search, queues, details, and dashboards.

Risk Signals

Order outcomes, confirmation attempts, failed reasons, and customer patterns can feed explainable scoring.

The design protects tenant isolation and prevents invalid order transitions before state is persisted.

The Problem In One Sentence

In Moroccan COD ecommerce, checkout is not the sale. The merchant pays operational cost before knowing whether the buyer is serious, reachable, or likely to refuse delivery.

That creates the real product problem: merchants do not need another order table; they need an operating system that manages COD work and learns which orders are risky before shipping.

Evidence Of The Workflow Problem

The visual evidence above is the product argument: Wasilio was shaped around repeated operational failure points, then each failure point became a queue, workflow, risk signal, or staff control.

This is why the system is modeled around workflows and state transitions instead of generic CRUD.

Design Decision

The visual model above is the core of the case study. The product was not organized around database tables; it was organized around who owns the next operational step.

The backend enforces that model in OrderLifecycleService. That means the system rejects impossible actions, such as delivering an order that was never picked up or modifying an order already in a final state.

Risk Intelligence Direction

The important product direction is that failed COD orders should not disappear into reports. They should become risk signals.

| Signal | Why it matters | Product response | | --- | --- | --- | | Repeated refusal from the same phone or address | Indicates possible fake intent or repeat abuse | Buyer risk score | | Customer unreachable after several attempts | Predicts likely failed delivery | Hold or reconfirm before shipping | | Bad address or suspicious location pattern | Increases courier cost and failure probability | Address risk flag | | Courier reports vague failure reasons | Hides whether the issue is buyer, courier, or operations | Structured failure taxonomy | | Merchant keeps shipping similar failed orders | Repeats preventable shipping loss | Recommendation before dispatch |

The score should not behave like a black box. A merchant should see the reasons behind the risk score, then decide whether to ship, reconfirm, require prepayment, hold for review, or reject clear abuse.

Architecture Decision

Wasilio uses an event-backed lifecycle for order changes and a read projection for operational screens. That event history is also the foundation for future risk scoring.

Why this matters:

  • The event log explains how an order reached its state.
  • The projection keeps dashboards and queues fast.
  • The lifecycle service protects business invariants.
  • Failed delivery outcomes become features for future order scoring.

Confirmation Is Not A Boolean

COD confirmation has more outcomes than yes or no:

sequenceDiagram
    autonumber
    participant Customer as Customer
    participant Agent as Confirmation agent
    participant App as Wasilio workspace
    participant Risk as Risk signals
    participant Order as Order lifecycle
    participant Events as domain_events
    participant Queue as Courier queue
 
    Customer->>App: Places COD order
    App->>Risk: Check phone, address, attempts, past outcomes
    Risk-->>App: Risk level + explanation
    Agent->>App: Record call attempt and note
    App->>Order: Request transition
    alt Confirmed and acceptable risk
        Order->>Events: OrderConfirmed
        Order->>Queue: Ready for courier assignment
    else Call back later
        Order->>Events: CallbackScheduled
        App->>Agent: Requeue for follow-up
    else Rejected or high-risk abuse
        Order->>Events: OrderRejected
        App->>Risk: Feed failure signal
    else Delivered or failed after dispatch
        Queue->>Order: Delivery outcome
        Order->>Events: Delivered or FailedDeliveryCaptured
        Order->>Risk: Feed outcome for future scoring
    end

The separate confirmation_attempts model preserves history: who called, what happened, which attempt number it was, and whether a callback is due, overdue, upcoming, or resolved.

System Surfaces

Wasilio has three product surfaces:

| Surface | Why it exists | | --- | --- | | Public landing and signup | Capture serious pilot merchants | | Merchant workspace | Run COD operations day to day | | Staff admin | Manage tenants, plans, manual payments, receipts, and lead follow-up |

This separation matters because the buyer journey, merchant workflow, and internal operations are different systems with different permissions.

The website demo points to wasilio.ma. The full merchant application is not publicly deployed yet, so the portfolio presents the architecture and product direction without implying the private app is live.

Security And Operations

The implementation includes JWT authentication, role-aware routing, tenant status blocking, password reset tokens, public signup controls, abuse throttling, Flyway migrations, local seed data separation, and actuator health endpoints.

Those details are not decorative. They make the system usable as a real SaaS pilot instead of a dashboard prototype.

Trade-Offs

Modular monolith first

Orders, confirmations, couriers, billing, and leads are separate concerns, but splitting them into services too early would create distributed complexity before the product needs it.

Event log plus projection

Event-backed order state is more work than a direct status update. The payoff is auditability and stronger workflow validation.

Manual billing first

For early Moroccan COD pilots, managed onboarding and manual receipts are more realistic than automated subscription checkout. The trade-off is staff workload, but it matches the sales motion.

Explainable risk scoring

Risk scoring can reduce shipping loss, but it must be explainable. A silent score would make the system hard to trust. Wasilio should show the reason: failed confirmation history, repeat refusal pattern, suspicious address, or courier outcome trend.

What This Case Study Demonstrates

Wasilio demonstrates product architecture under local business constraints:

  • Turning a messy operational process into explicit workflows.
  • Using state machines to protect business invariants.
  • Combining event history with fast read models.
  • Designing a foundation for failed-order prediction and fraud detection.
  • Designing multi-tenant SaaS with staff controls.
  • Choosing architecture based on product stage, not trend.

The engineering point is simple: architecture is valuable when it preserves business truth. For Wasilio, that truth is the journey from customer intent to confirmed order, courier handoff, delivered cash, explained failure, and smarter future shipping decisions.