Back to projects

// Case study

ASD Contabilidad & Sistemas

A document service connecting the accountant’s work with independent client access.

Node.jsExpressMySQLElectronWindowscPanel
Project video preview.
Who it serves

An accountant and small business clients who need accounting records without relying on someone being physically present at the office.

My responsibility

I designed and built the public site, private portal, API, data model, and Windows application; I documented requirements, decisions, and operations.

Current status

The service is published and the panel installed on the accountant computer; the full journey was checked with synthetic documents.

What it enables

Clients can consult their records while the accountant prepares and publishes them through one workflow.

Context

ASD Contabilidad & Sistemas serves small businesses that need balance sheets, forms, and other records for everyday operations. A request can arrive while the accountant is handling another task or away from the office. Previously, finding the file and replying depended on a manual step.

The product brings together three surfaces for different needs: an institutional website for services and enquiries, a Windows panel for managing clients and publishing documents, and a private portal where each business can consult its own files. An API and database coordinate the journey. This case explains how those pieces connect and why the main decisions were made.

Problem

Access to records depended on finding and sending files manually. Responding meant locating the file, identifying its business, and sending it manually. Beyond the time involved, that process created opportunities for recipient, classification, and tracking mistakes.

Digitizing PDFs alone would not resolve the issue. The accountant needed to distinguish local selection from confirmed publication; a lost network response could leave it unclear whether a file had been saved; and the portal had to prevent one business from downloading another’s documents. The problem combined work organization, operation continuity, and private access.

My role

I designed and built the full journey: requirements, institutional website, client portal, Express API, MySQL model, and Windows application. In the panel I handled search, client creation and editing, batch preparation, and upload states. On the server, the focus was confirming operations and authorizing delivery of the correct document.

I also structured the documentation as a requirements specification, decision register, accountant manual, and deployment guide. That traceability connects each user task to a technical criterion and a check instead of presenting isolated features.

Constraints

The service had to run on managed hosting with a specific Node.js startup mechanism, while the accountant worked on Windows. Publishing the web service and delivering the desktop application were distinct processes: each needed an effective-version check and preservation of working data.

PDFs contain sensitive information. The panel had to fix recipient and type before sending, including when working with long client lists; the API had to check authorization at publication and download. A broken connection could not turn an uncertain result into a second document. Those constraints shaped the local queue, operation receipts, and visible interface states.

Solution

The public site introduces the services and receives enquiries. The Windows panel supports client search and management, creation and editing of client data, status review, and document preparation. Search by name or identifier helps find a business without selecting it automatically. Before upload, the accountant explicitly chooses the client and category and reviews the quantity, filenames, and destination; each PDF may be up to 25 MB and a visible batch is limited to 100 files.

Client management also supports viewing files, updating data, resetting access, and deactivating an account according to its state. Document deletion shows whether the server confirmed the action or whether its result still needs to be checked. These tasks keep account access, the client profile, and the availability of individual files distinct. When access is created or reset, a temporary password is shown only after server confirmation; the accountant delivers it through an authorized channel and the client changes it at first sign-in.

Accepted jobs enter a queue that distinguishes preparation, sending, rejection, and server confirmation. Clients enter the portal, consult the list tied to their accounts, and download the files they need. When a session expires or the network fails, the interface offers the next action suited to that state. The accountant retains control of publication, while each business has its own retrieval path.

Architecture

The institutional website handles commercial contact. The Windows application concentrates accountant tasks, and the private portal serves client retrieval. Both communicate with an Express API. MySQL stores accounts, sessions, document references, and operation results; PDFs remain outside public web content and are delivered through the service.

This separation gives each layer a verifiable responsibility: the panel captures the intent to publish, the API validates and confirms the operation, and the portal presents documents without deciding on its own who may download them. The diagram shows actors and flow; the requirements specification sets the rules for each transition, and the ADRs explain choices the drawing alone cannot convey. Sensitive actions leave an outcome record without placing passwords or documents in that evidence.

ASD Contabilidad & Sistemas document and access flow
ASD Contabilidad & Sistemas document and access flowThe architecture separates public contact, the accountant Windows Electron application, the private web portal, and the Express API that controls MySQL metadata and private PDF streaming.Publish docSession / QueryMetadataPDF streamAudit logVisitorAccountantClientAdministratorPublic websiteReact · SPAElectron applicationWindows · PanelPrivate portalWeb session · Role-basedContact formPublic channelExpress APINode.js · Auth & RoleMySQLPrivate PDFsAudit ledgerASD Contabilidad & Sistemas document and access flowThe architecture separates public contact, the accountant Windows Electron application, the private web portal, and the Express API that controls MySQL metadata and private PDF streaming.VisitorPublic websiteReact · SPAContact formPublic channelAccountantClient / AdminAuthorized usersApp ElectronWindowsPrivate portalWeb sessionExpress APINode.js · Auth & RoleMySQLPrivate PDFsAudit ledger
Read the diagram and its limits

1. Flow reading and initiators: The visitor initiates the public journey through the institutional website and contact form without access to private documents. The accountant initiates publication from the Windows desktop panel (Electron). Clients and administrators initiate authenticated query requests from the private web portal.

2. Components and connections: The Express API mediates all privileged operations. It verifies credentials and roles before querying metadata in MySQL, handles document packaging, streams authorized PDFs located outside the web root, and records operational events into the audit ledger.

3. Groupings and simplifications: On mobile, client and administrator roles are visually grouped because they interact with the same private portal interface under role-specific permissions. Internal Electron packaging and secondary middleware passes are omitted to highlight the security boundary.

4. Implementation and verification state: The Electron desktop app, private portal, Express API, and relational schemas were implemented and verified locally with automated test suites (Vitest, storage doubles, and relational database fixtures).

5. Limits and unverified aspects: The diagram does not prove high-concurrency performance or multi-node production deployment. Unauthenticated direct download URLs do not exist; file streaming strictly requires prior API authentication.

Implementation map. System locally validated with automated test suites and mock storage; unauthenticated direct downloads are blocked by design.

Document pipeline

1. The accountant searches the authorized client list. Filtering helps find the business but does not fill in the recipient automatically. When creating or editing an account, the panel shows fields requiring confirmation and retains the result returned by the server.

2. For publication, the accountant explicitly chooses the client and category, selects PDFs, and reviews a summary with quantity, filenames, and destination. Each queued job retains that choice. Later changes to the filter or selected files do not silently reassign an accepted job.

3. The API checks the operation and PDF, stores the file outside public paths, and records its reference and result. The panel shows confirmed only after receiving server confirmation. Local selection and processing remain separate states.

4. If the response is lost, the panel retains the job and queries its receipt before another upload attempt. The client enters the portal and requests a document; the API checks identity and ownership again, verifies the stored file integrity, and only then delivers the PDF bytes.

Concurrency and interrupted responses

A timeout does not prove an upload failed: the server may have saved the file while only its response was lost. Each job retains an operation identity and a consultable receipt. Retries remain tied to that job and its original recipient; the panel queries the result before deciding whether to send again.

The local queue persists accepted jobs and reconstructs their state when the application reopens. Progress counts jobs confirmed by the server, not selected PDFs or bytes sent. This avoids announcing delivery early. It also separates a definitive rejection from an uncertain result so the accountant knows what action is appropriate. Before serving requests, the server checks that its schema and recoverable state are consistent.

In a controlled check, the response was interrupted after the server saved the receipt. The installed executable recovered the same result with one attempt and without resending the PDF. Isolated database checks also exercised retries and concurrent operations; the public evidence describes the observed scenario.

Decisions

The ADR register preserves the reason for each choice and its cost. This selection prioritizes five decisions that explain the system’s value: selecting the right recipient, recovering an uncertain operation, publishing for the available hosting, updating the panel without losing its profile, and showing clear states to clients.

The order follows the document journey: prevent a mistake before publication, preserve the result after sending, and keep the service operating in its actual environment. Each decision includes a rejected alternative to make the accepted tradeoff explicit.

  1. ADR-014Choose the recipient before publishing

    Problem: A default document type and an unclear destination could turn a routine upload into a misdirected file.

    Decision: The accountant explicitly selects the client and category, then reviews a batch summary before sending.

    Rejected alternative: Keep a default type and rely on the operator to catch the mistake later.

    Tradeoff: One deliberate step reduces classification and recipient mistakes.

  2. ADR-002Keep the result of every operation

    Problem: When an upload response is lost, blindly repeating the request can create a duplicate.

    Decision: A consultable result distinguishes confirmed work from an operation that needs reconciliation.

    Rejected alternative: Assume a timeout proves that the server did not save the file.

    Tradeoff: The workflow must retain and check the operation state before retrying.

  3. ADR-020Deploy for the actual hosting environment

    Problem: Code that runs locally does not become available merely by copying files to managed hosting.

    Decision: Server startup and publication follow the LiteSpeed/Passenger environment and a verified manual procedure.

    Rejected alternative: Treat a file upload or repository update as proof of deployment.

    Tradeoff: Each release needs operational checks instead of assuming the service has started.

  4. ADR-024Control delivery of the Windows application

    Problem: An improvised update could lose the working profile or install a different version from the reviewed one.

    Decision: Delivery identifies a specific version, checks its integrity, and preserves the local profile.

    Rejected alternative: Reinstall from source without preserving the accountant’s working state.

    Tradeoff: Updates require a controlled intervention rather than automatic propagation.

  5. ADR-015Explain client-facing states

    Problem: A network outage and an expired session require different actions even though both interrupt document access.

    Decision: The portal shows the relevant state and offers a retry or a new sign-in.

    Rejected alternative: Use one generic message or always send clients back to sign-in.

    Tradeoff: The interface handles more states to avoid misleading success or error messages.

Security

Commercial content, accountant tasks, and client documents follow separate paths. The portal uses a session that the server revalidates; the Windows application has its own authorization. The API checks identity, account state, and document ownership before every file delivery, even when the browser already displays a link.

Explicit recipient selection helps prevent an operational mistake, while the server check protects later retrieval. PDFs stay outside public web paths, pass structural validation before acceptance, and are checked against their integrity reference before download. Client creation validates identifier format and input data without treating a format check as proof of real-world ownership.

On the published service, two synthetic accounts downloaded their own documents and were denied the other account’s files without receiving PDF bytes. This page explains the behavior and evidence without exposing credentials, client data, internal parameters, or bypass instructions.

Testing

Documented component runs record 32 backend suites with 409 passing checks and one skipped; 180 of 180 Windows application checks; and 47 of 47 web frontend checks. These are separate runs. They cover identity and PDF validation, recipient selection, permissions, sessions, portal states, the local queue, and operation receipts. The requirements specification connects those checks to concrete accountant and client tasks.

Integration checks with isolated databases and synthetic files examined uploads, retries, and authorization alongside the component suites. On the published service, two test accounts downloaded their own documents and were denied access to the other account’s document without receiving PDF bytes. Another controlled check interrupted the response after an upload was saved: the same installed executable queried its receipt, recovered the result, and retained a single attempt.

On the accountant’s computer, a synthetic PDF was selected through the native picker, confirmed by the server, and downloaded from the portal with bytes identical to the original. The panel retained its access and job after closing and reopening. The public website also confirmed a synthetic enquiry received by the selected mailbox. The table separates automated results from observed journeys and states what each one establishes.

Results and scope of the checks
CheckResultScope
Automated backend suite32 suites · 409 passed · 1 skippedJest checks for identity, access, documents, receipts, and recovery. This count belongs to the documented backend run.
Automated Windows panel suite180/180 passedRegression checks for client and type selection, local queue, retries, states, and communication between the interface and main process.
Automated web frontend suite47/47 passedPortal and console behavior: sessions, visible states, errors, and navigation after a password change.
Database integrationFull journeys passed on isolated MySQL and MariaDBSynthetic data and files for authorization, uploads, receipts, retries, and recovery; runs separate from the component suites.
PDF validation and integrityInvalid files rejected; valid PDF preserved intactSynthetic files cover structure, truncation, and encryption; authorized download checks the stored file before sending bytes.
Installer delivery18/18 integrity · 12/12 build · 2/2 on WindowsPackage and Windows filesystem behavior. These suites simulate download and installation; actual installation was checked separately.
Cross-client isolationOwn document accessible; cross-access rejectedTwo synthetic accounts on the published service: intact own download and rejection of the other account without PDF bytes.
Interrupted responseOne job recovered without resending the PDFThe response was lost after saving the receipt; the installed panel queried the same result and retained a single attempt.
Accountant’s computer journeyUpload, download, and reopening completedSynthetic PDF chosen in the native picker; server confirmation, downloaded file identical to the original, and preserved profile after reopening.
Public contactSubmission and receipt observedSynthetic enquiry from the public website, visible confirmation, and receipt in the selected mailbox.

Deployment

The backend and portal are published manually on managed hosting, following its actual Node.js startup behavior. The procedure prepares a package of permitted source files, preserves operational data, and checks over HTTPS that the active version serves the website, portal, and API. Updating the repository and publishing the running service are separate steps.

The Windows application is built and distributed as an installer with a specific version and verified integrity. Installation preserves the access profile and job queue; updates follow a controlled delivery rather than assuming the program updates itself. The guide explains preparation, installation, checks, and recovery with the operator’s responsibilities.

Delivery was observed first on a validation computer and then on the accountant’s computer. There, a synthetic PDF was chosen through the native picker, confirmed by the server, downloaded from the portal, and followed by reopening the panel with its connection and job intact. That sequence links the deployment procedure to the installed application’s use.

Outcome

The result connects three surfaces in one service: contact website, work panel, and client portal. The accountant can find a business, manage its access, prepare documents, and distinguish a confirmed upload from an operation requiring a result check. Each client has a place to find and download its own records.

The project documents five priority decisions and separate automated runs with 409 passing backend checks, 180 panel checks, and 47 web frontend checks. Two synthetic accounts demonstrated isolation; an interrupted response was resolved with one attempt; and the accountant’s computer journey ended with a downloaded PDF identical to its source. These figures describe verified product behavior.

Qualitatively, the documented change is a move from manually finding and sending files to preparing publication in the panel and enabling private client access. The observed journey on the Windows computer connects that change to a confirmed upload and an intact portal download.

Evidence

This case draws on five project sources: the README for the system map, SRS for requirements, ADRs for decisions, the accountant manual for visible states, and the deployment guide for operation. Code and documented suite runs support the described mechanisms.

Operational evidence includes own-document downloads and cross-account rejection with synthetic accounts, recovery from a lost response, and an intact upload and download from the accountant’s computer. The downloaded file was compared with the original synthetic PDF; a visible link or receipt alone is not presented as a completed download. The video shows the interface. Detailed operational records and client data stay outside this public page.

Documentation behind the decisions

Selected sources show how the project moves from needs to architecture, use and operation.

README.md
Introduces the product, its actors, and the route between the public site, Windows panel, portal, and API.A starting point before the technical decisions.
docs/SRS.md
Turns client, accountant, and operational needs into verifiable requirements.Defines what each flow must do and how it is accepted.
docs/ADR.md
Records the problem, selected alternative, and consequences of significant decisions.The five decisions on this page are a prioritized selection.
docs/DEPLOY.md
Explains manual publication and operation of the service and Windows application.Connects the design to its actual environment.
docs/MANUAL_USUARIO_CONTADOR.md
Describes accountant tasks and visible states while preparing documents.Adds the user perspective to the architecture.

Software quality and UX

The quality of the flow starts before clicking Upload: filtering by name or identifier helps find a business without choosing it automatically; recipient and type are selected explicitly; and the batch summary lets the accountant check both alongside the PDF count. The visible 100-file limit helps divide a large batch without hiding drafts.

The queue communicates states with different consequences. Selecting a PDF does not advance progress: only a server-confirmed job does. If a response is lost, its context is retained so the same receipt can be queried. When a client edit has an uncertain result, the panel compares current data with the proposal before saving again.

The portal distinguishes an empty list, an expired session, and a network failure, offering the appropriate action for each. On the public site, the contact form confirms submission and its controls support keyboard use with visible focus. Authorization is checked again at download time. The example below isolates search normalization that helps find a recipient without making the accountant’s selection for them.

Code sample and engineering test

A self-contained public example of the panel search rule: it normalizes accents and identifier formatting to help locate a recipient. A match only helps find the business; it neither selects it automatically nor grants permission to publish.

The check uses fictitious data and covers a name match, an identifier match, and no match. It does not reproduce authentication, private routes, or real data.

JavaScript / Node.js
function normalizeClientSearch(value) {
return String(value || '').normalize('NFD')
.replace(/[\u0300-\u036f]/g, '')
.toLocaleLowerCase('es-CL').trim();
}
function clientMatchesSearch(client, query) {
const search = normalizeClientSearch(query);
if (!search) return true;
const name = normalizeClientSearch(client?.name);
const identifier = normalizeClientSearch(client?.identifier);
const compactSearch = search.replace(/[^0-9k]/g, '');
return name.includes(search) || Boolean(/^[0-9k.\-\s]+$/i.test(search) && compactSearch && identifier.replace(/[^0-9k]/g, '').includes(compactSearch));
}

Isolated sample test

JavaScript / Node.js
import assert from 'node:assert/strict';
const client = { name: 'Empresa Demostración', identifier: '00.000.000-0' };
assert.equal(clientMatchesSearch(client, 'demostracion'), true);
assert.equal(clientMatchesSearch(client, '000000000'), true);
assert.equal(clientMatchesSearch(client, 'otra empresa'), false);

The example shows name and identifier matches plus a nonmatching search.