A RESTful API for managing customer accounts and transactions, built with Go, PostgreSQL, and Docker.
- Overview
- Features
- Tech Stack
- Project Structure
- Prerequisites
- Getting Started
- API Documentation
- Testing
- Architecture
This project implements a banking system for managing customer accounts and transactions. Transactions are stored following event sourcing principles, where:
- Debit transactions (Purchase, Installment Purchase, Withdrawal) are stored with negative amounts
- Credit transactions (Payment) are stored with positive amounts
- Language: Go 1.24
- Web Framework: Gin
- Database: PostgreSQL 15
- Database Library: sqlx
- Documentation: Swagger (swaggo)
- Testing: testify, go-sqlmock
- Containerization: Docker & Docker Compose
.
├── cmd/api/ # Application entry point
├── internal/
│ ├── api/
│ │ ├── dto/ # Data Transfer Objects
│ │ ├── handlers/ # HTTP handlers
│ │ └── router/ # Route definitions
│ ├── config/ # Configuration management
│ ├── database/ # Database connection and migrations
│ ├── domain/models/ # Domain models
│ ├── repository/ # Data access layer
│ └── service/ # Business logic layer
├── tests/
│ ├── integration/ # Integration tests
│ ├── unit/ # Unit tests
│ └── mocks/ # Auto-generated mocks
├── docs/ # Swagger documentation
├── deployments/ # Docker Compose configuration
└── Makefile # Build and run commands
- Docker and Docker Compose
- Go 1.24+ (to run the application locally and also to run tests)
- PostgreSQL 15+
- Make (optional, for using Makefile commands)
-
Clone the repository
git clone https://github.com/thsfranca/code_assessment.git cd code_assessment -
Start the application
make docker-run
This will:
- Build the Docker image
- Start PostgreSQL database
- Run database migrations
- Start the application on port 8080
-
Access the application
- API: http://localhost:8080
- Swagger UI: http://localhost:8080/swagger/index.html
-
View logs
make logs
-
Stop the application
make docker-down
-
Start PostgreSQL database only
make docker-db-up
-
Run the application
make run
The application will start on http://localhost:8080
make help # Show all available commands
make docker-db-up # Start PostgreSQL container only
make docker-run # Run full stack in Docker
make docker-down # Stop all containers
make run # Run application locally
make logs # Show application logs
make swagger # Generate Swagger documentation
make mocks # Generate test mocks
make test-unit # Run unit tests only
make test-integration # Run integration tests only
make test-all # Run all tests
make clean # Clean up containers and volumesAccess the interactive API documentation at:
http://localhost:8080/swagger/index.html
POST /accounts
Content-Type: application/json
{
"document_number": "12345678900"
}
Response: 201 Created
{
"account_id": 1,
"document_number": "12345678900"
}GET /accounts/:accountId
Response: 200 OK
{
"account_id": 1,
"document_number": "12345678900"
}POST /transactions
Content-Type: application/json
{
"account_id": 1,
"operation_type_id": 4,
"amount": 123.45
}
Response: 201 Created
{
"transaction_id": 1,
"account_id": 1,
"operation_type_id": 4,
"amount": 123.45
}| ID | Description | Amount Sign |
|---|---|---|
| 1 | PURCHASE | Negative |
| 2 | INSTALLMENT PURCHASE | Negative |
| 3 | WITHDRAWAL | Negative |
| 4 | PAYMENT | Positive |
Note: The system automatically adjusts the amount sign based on the operation type, so you can send positive values for all operations.
make test-allmake test-unitmake test-integrationThe project includes comprehensive test coverage:
- Unit Tests: Service layer, Repository layer (with sqlmock)
- Integration Tests: Handler layer with full request/response cycle
-
Handlers (
internal/api/handlers/)- HTTP request/response handling
- Input validation
- Error mapping
-
Services (
internal/service/)- Business logic
- Domain rules enforcement
- Transaction coordination
-
Repositories (
internal/repository/)- Data access abstraction
- SQL query execution
- Data mapping
-
Domain Models (
internal/domain/models/)- Core business entities
- Domain logic (e.g., operation type rules)
- Dependency Inversion: Services depend on repository interfaces, not implementations
- Event Sourcing: Transactions are immutable (enforced with PostgreSQL rules)
- Enum for Operation Types: Stored in code for type safety, documented in ADR
- Centralized Error Handling: Consistent error responses with proper HTTP status codes
See docs/adr/ for detailed documentation of key architectural decisions:
- Database choice (PostgreSQL)
- Operation type implementation (enum vs table)
- Web framework selection (Gin)
- Database library (sqlx)
- API documentation approach (swaggo)
The application uses environment variables with sensible defaults:
| Variable | Default | Description |
|---|---|---|
| SERVER_PORT | 8080 | HTTP server port |
| SERVER_ENV | development | Environment (dev/prod) |
| DB_HOST | localhost | PostgreSQL host |
| DB_PORT | 5432 | PostgreSQL port |
| DB_USER | postgres | Database user |
| DB_PASSWORD | postgres | Database password |
| DB_NAME | accounts_db | Database name |
| DB_SSLMODE | disable | PostgreSQL SSL mode |
| DB_MAX_OPEN_CONNS | 25 | Maximum open database connections |
| DB_MAX_IDLE_CONNS | 5 | Maximum idle database connections |
| DB_CONN_MAX_LIFETIME | 5m | Connection maximum lifetime (e.g., 5m, 1h) |
Note: No .env file is required. The application works with defaults for local development.