E-commerce · Pharmaceuticals, supplements, cosmetics and hygiene

Daroobin: an online pharmacy with batch tracking, expiry dates and FEFO allocation

An online pharmacy and cosmetics shop on .NET 10: multi-batch inventory with lot numbers and expiry dates, FEFO allocation, three payment gateways, scheduled campaigns and flash sales, and margin reporting.

Client
Daroobin
Industry
Pharmaceuticals, supplements, cosmetics and hygiene
Year
2025
Status
Live
Visit the site
  • Discovery and analysis
  • UX and UI design
  • Software architecture
  • Front-end development
  • Back-end and API development
  • Database design
  • Third-party integrations
  • Data migration
  • Deployment and DevOps
  • Technical SEO
  • QA and testing
  • Support and ongoing development

The result, in numbers

FEFO
allocation by nearest expiry

stock held per batch, not per product

3
integrated payment gateways

The challenge

Selling medicines and supplements is not like selling ordinary goods, and that is where an off-the-shelf shop falls short.

One product, several different stocks. A single medicine may sit in the warehouse across three separate deliveries, with three lot numbers and three expiry dates. "Stock: 40" is meaningless if you do not know which forty, and which of them expires in two months. Nor is the order of sale arbitrary: the nearest to expiry has to go first, or stock is left on the shelf and written off.

Several warehouses, several suppliers. The same product arrives from two suppliers at different purchase prices, and for the margin to be real you have to know which batch each sale came out of.

The previous shop was WordPress and WooCommerce. Replacing it meant migrating the catalogue, customers and orders, and more importantly preserving the SEO paths — URLs that rank must not break.

The solution

A bespoke platform was built as a modular monolith with three independent parts — storefront, admin panel and API — layered into Domain, Application, Infrastructure and API.

The heart of it is date-aware inventory. Stock is held per batch rather than per product: lot number, expiry date, supplier and warehouse. Allocation follows FEFO — nearest to expiry first — and a stock ledger records every receipt, issue, transfer and adjustment. The system warns on near-expiry and low stock, and reservations on unpaid orders release automatically.

Pricing and campaigns are managed separately from stock: base and special prices, price history, bulk editing, coupons, flash sales and festivals — all with scheduled activation, so a campaign is set up in advance and starts and ends on its own.

Three payment gateways — ZarinPal, Behpardakht Mellat and Saman Kish — with gateway selection, a default, and secure verification. Heavy work runs on RabbitMQ with MassTransit and scheduled jobs under Quartz, so placing an order never waits on an SMS, an invoice or a feed update.

The WooCommerce migration preserved the catalogue, customers and orders and redirected the old URLs, with product and breadcrumb structured data.

Key features

  • Date-aware inventory with lot numbers

    Stock per batch: lot number, expiry date, supplier and warehouse — not one number for the whole product.

  • FEFO allocation

    The stock closest to expiry is allocated first, so goods are not left to be written off.

  • Stock ledger and transfers

    Every receipt, issue, transfer and adjustment is recorded; you can always say where an item came from and went.

  • Scheduled campaigns and flash sales

    Base and special prices, history, bulk editing, coupons and festivals — with activation and end times, so a campaign runs itself.

  • Three payment gateways

    ZarinPal, Behpardakht Mellat and Saman Kish with selection, a default, and secure verification.

  • Warehouse and packing operations

    Printing invoices, labels and picking and packing lists, tracking-code capture, and automatic SMS on order events.

  • Margin reporting

    Sales, finance, margin, inventory and returns on Jalali dates — and because a sale is tied to its batch, the margin is real rather than estimated.

  • Torob feed and WooCommerce migration

    A dynamic product and stock feed for Torob, and a full migration with redirects so rankings survive.

Architecture and stack

Style
Modular monolith
Patterns
Clean architectureCQRSEvent-driven

A modular monolith with Domain, Application, Infrastructure and API separated: the operational simplicity of one deployment, with boundaries that allow a part to be split out later.

Three independent parts: the storefront on Next.js 16 and React 19, the admin panel on React with Vite, and an API with versioned contracts and OpenAPI documentation.

Data: PostgreSQL is the source of truth, with EF Core for writes and Dapper for reports whose queries have to be exact and fast — a margin report over hundreds of thousands of rows through a general-purpose ORM is a performance bug in itself. Redis holds cache and sessions.

Background work: SMS, invoices, the Torob feed and heavy processing go onto RabbitMQ with MassTransit, and scheduled jobs run under Quartz. A customer placing an order never waits behind any of them.

Container deployment with Docker and nginx, structured logging with Serilog, and releases with a backup, health checks and rollback — because this shop is trading while it is being updated.

Front end
Next.jsReact.jsTypeScriptTailwind CSS

Storefront — Next.js 16 and React 19, Persian and RTL

Front end
Vite

Responsive admin panel with TanStack Query

Back end and API
.NET 10ASP.NET CoreC#REST APIClean ArchitectureEntity Framework CoreDapper

EF Core for writes, Dapper for heavy reporting

Database
PostgreSQL
Cache
Redis
Messaging and queues
RabbitMQMassTransitQuartz.NET

SMS, invoices, the Torob feed and scheduled jobs

Infrastructure and deployment
DockernginxSerilog

Container deployment with backups, health checks and rollback

Integrations

  • ZarinPal, Behpardakht Mellat and Saman Kish
  • Torob — a dynamic product and stock feed
  • SMS.ir for order-event notifications
  • Neshan maps for customer address positions

Full write-up

Capabilities in detail

Catalogue

Multi-level categories, brand and licensing country, conditional specifications by product type, simple and variable products with unlimited attributes, image galleries, SKU and GTIN, and publication status.

Date-aware inventory

Multiple warehouses and suppliers, independent stock per variant and per batch, lot numbers and expiry dates, physical and online stock kept apart, transfers between warehouses, a stock ledger, FEFO allocation, low-stock and near-expiry alerts, and automatic reservation and release against orders.

Pricing and campaigns

Base and special prices, price change history, bulk price editing, discount coupons, flash sales, festivals, and scheduled activation and expiry for every campaign.

Orders and operations

Orders placed by customer or operator, order, payment and shipping status management, printing of invoices, labels and picking and packing lists, tracking-code capture, SMS on order events, and returns with review and refund.

Payments

Three gateways — ZarinPal, Behpardakht Mellat and Saman Kish — with gateway selection, a configurable default, a controlled callback and secure verification.

Shipping and tracking

Dynamic zones and shipping methods, addresses with a map position, postal tracking codes and order-status notifications.

Customers

One-time-code login, profiles, multiple addresses, wish lists, reviews, support tickets, return requests, back-in-stock alerts and a loyalty club.

SEO

Canonicals, sitemap, robots, index and noindex control, redirects for old links, and product and breadcrumb structured data.

Management reporting

Sales, finance, profit margin, inventory, returns, support and customer analysis — all on Jalali dates. A responsive dashboard, separated roles and permissions, and a history of administrator activity and sensitive changes.

Content and integrations

Pages, blog, banners, menus and media; a dynamic product and stock feed to the Torob comparison service; SMS via SMS.ir; maps for customer addresses; and infrastructure ready for CRM and accounting.

Have a similar project in mind?

Fifteen minutes is enough to say what it needs, how long it takes and where to start.