Skip to main content

Data Import Module

Bulk import master data, pricing, and inventory from Excel/CSV files via an asynchronous queue-based pipeline.

Architecture

HTTP upload → FileParserService (xlsx/csv → rows[])
→ DataImportService.createJob() → importJob DB row (status=pending)
→ BullMQ queue ("import-processing")
→ ImportProcessingProcessor (worker)
→ ImportTypeRegistry.get(importType)
→ handler.validate(row)
→ handler.handle(row) → upsert/create entity
→ importRow DB rows (success/error per row)
→ importJob status=completed

Layers (Hexagonal Architecture)

LayerPathResponsibility
Domaindomain/import-repository.domain.tsRepository port (IImportRepository), param types
Applicationapplication/DataImportService (job lifecycle), TemplateGeneratorService, handler registry, 17 import handlers
Infrastructureinfrastructure/ImportRepository (Kysely adapter), FileParserService (Excel/CSV parsing), ImportProcessingProcessor (BullMQ worker)
Interfaceinterfaces/DataImportController (HTTP endpoints), DTOs

Dependency Flow

Controller → DataImportService → IImportRepository (port)
→ FileParserService
→ BullMQ Queue
Processor → IImportRepository (port)
→ ImportTypeRegistry → ImportTypeHandler (per type)

Supported Import Types (17)

TypeHandlerUpsert KeyDependencies
attributeAttributeImportHandlernameAttributes
brandBrandImportHandlernameBrands
categoryCategoryImportHandlernameCategories
colorColorImportHandlernameColors
sizeSizeImportHandlernameSizes
styleStyleImportHandlernameStyles, Brands
modelModelImportHandlernameModels, Brands
productProductImportHandlerskuProducts, Categories, Brands, Colors, Sizes, Styles, Models, Currencies, Taxes, Inventories
product_with_variantsProductWithVariantsImportHandlername+category (product), sku (variant)Products, ProductVariants, Categories, Brands, Currencies, Taxes, Inventories
opening_inventoryOpeningInventoryImportHandlersku+locationProducts, Locations, Inventories, InventoryLedgers
supplierSupplierImportHandlersupplierCode or emailSuppliers
customerCustomerImportHandlercustomerCode or emailCustomers
locationLocationImportHandlernameLocations, Addresses
employeeEmployeeImportHandleremployeeNumber or emailEmployees, Locations, Users
price_listPriceListImportHandlernameBusinessCurrencies
price_list_scopePriceListScopeImportHandlerpriceListId+locationId+channelPriceLists, Locations
price_list_itemPriceListItemImportHandlerpriceListId+itemType+identifierPriceLists, Products

API Endpoints

MethodPathAuthDescription
POST/data-import/uploadBearerUpload file and create import job
GET/data-import/jobsBearerList jobs (paginated, filterable)
GET/data-import/jobs/:idBearerGet job status
GET/data-import/jobs/:id/errorsBearerGet error rows (JSON or CSV)
POST/data-import/previewBearerPreview first 20 mapped rows
GET/data-import/templates/:importTypeBearerDownload Excel template

Key Design Decisions

  1. Handler Registry Pattern — Handlers are registered via NestJS factory provider into a Map<string, ImportTypeHandler>. Adding a new type requires only a handler file, schema entry, and module registration.

  2. Upsert Semantics — All handlers follow find-by-natural-key → update-if-exists → create-if-not. Re-imports are safe and idempotent.

  3. Async Processing — BullMQ with 3 retries and exponential backoff. Row-level idempotency via rowNumber tracking prevents duplicate processing on retry.

  4. Batch Persistence — Row results are flushed to DB every 300 rows to balance memory and write efficiency.

  5. Repository Token DIIMPORT_REPOSITORY Symbol token in domain layer; infrastructure provides the Kysely implementation. Both service and processor depend on the IImportRepository interface, not the concrete class.