Soroush Neyestani

Software Engineer

Application Architect

Enterprise Application Developer

Technical Author & Educator

CRM Full Sales & Operations Platform

Background

The original version of this system was developed in June 2020 as a CRM application focused primarily on customer and sales relationship management.

Years later, I returned to the same product concept and redesigned it as a much broader Sales & Operations Management Platform.

The new version is not simply a visual refresh or a framework upgrade. It is a substantial architectural and functional modernization in which the original CRM concept was expanded into a complete operational workflow covering sales, commercial documents, payments, inventory, fulfillment, shipment, notifications, support, reporting, and administration.

The current version was rebuilt with Laravel 13.


Business Workflow

The main operational workflow is:

Lead → Customer → Sales Follow-up → Quotation → Order → Payment → Invoice → Inventory → Packing → Shipment → Delivery → Support

The purpose of the redesign was to connect these stages through explicit business rules instead of treating them as isolated CRUD modules.


CRM

The CRM domain includes:

  • leads;
  • customers;
  • contacts;
  • addresses;
  • acquisition sources;
  • activities;
  • calls and interaction history;
  • follow-ups;
  • opportunity tracking;
  • unified timeline behavior.

Leads can be converted into customers while keeping the commercial relationship intact.

Customers can contain multiple contacts and addresses instead of forcing all information into a single flat table.

This makes the customer entity suitable for long-term operational use rather than only initial lead capture.


Sales Pipeline

The sales process is implemented through a controlled pipeline.

The main status flow includes stages such as:

NEW
CONTACT_PENDING
CONTACTED
QUALIFIED
QUOTATION_SENT
PAYMENT_PENDING
PAID
PREPARING
SHIPPED
DELIVERED
CLOSED

Additional side states support real-world outcomes such as:

NO_ANSWER
FOLLOW_UP_LATER
LOST
CANCELLED

Transitions are handled by dedicated application services rather than unrestricted manual database updates.

This creates a predictable and auditable sales workflow.


Activities and Follow-ups

The system distinguishes between:

  • activity history;
  • scheduled follow-up actions.

Activities represent completed interactions such as calls, meetings, notes, or sales actions.

Follow-ups represent future work and can be scheduled, completed, or cancelled.

This separation provides both historical context and an actionable work queue for sales users.


Quotations

The quotation module supports:

  • independent business numbering;
  • customer snapshots;
  • product/item snapshots;
  • quantity;
  • price;
  • discount;
  • shipping cost;
  • optional tax;
  • currency;
  • validity;
  • terms;
  • notes;
  • print/PDF-ready presentation;
  • lifecycle states.

Typical quotation states include:

DRAFT
SENT
ACCEPTED
REJECTED
CANCELLED
EXPIRED
CONVERTED_TO_ORDER

A sent quotation is treated as a stable commercial document.

The important architectural decision is that commercial snapshots are preserved so later changes to customer or product master data do not silently modify historical documents.


Orders

Accepted quotations can be converted into orders.

Orders receive their own business numbers and retain immutable commercial snapshots.

The order then becomes the central record connecting:

  • customer;
  • quotation;
  • payments;
  • invoice;
  • fulfillment;
  • inventory;
  • shipment.

Multiple Payments per Order

The platform supports more than one payment for the same order.

Payment records support states such as:

PENDING
CONFIRMED
REJECTED

The application derives the aggregate commercial payment status:

UNPAID
PARTIALLY_PAID
PAID
OVERPAID

This is calculated from confirmed payments instead of being maintained manually.

Monetary data is handled without floating-point arithmetic to avoid precision issues.


Invoicing

Invoices are generated from eligible paid orders.

Each invoice includes:

  • an independent business number;
  • order reference;
  • customer snapshot;
  • commercial snapshot;
  • print view;
  • auditability.

The system therefore connects invoicing directly to the commercial and payment workflow.


Inventory Architecture

Inventory was redesigned around a Stock Movement Ledger.

The system does not rely on a freely editable stock balance as the primary source of truth.

Instead, inventory is derived from movement records.

Supported movement types include:

PURCHASE_IN
SALE_OUT
RETURN_IN
ADJUSTMENT_IN
ADJUSTMENT_OUT
TRANSFER_IN
TRANSFER_OUT

This provides traceability for every stock change.

Benefits include:

  • clear movement history;
  • auditable stock changes;
  • explicit transfers;
  • explicit returns;
  • explicit adjustments;
  • reduced risk of unexplained balance edits.

Multi-Warehouse Support

The inventory model is multi-warehouse capable.

Transfers are handled as paired movements:

TRANSFER_OUT
TRANSFER_IN

The operation is designed to execute atomically so a transfer cannot partially complete and leave the ledger inconsistent.

The system also supports negative-stock control as a configurable business rule.


Fulfillment

Fulfillment is managed independently from the commercial order status.

The operational flow includes:

PENDING
PACKING
PACKED
READY_TO_SHIP
SHIPPED
DELIVERED

This separates the commercial lifecycle from the physical preparation and delivery process.


Package Generation

The system supports configurable package generation.

The number of packages can be defined through:

  • a product-level override;
  • a global fulfillment default.

This avoids hard-coding packaging rules into the application.

Package generation is therefore configurable and reusable for different products or operational scenarios.


Labels

Package labels can contain frozen snapshots of:

  • sender;
  • receiver;
  • mobile number;
  • province;
  • county;
  • locality;
  • address;
  • postal code;
  • order number;
  • package index;
  • total package count;
  • barcode value;
  • QR payload.

Label access is protected by application authorization instead of exposing sensitive files publicly.


Shipment Tracking

Shipment records support:

  • carrier;
  • tracking number;
  • shipment date;
  • package relationship;
  • shipment status;
  • notes.

The architecture intentionally leaves carrier API integration as an extension point.

This prevents the domain layer from becoming dependent on a single shipping provider.


Notifications: Major Upgrade from the 2020 Version

One of the clearest differences between the original version and the new generation is how external communication settings are handled.

In the older version, integrations such as Telegram required direct developer-side configuration.

In the new version, Telegram / SMS / Queue-related settings and test operations are exposed through the administrative interface.

This means the customer can manage or test operational notification behavior without requiring code changes for every configuration adjustment.

The notification pipeline is structured as:

Business Event
→ Notification Service
→ Durable Notification Record
→ Queue
→ Delivery Service
→ Provider Gateway
→ Attempt Log

Supported notification channels include:

SMS
TELEGRAM

Provider-specific logic is separated behind gateway abstractions.

This makes future SMS-provider replacement possible without rewriting the business domain.

Notification states include:

QUEUED
SENDING
SENT
FAILED
CANCELLED

Retry and backoff behavior is handled asynchronously.


Support, Warranty, and Returns

After-sales support is modeled as a separate domain rather than being mixed into sales activities.

The support module includes:

  • tickets;
  • warranties;
  • returns.

When a validated returned product should be added back to inventory, the support module uses the inventory service and creates a real:

RETURN_IN

movement.

This preserves the inventory ledger as the source of truth.


Finance Lite

The application includes a lightweight finance layer.

Confirmed payments can be projected into finance entries in an idempotent way.

The system intentionally does not attempt to become a complete accounting package.

It does not claim to provide:

  • general ledger;
  • payroll;
  • statutory tax filing;
  • complete accounting workflows.

This keeps the scope aligned with the operational requirements of the platform.


Reporting

Reporting covers multiple operational areas, including:

  • leads;
  • conversion;
  • sales;
  • payments;
  • customers;
  • products;
  • inventory;
  • fulfillment;
  • support;
  • salesperson performance.

Reports are generated from operational source data rather than duplicated manual summary tables wherever possible.


Role-Based Access Control

The platform supports business-oriented roles such as:

System Administrator
Sales Manager
Sales Agent
Accounting
Warehouse / Packing
Support

Permissions are capability-based, for example:

crm.view
crm.manage
sales.view
sales.manage
payments.view
payments.manage
inventory.view
inventory.manage
fulfillment.view
fulfillment.manage
support.view
support.manage
reports.view
admin.users.manage

Backend authorization is enforced through policies and permission checks.

Hiding a menu item is not treated as sufficient access control.


Audit Logging

Administrative and operational actions can be recorded through an Audit Log.

Audit records can include:

  • event type;
  • acting user;
  • affected entity;
  • old values;
  • new values;
  • metadata.

This provides operational traceability for sensitive changes.


Iranian Geographic Data

The CRM integrates structured Iranian national-division data.

Raw geographic source data is imported locally and isolated behind a dedicated service/adapter layer.

The CRM itself depends on the normalized application-facing geography model rather than the raw source schema.

This keeps the business domain decoupled from the source-data format.


Business Numbering

Customer-facing document numbers are independent from database primary keys.

Separate number sequences are used for entities such as:

  • leads;
  • customers;
  • quotations;
  • orders;
  • invoices;
  • stock movements;
  • transfers;
  • fulfillment records;
  • packages;
  • shipments;
  • support records.

This preserves flexibility in business-document numbering.


Architecture

The application was rebuilt as a Laravel Modular Monolith.

This architecture was chosen deliberately.

A microservice architecture would have added unnecessary operational overhead for this project size, including:

  • distributed deployment;
  • service communication;
  • distributed observability;
  • cross-service transaction complexity;
  • infrastructure overhead.

The modular monolith keeps the deployment model simple while maintaining clear internal boundaries.

The internal architecture separates:

UI / HTTP Layer
Request Validation
Authorization Policies
Application Services
Domain Models
State Machines
Persistence
Background Jobs
External Gateway Abstractions
Reporting

Business rules are intentionally kept out of Blade templates and minimized inside controllers.


Laravel 13 Modernization

The new generation was rebuilt using Laravel 13.

The stack includes:

  • PHP 8.4;
  • Laravel 13;
  • Laravel Jetstream;
  • Livewire 3;
  • Laravel Fortify;
  • Laravel Sanctum;
  • MySQL / MariaDB;
  • Tailwind-based UI;
  • Alpine.js through the Laravel frontend stack.

The modernization was therefore both architectural and technological.


Persian RTL Interface

The interface was redesigned for Persian users with:

  • RTL layout;
  • Persian labels;
  • responsive navigation;
  • grouped sidebar;
  • icon-based navigation;
  • responsive forms;
  • responsive tables;
  • empty states;
  • status badges;
  • mobile navigation drawer;
  • workflow-oriented dashboard.

The final UI pass focused on removing the visual feel of a framework-generated admin panel and creating a cohesive business application.


PWA: Another Major Upgrade

A major new capability compared with the original 2020 version is Progressive Web App support.

The application can now be installed directly on:

Windows through Chrome / Edge
Android through Chrome

No separate native Android or Windows application is required.

The same web application remains the single source of truth.

This avoids duplicating business logic across different client codebases.

Offline business mutations are intentionally not enabled because the platform relies on transactional server-side state.


Security

Security decisions include:

  • production HTTPS requirement;
  • password hashing;
  • CSRF protection;
  • request validation;
  • backend authorization;
  • least-privilege roles;
  • protected file access;
  • upload validation;
  • environment-based secrets;
  • audit logging;
  • rate-limiting capability;
  • disabled public registration;
  • production APP_DEBUG=false;
  • no requirement for publicly exposed MySQL.

The production handover also documents:

  • Nginx serving only the Laravel public/ directory;
  • PHP-FPM;
  • local-only database access;
  • UFW;
  • Fail2ban;
  • HTTPS certificate management;
  • off-server encrypted backups;
  • restore drills;
  • health monitoring.

Production Handover

The development scope ended at a complete application and deployment-handover package.

Infrastructure administration is intentionally separated from application development.

The handover package includes:

  • production source archive;
  • production environment template;
  • Nginx configuration example;
  • Supervisor queue-worker example;
  • systemd scheduler examples;
  • backup examples;
  • restore-drill procedure;
  • health-check configuration;
  • security-hardening checklist;
  • deployment checklist;
  • rollback instructions;
  • SHA-256 manifest.

This creates a clear responsibility boundary:

Application development: architecture, implementation, testing, release package, deployment requirements.

Infrastructure operations: VPS, Linux administration, DNS, TLS, firewall, backup repository, monitoring, and production operations.


Automated Testing

The final release reached:

148 automated tests
564 assertions

The test suite covers framework-level behavior and custom business workflows.

Testing was used as a release gate throughout development.

A feature was not considered complete simply because its page rendered successfully.

Each implementation phase had to return to a green state before the next phase could proceed.


Code Quality

The release workflow included:

  • PHPUnit;
  • Laravel Pint;
  • PHPStan / Larastan;
  • runtime verification;
  • phase-based regression gates.

The objective was to keep architectural and implementation issues visible throughout development instead of accumulating them for a final cleanup stage.


Development Approach

The modernization followed a phase-gated implementation process:

Requirements & Architecture
→ Engineering Foundation
→ Identity / RBAC / Settings / Audit / Geography
→ Catalog / Warehouse / CRM
→ Sales Pipeline / Activities / Follow-ups
→ Quotations
→ Orders / Payments / Invoices
→ Inventory Ledger
→ Fulfillment / Packages / Labels / Shipment
→ Notifications
→ Support / Warranty / Returns
→ Finance Lite / Reporting
→ PWA
→ Production Handover

Each phase was completed, tested, and validated before moving to the next.


What Changed Compared with the 2020 Version

The most important evolution can be summarized as:

Then

  • CRM-oriented scope;
  • narrower sales functionality;
  • more developer-managed configuration;
  • integrations configured directly in code;
  • no PWA;
  • less operational automation;
  • smaller domain scope.

Now

  • full Sales & Operations workflow;
  • Laravel 13 modernization;
  • modular architecture;
  • explicit sales state machine;
  • quotation/order/payment/invoice workflow;
  • stock movement ledger;
  • multi-warehouse support;
  • fulfillment and package generation;
  • label and shipment management;
  • support/warranty/returns;
  • finance-lite reporting;
  • admin-configurable Telegram/SMS/Queue behavior;
  • role-based access control;
  • audit logging;
  • PWA installation on Windows and Android;
  • extensive automated testing;
  • production handover documentation.

Final Result

The project is a practical example of software modernization over time.

Instead of discarding an older CRM concept, I revisited it with several more years of engineering experience and rebuilt it around stronger domain modeling, explicit business rules, cleaner architecture, better operational coverage, stronger testing, and a modern deployment model.

The result is no longer only a CRM.

It is a complete Sales & Operations Management Platform designed to manage the lifecycle from the first lead to final delivery and after-sales support.