Trendplus is a production-grade backend and analytics pipeline for retail data: a .NET 8 Web API that ingests legacy point-of-sale databases (Access .mdb/.accdb), normalizes transactional and master data, stores it in PostgreSQL and maintains a synchronized Analytics database for reporting.
This README aims to be a single source of truth for developers and operators: quickstart, architecture, Access-import specifics, deployment notes, troubleshooting and developer workflows.
—
- Language & Frameworks: C#, .NET 8, ASP.NET Core Web API
- Persistence: Entity Framework Core (Npgsql) + PostgreSQL;
pgvectorfor vector features - Import: Robust Access importer using
unixODBC+libmdbodbc(mdbtools) with a CLI fallback (mdb-export/mdb-tables) - Patterns: CQRS + MediatR, background HostedServices (Workers), streaming I/O (IAsyncEnumerable)
- Resilience & Observability: Polly retries/circuit-breakers, Serilog (console/file), Swagger, health & perf endpoints
- Messaging & Cache: RabbitMQ broker integration, Redis caching (optional hybrid cache)
- ML Integration: ONNX runtime and optional Python embedding/model services via HTTP
- Container-first: Dockerfile with mdbtools preinstalled for Linux containers
—
Prereqs:
- .NET 8 SDK
- Docker (optional, recommended for parity)
- Node 18+ for frontend dev
Run backend locally (dev environment):
cd Trendplus2
dotnet restore
dotnet build
dotnet run --project Api/Api.csprojFrontend (dev server):
cd Klijent/clientapp
npm install
npm run devRun migrations (from repo root):
dotnet ef database update --project Infrastructure/Infrastructure.csproj --startup-project Api/Api.csproj --context TrendplusDbContext
dotnet ef database update --project Infrastructure/Infrastructure.csproj --startup-project Api/Api.csproj --context AnalyticsDbContext—
appsettings.json/appsettings.Development.json— main configuration values. Key sections:ConnectionStrings:DefaultConnection— Trendplus DBConnectionStrings:AnalyticsConnection— Analytics DBAccessImportOptions— importer tuning (batch size, CLI timeouts, AutoInsertMissingParents)Caching:UseRedis— toggle RedisWorkers:Enabled&Workers:AllowRuntimeToggle— control background workers
Environment variables commonly used in CI / Docker:
ASPNETCORE_ENVIRONMENT—Development/ProductionPORT— server portDOCUMENT_SIGNING_KEY— required in production for document export
—
Problem space:
- Many customers keep POS exports in legacy Access files. On Linux containers, the ODBC driver is brittle and can return inconsistent metadata.
Approach:
- Primary read mode: ODBC via
libmdbodbc(unixODBC). When the provider returns unexpected schema or fails, the importer falls back tomdbtoolsCLI (mdb-tables,mdb-export). - For open/locked ACCDB files we create a timestamped snapshot copy to ensure a consistent read.
- The importer pre-scans parent IDs (e.g.
prodaja_zaglavlje) and either validates or optionally auto-inserts missing parents (AutoInsertMissingParentsflag) to avoid FK violations duringprodaja_stavkeimport. - Large tables are streamed using
IAsyncEnumerable<AccessDataRow>to limit memory and throughput spikes.
Operational tips:
- Docker image includes
mdbtoolsand config forodbcinst.ini— keep image aligned with host distro. - If imports fail with ODBC errors, inspect logs for fallback activation (logger warns) and run
mdb-toolslocally to validate the file.
—
Api/— Web API, DI,AccessImportService, endpointsApplication/— business logic, MediatR handlers, validatorsInfrastructure/— EF DbContexts, repositories, migrations, seedersDomain/— domain entities and value objectsWorkers/— background hosted services: import processor, analytics aggregator, outbox processor, training workersKlijent/clientapp/— React + TypeScript frontend
—
Build and run the container (example):
docker build -t trendplus:latest .
docker run -e ASPNETCORE_ENVIRONMENT=Production -e PORT=8080 -p 8080:8080 trendplus:latestNotes:
- Dockerfile includes
mdbtoolsandunixodbcso Access import works inside container. - Ensure PostgreSQL connection strings point to production DB and that DB migrations have run before enabling workers.
—
- Build:
dotnet build Api/Api.csproj - Tests:
dotnet test Api.Tests/Api.Tests.csproj - Run only importer preview (quick local check): call the API endpoint
POST /api/access-import/previewwith a sample ACCDB path or use the admin UI.
—
- If imports return "Could not find DSN nor DBQ": check
odbcinst.ini,libmdbodbcpresence and allow CLI fallback. - For FK 23503 errors on
prodaja_stavke: enableAccessImportOptions:AutoInsertMissingParentstemporarily or inspect source file rows for parent ids. - To debug heavy DB IO during import: monitor PostgreSQL
pg_stat_activityand lower_options.DbSaveBatchSizeto flush more frequently.
Logs & monitoring:
- Serilog writes console and file sinks. Check API logs for
AccessReadModeandcli-processmessages. - Health & perf endpoints:
/health,/api/performance, and/api/logs.
—
- Follow existing repository conventions (folder layout already in use).
- Use
dotnet formatand run unit tests before opening PRs. Keep changes small and focused; add unit tests for core logic (import heuristics, schema parsing).
—
- Primary maintainer: Ivan Jovičić — email: ivanjovicic1986@gmail.com
—
If you want, I can also:
- Add a short
CONTRIBUTING.mdandSECURITY.md. - Create a markdown snippet explaining how to reproduce import failures locally with
mdbtools. - Commit this README update and push to
main.