# Open Accounting Server

Open Accounting Server is a modern financial accounting system built with Go, featuring GORM integration, Viper configuration management, and Docker support.

## Features

- **GORM Integration**: Modern ORM with SQLite and MySQL support
- **Viper Configuration**: Flexible config management with environment variables
- **Docker Ready**: Containerized deployment with multi-stage builds
- **SQLite Support**: Easy local development and testing
- **Security**: Environment variable support for sensitive data

## Prerequisites

- **Go 1.24+** (updated from 1.8+)
- **SQLite** (for development) or **MySQL 5.7+** (for production)
- **Docker** (optional, for containerized deployment)
- **Just** (optional, for build automation)

## Quick Start

### Using Just (Recommended)

```bash
# Setup development environment
just dev-setup

# Run in development mode
just run-dev

# Build and run with Docker
just docker-run
```

### Manual Setup

```bash
# Install dependencies
go mod download

# Run with SQLite (development)
OA_DATABASE_DRIVER=sqlite ./server

# Run with MySQL (production)
OA_DATABASE_DRIVER=mysql OA_PASSWORD=secret ./server
```

## Configuration

The server now uses **Viper** for advanced configuration management with multiple sources:

### Configuration Sources (in order of precedence)

1. **Environment Variables** (highest priority)
2. **Config Files**: `config.json`, `config.yaml`, `config.toml`
3. **Default Values** (lowest priority)

### Config File Locations

- `./config.json` (current directory)
- `/etc/openaccounting/config.json`
- `~/.openaccounting/config.json`

### Environment Variables

All configuration can be overridden with environment variables using the `OA_` prefix:

| Environment Variable | Config Field | Default | Description |
|---------------------|--------------|---------|-------------|
| `OA_ADDRESS` | Address | `localhost` | Server bind address |
| `OA_PORT` | Port | `8080` | Server port |
| `OA_API_PREFIX` | ApiPrefix | `/api/v1` | API route prefix |
| `OA_DATABASE_DRIVER` | DatabaseDriver | `sqlite` | Database type: `sqlite` or `mysql` |
| `OA_DATABASE_FILE` | DatabaseFile | `./openaccounting.db` | SQLite database file |
| `OA_DATABASE_ADDRESS` | DatabaseAddress | `localhost:3306` | MySQL server address |
| `OA_DATABASE` | Database | | MySQL database name |
| `OA_USER` | User | | Database username |
| `OA_PASSWORD` | Password | | Database password ⚠️ |
| `OA_MAILGUN_DOMAIN` | MailgunDomain | | Mailgun domain |
| `OA_MAILGUN_KEY` | MailgunKey | | Mailgun API key ⚠️ |
| `OA_MAILGUN_EMAIL` | MailgunEmail | | Mailgun email |
| `OA_MAILGUN_SENDER` | MailgunSender | | Mailgun sender name |

⚠️ **Security**: Always use environment variables for sensitive data like passwords and API keys.

### Configuration Examples

#### Development (SQLite)
```bash
# Minimal - uses defaults
./server

# Custom database file and port
OA_DATABASE_FILE=./dev.db OA_PORT=9090 ./server
```

#### Production (MySQL)
```bash
# With environment variables (recommended)
export OA_DATABASE_DRIVER=mysql
export OA_DATABASE_ADDRESS=db.example.com:3306
export OA_DATABASE=openaccounting_prod
export OA_USER=openaccounting
export OA_PASSWORD=secure_password
export OA_MAILGUN_KEY=key-abc123
./server

# Or inline
OA_DATABASE_DRIVER=mysql OA_PASSWORD=secret OA_MAILGUN_KEY=key-123 ./server
```

#### Docker
```bash
# SQLite with volume mount
docker run -p 8080:8080 \
  -e OA_DATABASE_DRIVER=sqlite \
  -v ./data:/app/data \
  openaccounting-server:latest

# MySQL with environment variables
docker run -p 8080:8080 \
  -e OA_DATABASE_DRIVER=mysql \
  -e OA_DATABASE_ADDRESS=mysql:3306 \
  -e OA_PASSWORD=secret \
  openaccounting-server:latest
```

## Database Setup

### SQLite (Development)

SQLite databases are created automatically. No manual setup required.

```bash
# Uses ./openaccounting.db by default
OA_DATABASE_DRIVER=sqlite ./server

# Custom location
OA_DATABASE_DRIVER=sqlite OA_DATABASE_FILE=./data/myapp.db ./server
```

### MySQL (Production)

Use the provided schema files to create your MySQL database:

```sql
-- Create database and user
CREATE DATABASE openaccounting;
CREATE USER 'openaccounting'@'%' IDENTIFIED BY 'secure_password';
GRANT ALL PRIVILEGES ON openaccounting.* TO 'openaccounting'@'%';
```

The server will automatically create tables and run migrations on startup.

## Building

### Local Build

```bash
# Development build
go build -o server ./core/

# Production build (optimized)
CGO_ENABLED=1 GOOS=linux go build -a -installsuffix cgo -ldflags="-w -s" -o server ./core/
```

### Docker Build

```bash
# Build image
docker build -t openaccounting-server:latest .

# Multi-platform build
docker buildx build --platform linux/amd64,linux/arm64 -t openaccounting-server:latest .
```

## Running

### Development

```bash
# Local with SQLite
just run-dev

# Or manually
OA_DATABASE_DRIVER=sqlite OA_PORT=8080 ./server
```

### Production

```bash
# With Docker Compose (recommended)
docker-compose up -d

# Or manually with environment file
export $(cat .env | xargs)
./server
```

## Just Recipes

This project includes a `justfile` with common tasks:

```bash
just --list                 # Show all available recipes
just build                  # Build the application
just run-dev                # Run in development mode
just docker-build           # Build Docker image
just docker-run             # Run container
just test                   # Run tests
just config-help            # Show configuration help
just dev-setup              # Complete development setup
```

## API

The server provides a REST API at `/api/v1/` (configurable via `OA_API_PREFIX`).

### Health Check

```bash
curl http://localhost:8080/api/v1/health
```

## Development

### Prerequisites

```bash
# Install Go dependencies
go mod download

# Install development tools (optional)
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
```

### Running Tests

```bash
just test
# or
go test ./...
```

### Code Quality

```bash
# Format code
just fmt

# Lint code (requires golangci-lint)
just lint
```

## Docker

### Official Images

Docker images are available with multi-stage builds for optimal size and security:

- Non-root user for security
- Alpine Linux base for minimal attack surface
- Health checks included
- Volume support for data persistence

### Environment Variables in Docker

```dockerfile
ENV OA_DATABASE_DRIVER=sqlite \
    OA_DATABASE_FILE=/app/data/openaccounting.db \
    OA_ADDRESS=0.0.0.0 \
    OA_PORT=8080
```

### Data Persistence

```bash
# Mount volume for SQLite data
docker run -v ./data:/app/data openaccounting-server:latest

# Use named volume
docker volume create openaccounting-data
docker run -v openaccounting-data:/app/data openaccounting-server:latest
```

## Deployment

### Docker Compose

```yaml
version: '3.8'
services:
  openaccounting:
    image: openaccounting-server:latest
    ports:
      - "8080:8080"
    environment:
      OA_DATABASE_DRIVER: mysql
      OA_DATABASE_ADDRESS: mysql:3306
      OA_DATABASE: openaccounting
      OA_USER: openaccounting
      OA_PASSWORD: ${DB_PASSWORD}
    depends_on:
      - mysql
  
  mysql:
    image: mysql:8.0
    environment:
      MYSQL_DATABASE: openaccounting
      MYSQL_USER: openaccounting
      MYSQL_PASSWORD: ${DB_PASSWORD}
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
    volumes:
      - mysql_data:/var/lib/mysql

volumes:
  mysql_data:
```

### Kubernetes

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: openaccounting-server
spec:
  replicas: 3
  selector:
    matchLabels:
      app: openaccounting-server
  template:
    metadata:
      labels:
        app: openaccounting-server
    spec:
      containers:
      - name: openaccounting-server
        image: openaccounting-server:latest
        ports:
        - containerPort: 8080
        env:
        - name: OA_DATABASE_DRIVER
          value: "mysql"
        - name: OA_PASSWORD
          valueFrom:
            secretKeyRef:
              name: openaccounting-secrets
              key: db-password
```

## Troubleshooting

### Common Issues

1. **Config file not found**: The server will use environment variables and defaults if no config file is found
2. **Database connection failed**: Check your database credentials and connectivity
3. **Permission denied**: Ensure proper file permissions for SQLite database files

### Debug Mode

```bash
# Enable verbose logging
OA_LOG_LEVEL=debug ./server

# Check configuration
just config-help
```

### Health Checks

```bash
# Application health
curl http://localhost:8080/api/v1/health

# Docker health check
docker inspect --format='{{.State.Health.Status}}' container_name
```

## Migration from Legacy Setup

The server maintains backward compatibility with existing `config.json` files while adding Viper features:

1. Existing `config.json` files continue to work
2. Add environment variables for sensitive data
3. Use SQLite for easier local development
4. Leverage Docker for production deployments

## Help & Support

- **Documentation**: This README and inline code comments
- **Issues**: GitHub Issues for bug reports and feature requests
- **Community**: [Join our Slack chatroom](https://join.slack.com/t/openaccounting/shared_invite/zt-23zy988e8-93HP1GfLDB7osoQ6umpfiA)

## License

See LICENSE file for details.