Skip to content
Muslu Yüksektepe

İnşaat iş akışı paneli

A multi-tenant accounting and project panel for construction firms, bringing cash, cheques, bank movements and project costs together.

The Construction Workflow Panel is a management application I built to bring the day-to-day accounting and site work of construction companies into a single web panel. I developed it for Makdos, and it is one of the workflow products Makdos offers to its customers. It keeps a construction company's money and project information in one place, from the cash ledger and cheque tracking to the approval of bank movements and cost analysis per project.

Purpose

In construction companies, money movements are often scattered across spreadsheets, bank statements and separately kept project files. To learn a project's cost per square metre, how much a subcontractor has been paid this year, or which cheques in the portfolio are about to mature, you usually have to put several sources side by side. I designed this panel to bring that information into one consistent record structure and to produce reports from the records themselves instead of preparing them by hand.

Another goal was to make the panel safe to sell to many customers. For that reason it runs as a multi-tenant system in which every customer manages its own firms, users and data in complete isolation from others. The name, logo and main colour shown in the panel come from the installation settings, so each customer uses the panel under its own brand.

How it works

The panel has two main modules. The accounting module handles the cash ledger, cheques, accounts and bank movements. The construction module manages companies, subcontractors, projects and project partnerships. Every user has a role and a set of modules they can access. A viewer can only read, an editor can add and edit records, an admin can delete and manage other users, and the account owner can do everything. I did not stop at hiding these permissions in the interface; every request is also checked on the server.

In the cash ledger every record is a movement into or out of an account. An account's balance is calculated by adding the movements after the opening date to the opening balance. The two legs of a transfer between accounts are linked and are edited or deleted together. When money moves between different currencies, both amounts are entered separately.

For foreign currency transactions I store, on each record, the rate from the last Central Bank of Turkey (TCMB) bulletin published before the transaction date. The bulletin is published in the afternoon and applies to the following day, so this approach keeps the result independent of the time a record happens to be entered. When converting foreign currency to Turkish lira I use the buying rate, in line with tax regulations, and keep the selling rate as well. Assets on hand are converted at the latest bulletin rate, while income and expenses are converted at each record's own transaction rate.

Movements coming from the bank first land on the Pending Transactions screen. There the user can classify a movement and post it to the ledger, match it with an existing ledger record, or ignore it. The panel suggests a classification based on earlier records and on words in the description. Fee lines belonging to the same operation, such as transfer fees and banking tax, are posted together in a single bank charge record. If the ledger record is deleted, or its account or amount changes, the related bank movement goes back to the pending state.

Key features

  • The cash ledger works with filters for account, currency, transfer type and project, and shows the total of all filtered records.
  • Received cheques enter the firm's cheque portfolio account for that currency, and endorsements and collections are recorded as outflows from that portfolio or transfers to another account.
  • The cheque list separately summarises overdue cheques and cheques due within thirty days, and an image of the cheque can be attached to the record.
  • The My Accounts screen shows bank, cash and personal accounts with their balances by currency and type, together with their Turkish lira equivalents.
  • The Pending Transactions screen offers a statement comparison per account, checking the ledger amount plus pending movements against the bank balance.
  • The project detail page shows total income and expenses, cost per square metre, partnership share, the trend over the last twelve months, and breakdowns by category and subcontractor.
  • Partnered projects have a separate partner account, and the partner's share of expenses is calculated from ledger records and offered as a suggestion.
  • Subcontractor records support multiple categories, use the official province and district lists, and validate tax numbers and postcodes.
  • Daily, monthly and yearly reports exclude internal money movements and can be downloaded as CSV.
  • The general report on the home page brings exchange rates, trend indicator cards, a cash flow chart, asset distribution and upcoming cheques together on one screen.

Multi-tenant structure

Because I designed the panel as a product to be sold, I paid particular attention to tenant isolation. The hierarchy runs from Makdos to the customer, the customer's administrators, the construction firm, and finally the firm's departments and members. Each customer is tied to a package that limits how many firms and users it can create. A person can work in several firms with different roles, because roles and module permissions belong to the firm membership rather than to the person.

Instead of leaving data isolation to application code, I enforced it with PostgreSQL row-level security (RLS). RLS is a mechanism that makes the database return only the permitted rows for every query. The connection pool writes the firm of each request into the database session, and a context without a firm cannot see any firm data. If the application's database role has privileges that would let it bypass these rules, the API refuses to start.

Makdos signs in through the same panel but only sees its own menu, which contains customers, packages, administrators, support tickets and invoices. Keeping Makdos away from customers' firm data is a deliberate design decision, because the panel is sold and the data inside it belongs to the customer.

Technical stack

  • I wrote the server side in Go and used the chi library for routing.
  • The database is PostgreSQL; I use pgx for connections and goose migrations embedded in the application for schema changes.
  • Money amounts are stored as numeric in the database, handled with a decimal library in Go and carried as text in JSON, so no rounding errors occur.
  • Name columns use Turkish collation, so the letters I and İ behave correctly in search and sorting.
  • Sessions are kept in HttpOnly cookies, passwords are stored with argon2id, and there is protection against cross-site request forgery.
  • I built the interface with React 19, Vite, TypeScript and Tailwind, using TanStack Query for data fetching and recharts for charts.
  • Every write runs inside a single database transaction, and the audit record is written in the same transaction.
  • Only the compiled program, the built interface and the service configuration are sent to the server; source code never goes there.

Use cases

  • Construction companies running several projects at once that want to track costs per project can use this panel.
  • It suits accounting teams that work with cheques and need to follow the maturity dates of the cheques in their portfolio.
  • It helps firms that want to follow a partner's contributions and share of expenses transparently in partnered projects.
  • Groups that manage several companies or firms from one account can switch between them with the firm selector.

Status

The accounting, construction and settings modules and the multi-tenant structure are complete, and a showcase installation with fictional data is ready for demonstrations. In the next phase I am working on integrations that will pull movements directly from banks; the Pending Transactions screen and the statement comparison are already prepared for them.

Category
Business panels
Year
2026

Technologies

  • Go
  • PostgreSQL
  • React
  • Multitenancy
  • Accounting

Back to all projects