A modern, scalable REST API backend for Point of Sales (POS) systems built with Go, PostgreSQL/Supabase, and best practices.
- RESTful API with versioning (
/api/v1/) - JWT Authentication with role-based access control (Admin, Manager, Cashier)
- PostgreSQL/Supabase Database for production-ready persistence
- Rate Limiting per IP address
- Standardized Responses with validation errors
- Docker Ready with multi-stage builds
- Health Checks for monitoring
- Sales Reports (daily, monthly, top products)
- POS Features (transactions, customers, products, categories)
βββ cmd/api/ # Application entry point
βββ internal/
β βββ config/ # Configuration management (Viper)
β βββ database/ # PostgreSQL connection & migrations
β βββ dto/ # Data Transfer Objects
β βββ handler/ # HTTP handlers
β βββ middleware/ # Auth, CORS, Rate Limit, Logger
β βββ models/ # Domain models
β βββ repository/ # Data access layer (PostgreSQL)
β βββ router/ # Route definitions
β βββ service/ # Business logic
β βββ utils/ # Helpers (JWT, Response, Validation)
βββ scripts/ # Database seed script
βββ tests/ # Integration tests
βββ docs/ # API documentation (Swagger)
- Go 1.21 or higher
- PostgreSQL database (Supabase recommended)
- Docker (optional)
-
Create a Supabase Project
- Go to supabase.com and create a new project
- Note your project password (you'll need it)
-
Get Connection String
- Navigate to: Settings β Database β Connection string
- Copy the "Transaction pooler" connection string
- Replace
[YOUR-PASSWORD]with your database password
-
Run Database Migration
- Go to SQL Editor in Supabase dashboard
- Copy contents of
internal/database/migrations/001_init_postgres.sql - Execute the SQL to create all tables
-
Seed Initial Data (Optional)
- Copy contents of
scripts/seed_postgres.sql - Execute in SQL Editor to add test data
- Copy contents of
# Clone repository
git clone <repository-url>
cd goland-dasar
go mod tidy
# Configure environment
cp .env.example .env
# Edit .env and set your DB_CONN (Supabase connection string)
# Run server
make dev
# Or: go run ./cmd/api/main.go
# Test health check
curl http://localhost:8080/health# Build and run
docker-compose up --build
# Stop
docker-compose down| Variable | Description | Default |
|---|---|---|
APP_ENV |
Environment (development/production) | development |
APP_PORT |
Server port | 8080 |
DB_CONN |
PostgreSQL/Supabase connection string | (required) |
JWT_SECRET |
JWT signing secret | (change in production!) |
JWT_EXPIRY_HOURS |
Access token expiry | 24 |
JWT_REFRESH_EXPIRY_HOURS |
Refresh token expiry | 168 (7 days) |
RATE_LIMIT_RPS |
Requests per second limit | 100 |
CORS_ALLOWED_ORIGINS |
Allowed CORS origins | http://localhost:3000 |
APP_ENV=development
APP_PORT=8080
DB_CONN=postgres://postgres.projectid:password@aws-0-region.pooler.supabase.com:6543/postgres?sslmode=require
JWT_SECRET=your-super-secret-jwt-key
CORS_ALLOWED_ORIGINS=http://localhost:3000,http://localhost:5173| Password | Role | |
|---|---|---|
| admin@gopos.local | Admin123! | admin |
| manager@gopos.local | Manager123! | manager |
| cashier@gopos.local | Cashier123! | cashier |
curl -X POST http://localhost:8080/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email": "admin@gopos.local", "password": "Admin123!"}'After login, authentication cookies are automatically sent. For API testing:
curl http://localhost:8080/api/v1/products \
--cookie "access_token=<your-token>"| Method | Endpoint | Description |
|---|---|---|
| GET | /health |
Health check |
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| POST | /api/v1/auth/login |
Login | No |
| POST | /api/v1/auth/register |
Register | No |
| POST | /api/v1/auth/refresh |
Refresh token | No |
| POST | /api/v1/auth/logout |
Logout | No |
| GET | /api/v1/auth/me |
Get current user | Yes |
| PUT | /api/v1/auth/me |
Update profile | Yes |
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /api/v1/categories |
List all | Yes |
| GET | /api/v1/categories/:id |
Get by ID | Yes |
| POST | /api/v1/categories |
Create | Admin/Manager |
| PUT | /api/v1/categories/:id |
Update | Admin/Manager |
| DELETE | /api/v1/categories/:id |
Delete | Admin |
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /api/v1/products |
List all | Yes |
| GET | /api/v1/products/:id |
Get by ID | Yes |
| POST | /api/v1/products |
Create | Admin/Manager |
| PUT | /api/v1/products/:id |
Update | Admin/Manager |
| DELETE | /api/v1/products/:id |
Delete | Admin |
| PATCH | /api/v1/products/:id/stock |
Update stock | Yes |
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /api/v1/customers |
List all | Yes |
| GET | /api/v1/customers/:id |
Get by ID | Yes |
| POST | /api/v1/customers |
Create | Yes |
| PUT | /api/v1/customers/:id |
Update | Yes |
| DELETE | /api/v1/customers/:id |
Delete | Admin/Manager |
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /api/v1/transactions |
List all | Yes |
| GET | /api/v1/transactions/:id |
Get by ID | Yes |
| POST | /api/v1/transactions |
Create sale | Yes |
| PATCH | /api/v1/transactions/:id/status |
Update status | Admin/Manager |
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /api/v1/users |
List all | Admin |
| GET | /api/v1/users/:id |
Get by ID | Admin |
| POST | /api/v1/users |
Create | Admin |
| PUT | /api/v1/users/:id |
Update | Admin |
| DELETE | /api/v1/users/:id |
Delete | Admin |
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /api/v1/reports/sales/daily |
Daily sales | Admin/Manager |
| GET | /api/v1/reports/sales/monthly |
Monthly sales | Admin/Manager |
| GET | /api/v1/reports/products/top |
Top products | Admin/Manager |
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /api/v1/dashboard |
Dashboard summary | Admin/Manager |
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /api/v1/pos/products |
POS product list | Yes |
| POST | /api/v1/pos/checkout |
Checkout | Yes |
| POST | /api/v1/pos/hold |
Hold transaction | Yes |
| GET | /api/v1/pos/held |
Get held items | Yes |
| DELETE | /api/v1/pos/held/:id |
Delete held item | Yes |
{
"success": true,
"message": "Data retrieved successfully",
"data": { ... },
"meta": {
"page": 1,
"per_page": 10,
"total": 100,
"total_pages": 10
}
}{
"success": false,
"message": "Validation failed",
"errors": [{ "field": "email", "message": "Email is required" }]
}# Set up test database (use a separate Supabase project or local PostgreSQL)
export TEST_DB_CONN="postgres://user:pass@host:5432/pos_test?sslmode=disable"
# Run tests
go test -v ./tests/...
# Run specific test
go test -v ./tests/... -run TestAuthLogingo test -cover ./...make help # Show all commands
make dev # Run development server
make build # Build binary
make test # Run tests
make docker-build # Build Docker image
make docker-run # Run with Docker ComposeSwagger documentation is available at:
- Development:
http://localhost:8080/docs/swagger.yaml - See
docs/swagger.yamlfor OpenAPI specification
- Set up Supabase database (see Quick Start section)
- Build the binary:
CGO_ENABLED=0 GOOS=linux go build -o gopos-api ./cmd/api/
- Configure environment on your server
- Run with systemd or container orchestration
APP_ENV=production
APP_PORT=8080
DB_CONN=<your-supabase-connection-string>
JWT_SECRET=<strong-random-secret>
CORS_ALLOWED_ORIGINS=https://your-frontend-domain.comMIT License - see LICENSE for details.