AppTech — Plataforma de Gestão
A satellite platform unifying sales, receivables, tax, legal and HR for a construction company.
- processes in the historical pipeline
- ~2,7M
- permission-controlled modules
- 13
- incremental ETL pipelines
- 20+
From pain to result
Before
Dozens of spreadsheets and manual ERP lookups. Each department kept its own copy of the numbers, often out of date.
Operations relied on dozens of spreadsheets and manual queries against the UAU ERP (SQL Server) and TOTVS RM (payroll). Sales closings, bank reconciliation, tax and legal work took hours and were error-prone.
There was no single trustworthy view: each department kept its own copy of the numbers, often out of date.
And every new request from a department turned into yet another spreadsheet or another isolated little system — multiplying logins, diverging databases and maintenance.
How · 1/5
I built a Flask + React application with its own PostgreSQL database, fed by more than twenty ETL pipelines that incrementally extract from UAU, TOTVS RM and spreadsheets — with watermarks, natural-key UPSERTs and resilience to replica RESTOREs.
How · 2/5
On top of that data, I delivered 13 permission-controlled modules — Sales, Receivables, Administrative Area, Bank Reconciliation, Tax/Accounting, Legal, HR/Payroll, Protests, Innovation Centre, Users, among others. The larger ones branch out: HR holds eleven sub-modules and Tax, eight.
How · 3/5
The architectural decision behind it: every new tool ships as a module of AppTech, never as a separate application. Each department gets its own dashboard grouping what it needs, while the database, authentication and deployment stay single.
How · 4/5
The legal system, born as a separate application, was the test of that rule: I migrated it into AppTech as a module — court cases, cost allocations across projects, law-firm payments and monitored companies —, brought its history over checked 1:1 (197 allocations, 3,340 items) and shut the legacy down.
How · 5/5
Everything is packaged in Docker and served in production via Docker Swarm + Traefik, with rolling deploys and healthchecks.
After
A single platform around the ERP: sales, finance, tax, legal and HR in 13 modules, one database and one login. A new request becomes a module, not another spreadsheet.
- ~2,7M
- processes in the historical pipeline
- 13
- permission-controlled modules
- 20+
- incremental ETL pipelines
Reading the diagram
More than twenty incremental pipelines consolidate the source systems into Postgres; on top of it, thirteen modules and the outputs operations actually use — including legal filings back into the ERP. Payroll comes in over a VPN, opened only during extraction. Drawing a single Postgres is a simplification: it stands for AppTech’s own database plus the legal database it reads and enriches.
Technical highlights
- 1 Historical pipeline of ~2.7 million payment processes since 2014. The first load is year-sliced and resumable — at that volume, a job that must restart from zero on every failure never finishes. After that, incremental sliding-window only.
- 2 Tax ETL resilient to SQL Server replica RESTOREs: the replica is periodically restored, which would invalidate any position tracking. A watermark plus natural-key UPSERT let the load recover on its own instead of duplicating or dropping rows.
- 3 Payroll lives behind a VPN. The TOTVS RM ETL opens the tunnel only during extraction and closes it right after, via a context manager — the exposure window is the query duration, not the application uptime.
- 4 Legal filing into the ERP as a sequence of steps — create the process, attach the document, comment — run as an asynchronous queue: progress lives on the row itself, with a heartbeat, and an item stuck halfway is detected and released for retry. Once the process exists in the ERP, the allocation locks: the system refuses the edit rather than let the database diverge from the ERP.
- 5 Legal-case enrichment across public databases and one paid source, with sliding-window rate limiting and cost control: before every metered query the robot checks the balance and stops on its own when it hits the reserve floor. The city comes from matching the court with the official municipality registry.
- 6 WhatsApp notification with verified delivery: the API reported success and the message simply never arrived, due to a mismatch in the recipient identifier. I now confirm the valid identifier before sending, with caching and safe degradation.
- 7 Third-party spreadsheet generation that preserves macros, images and vectors — which any writer library destroys when it saves the file.
- 8 Docker Swarm deployment with Traefik, per-request internal DNS resolution in Nginx — without it the proxy breaks whenever the backend has not come up yet — and a healthcheck with a start grace period so a container that is merely booting is not killed.