Back to portfolio
IntegrationClient work

DeltaPlus ERP Integration

Laravel B2B portal connected to the ManFin ERP for catalog and locality synchronization, per-client differentiated pricing, XML/CSV/JSON feeds, online ordering, and asynchronous order export back into the ERP.

DeltaPlus ERP Integration

Core stack

PHP 8.2+
Laravel 12
Laravel Sanctum
Laravel Queue
Eloquent ORMFilament 3Livewire 3BladeTailwind CSSViteMySQLMicrosoft SQL ServerPDOFreeTDS / dblibDockerNginx

The challenge

The main challenge was keeping a coherent B2B catalog consistent between a Laravel application and a ManFin ERP accessed through stored procedures, while maintaining per-client differentiated pricing, up-to-date stock and technical parameters, external feeds, and a checkout that had to turn a web order into an ERP-compatible structure, including eco-tax and auxiliary lines.

The solution

The solution isolates the ManFin integration inside an ErpService and moves slow operations into Laravel Queue jobs. Products, categories, and localities are synchronized into local MySQL tables, the Blade/Tailwind portal consumes this data for the B2B experience, and a FeedService generates per-account personalized exports. Orders are created transactionally in the local database and then exported asynchronously through stored procedures, with retries and a check for an already-saved ERP ID. Filament provides administration and manual triggering of synchronizations, while Sanctum protects the feed API.

Notable complexity

DeltaPlus ERP Integration connects a modern B2B portal to the ManFin ERP system, which serves as the operational source of truth for products, categories, localities, and order registration. The integration does not treat the ERP as a generic API: a dedicated service uses PDO/FreeTDS and ManFin-specific stored procedures, checks a primary endpoint and a fallback one, and exposes the operations needed for catalog, technical parameters, eco-tax, customers, and orders.

The local catalog is synchronized through Laravel Queue jobs. Products are fetched by CodStoc and updated together with the name, list and promo prices, stock, EAN, image, specifications, warranty, and other ERP indicators. Technical parameters are refreshed per product, category association is synchronized, and the eco-tax is resolved separately and persisted for correct order export. Categories use the hierarchical relationship from the ERP, and counties and localities are bulk-imported in batches of 500 rows to support checkout.

On the client side, the application offers authentication, a dashboard, a filterable and paginated catalog, a product page, a cart, checkout, and order history. The displayed price starts from the list or promo price configured for the account and applies the client's discount or markup. Stock shown in the portal and feed is capped at 50 units, and catalog search covers name, SKU, and EAN. Checkout supports both individuals and companies, plus selection of county/locality from the data synchronized from the ERP.

Orders are persisted locally before the external integration runs, and export to ManFin executes asynchronously. The job creates the ERP customer, order header, and product lines, converts prices to the VAT-exclusive value used by the ERP, splits the eco-tax into its own lines, and can add technical lines for shipping and cash-on-delivery. The export retries three times with a 60-second backoff and avoids re-running when the ERP ID has already been saved locally. However, the code does not implement a distributed idempotency or locking mechanism between creating the order in the ERP and saving the local ID, so this remains one of the important hardening directions.

The application also exposes a v1 API protected with Laravel Sanctum. Authenticated users can obtain their personalized feed in XML, CSV, or JSON, and the generated feed is saved per account. There is also an internal endpoint for regenerating the CSV, additionally protected by an IP restriction. Separately, a CLI command can generate all three formats for a single user or for all accounts. Generation is correctly personalized per client price, but in the current implementation it loads the entire active catalog into memory for each user, without streaming or chunking.

The Filament admin panel manages users, products, categories, and orders, and includes a dedicated ERP synchronization page. The administrator can check reachability for the primary and fallback hosts, queue synchronization of categories, localities, and products, and manually resend an order to the ERP when it does not yet have an external ID. Filament access is restricted to active accounts with an administrator flag; the portal and API login use standard authentication, but the current code does not explicitly add the is_active filter to client authentication.

The repository includes a migration path from the old wpke_erp_* tables to the erp_* schema, which indicates the modernization of an existing flow rather than a project demonstrated as built entirely from scratch. At the same time, the current manifests require PHP 8.2 and Laravel 12, while the legacy Docker image starts from PHP 8.0, and the compose file labeled prod is practically identical to the local one and does not define a queue worker, scheduler, healthcheck, or CI/CD. The existing tests are only the default Laravel examples. Consequently, the seed treats the integration, data model, and B2B flows as confirmed functionality, but does not claim automated deployment, real test coverage, online payments, scheduled synchronization, email/SMS, analytics, or AI.

Key results

  • Authenticated B2B portal with dashboard, catalog, product page, cart, checkout, and order history
  • Catalog with search by name, SKU, or EAN, category filtering, and pagination at 24 products
  • List or promo price selectable per account, adjusted by the client's discount or commercial markup
  • Asynchronous synchronization from ManFin for products, technical parameters, categories, and localities
  • Separate resolution and persistence of the eco-tax for the products that use it
  • Locality import in batches of 500 rows to populate checkout
  • Asynchronous order export to the ERP with customer, header, and order line creation
  • Splitting eco-tax, shipping, and cash-on-delivery fee into distinct ERP lines when applicable
  • Retry for order export to the ERP: three attempts with a 60-second backoff
  • Personalized feeds per client in XML, CSV, and JSON formats
  • Authenticated v1 API with Laravel Sanctum for login, profile, and feed
  • Internal CSV regeneration endpoint with authentication and an additional IP restriction
  • Filament panel for products, categories, users, orders, and ERP synchronization operations
  • Availability check for a primary ERP host and a fallback host
  • CLI command for testing ERP connectivity and essential stored procedures
  • Data migration script from the legacy wpke_erp_* schema to the new erp_* schema

Related projects

Want something similar?

Start with the estimate wizard — answer a few questions and get a realistic price range and timeline.