313 lines
7.1 KiB
Markdown
313 lines
7.1 KiB
Markdown
# ZynkTime
|
|
|
|
A time reporting application for the Kleer API with both FastAPI web interface and CLI.
|
|
|
|
## Features
|
|
|
|
- 🎨 **Modern Web UI**: Beautiful, responsive web interface with drag-and-drop file upload
|
|
- 📊 **CSV Processing**: Parse and extract work time from CSV files
|
|
- 🌐 **REST API**: FastAPI endpoints for time reporting
|
|
- 💻 **CLI Interface**: Interactive command-line time reporting
|
|
- ✅ **Input Validation**: Pydantic models for data validation
|
|
- 🧪 **Tested**: Unit tests with pytest
|
|
- 📝 **Well-Documented**: Comprehensive docstrings and type hints
|
|
|
|
## Quick Start
|
|
|
|
### 🐳 Docker (Recommended)
|
|
|
|
The easiest way to run ZynkTime is with Docker:
|
|
|
|
```bash
|
|
# 1. Clone the repository
|
|
cd zynktime
|
|
|
|
# 2. Copy environment file
|
|
cp .env.example .env
|
|
|
|
# 3. Edit .env and add your API key
|
|
nano .env # or use your favorite editor
|
|
|
|
# 4. Start with Docker Compose
|
|
docker-compose up -d
|
|
|
|
# 5. Open your browser
|
|
# Navigate to: http://localhost:8000
|
|
```
|
|
|
|
**Docker Commands:**
|
|
```bash
|
|
# Start the application
|
|
docker-compose up -d
|
|
|
|
# View logs
|
|
docker-compose logs -f
|
|
|
|
# Stop the application
|
|
docker-compose down
|
|
|
|
# Rebuild after code changes
|
|
docker-compose up -d --build
|
|
|
|
# Access container shell
|
|
docker-compose exec zynktime bash
|
|
```
|
|
|
|
### 🐍 Manual Installation
|
|
|
|
If you prefer to run without Docker:
|
|
|
|
```bash
|
|
# Clone the repository
|
|
cd zynktime
|
|
|
|
# Create virtual environment
|
|
python -m venv venv
|
|
source venv/bin/activate # On Windows: venv\Scripts\activate
|
|
|
|
# Install dependencies
|
|
pip install -r requirements.txt
|
|
```
|
|
|
|
### Configuration
|
|
|
|
**Option 1: Environment File (Recommended)**
|
|
```bash
|
|
# Copy example file
|
|
cp .env.example .env
|
|
|
|
# Edit with your values
|
|
nano .env
|
|
```
|
|
|
|
**Option 2: Export Variables**
|
|
```bash
|
|
export KLEER_API_KEY="your_api_key_here"
|
|
export KLEER_USERNAME="Your Name" # Optional, defaults to "Christopher Juhlin"
|
|
export KLEER_COMPANY_ID="1336" # Optional, defaults to "1336"
|
|
```
|
|
|
|
### Running the Application
|
|
|
|
**Web UI Mode (Recommended):**
|
|
```bash
|
|
python main.py
|
|
# Open your browser and navigate to: http://localhost:8000
|
|
```
|
|
|
|
**CLI Mode:**
|
|
```bash
|
|
python main.py cli
|
|
# Interactive CLI for processing CSV files
|
|
```
|
|
|
|
### Using the Web UI
|
|
|
|
1. **Open your browser** to `http://localhost:8000`
|
|
2. **Upload your CSV file** by dragging and dropping or clicking to browse
|
|
3. **Select a project** from the dropdown
|
|
4. **Click "Report Time"** to submit
|
|
5. View the **results summary** with total hours and days reported
|
|
|
|
The web interface features:
|
|
- 🎯 Drag-and-drop file upload
|
|
- 📋 Real-time project list
|
|
- 💫 Smooth animations and transitions
|
|
- 📱 Fully responsive design
|
|
- 🔔 Toast notifications for feedback
|
|
- ✅ Connection status indicator
|
|
|
|
## API Endpoints
|
|
|
|
### GET /
|
|
Serves the modern web UI interface.
|
|
|
|
### GET /api
|
|
Returns API information and available endpoints.
|
|
|
|
### GET /health
|
|
Health check endpoint - verifies API key configuration.
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"status": "healthy",
|
|
"api_key_configured": true
|
|
}
|
|
```
|
|
|
|
### GET /projects
|
|
Lists all active projects for the configured user.
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"Project Name": {
|
|
"id": 123,
|
|
"activity": {"id": 456}
|
|
}
|
|
}
|
|
```
|
|
|
|
### POST /report-time
|
|
Upload a CSV file and report time to a specific project.
|
|
|
|
**Parameters:**
|
|
- `project_name` (query): Name of the project
|
|
- `file` (form): CSV file with time entries
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"message": "Time reported successfully.",
|
|
"reported_days": 5,
|
|
"total_hours": 40.0,
|
|
"project_name": "Project Name",
|
|
"user_name": "Your Name"
|
|
}
|
|
```
|
|
|
|
### GET /docs
|
|
Interactive API documentation (Swagger UI).
|
|
|
|
## CSV Format
|
|
|
|
The application **automatically detects** the CSV delimiter (comma or semicolon) and column structure.
|
|
|
|
### Supported Formats
|
|
|
|
**Format 1: Comma-separated with headers**
|
|
```csv
|
|
reg_period,xreg_period,T,Time code,Time code (T),Vouch.date,Project Activity,Project Activity (T),Work package,Work package (T),Hours,Workflow status,Text
|
|
202544,,A,0,Standard Time,10/27/2025,,,,,2.00,N,
|
|
202544,,A,0,Standard Time,10/28/2025,,,,,4.00,N,
|
|
```
|
|
|
|
**Format 2: Semicolon-separated**
|
|
```csv
|
|
...;...;...;...;...;01/15/2024;...;...;...;...;8.5;...
|
|
...;...;...;...;...;01/16/2024;...;...;...;...;7,5;...
|
|
```
|
|
|
|
### Column Detection
|
|
|
|
- **Date column**: Automatically detected by searching for columns containing "date" or "vouch" in the header
|
|
- **Hours column**: Automatically detected by searching for columns containing "hour" in the header
|
|
- **Date formats**: Supports both `MM/DD/YYYY` and `YYYY-MM-DD`
|
|
- **Hours format**: Supports decimal hours with comma (`,`) or dot (`.`) as separator
|
|
- **Whitespace**: Automatically trimmed from values
|
|
|
|
## Development
|
|
|
|
### Project Structure
|
|
|
|
```
|
|
zynktime/
|
|
├── static/
|
|
│ ├── index.html # Modern web UI
|
|
│ ├── css/
|
|
│ │ └── style.css # Responsive styling
|
|
│ └── js/
|
|
│ └── app.js # Frontend logic
|
|
├── main.py # FastAPI application entry point
|
|
├── cli.py # CLI interface
|
|
├── config.py # Configuration management
|
|
├── models.py # Pydantic models
|
|
├── api_client.py # Kleer API client
|
|
├── services.py # Business logic
|
|
├── test_main.py # Unit tests
|
|
├── requirements.txt # Python dependencies
|
|
├── AGENTS.md # Guidelines for AI agents
|
|
└── README.md # This file
|
|
```
|
|
|
|
### Running Tests
|
|
|
|
```bash
|
|
# Run all tests
|
|
pytest
|
|
|
|
# Run with verbose output
|
|
pytest -v
|
|
|
|
# Run specific test
|
|
pytest test_main.py::TestServices::test_validate_date_valid -v
|
|
|
|
# Run with coverage
|
|
pytest --cov=. --cov-report=html
|
|
```
|
|
|
|
### Code Quality
|
|
|
|
The codebase follows:
|
|
- **Type hints**: Full typing support
|
|
- **Error handling**: Specific exceptions with proper logging
|
|
- **Separation of concerns**: Modular architecture
|
|
- **Documentation**: Comprehensive docstrings
|
|
- **Testing**: Unit tests for core functionality
|
|
|
|
## Environment Variables
|
|
|
|
| Variable | Required | Default | Description |
|
|
|----------|----------|---------|-------------|
|
|
| `KLEER_API_KEY` | Yes | - | API key for Kleer API |
|
|
| `KLEER_USERNAME` | No | Christopher Juhlin | Username for API requests |
|
|
| `KLEER_COMPANY_ID` | No | 1336 | Company ID for API requests |
|
|
|
|
## Docker Deployment
|
|
|
|
### Production Deployment
|
|
|
|
For production, you can customize the docker-compose.yml:
|
|
|
|
```yaml
|
|
version: '3.8'
|
|
|
|
services:
|
|
zynktime:
|
|
image: zynktime:latest
|
|
restart: always
|
|
ports:
|
|
- "80:8000" # Expose on port 80
|
|
environment:
|
|
- KLEER_API_KEY=${KLEER_API_KEY}
|
|
- KLEER_USERNAME=${KLEER_USERNAME}
|
|
- KLEER_COMPANY_ID=${KLEER_COMPANY_ID}
|
|
env_file:
|
|
- .env
|
|
```
|
|
|
|
### Behind a Reverse Proxy
|
|
|
|
If deploying behind nginx or traefik:
|
|
|
|
```yaml
|
|
# docker-compose.yml
|
|
services:
|
|
zynktime:
|
|
image: zynktime:latest
|
|
networks:
|
|
- proxy
|
|
labels:
|
|
- "traefik.enable=true"
|
|
- "traefik.http.routers.zynktime.rule=Host(`time.example.com`)"
|
|
```
|
|
|
|
### Health Checks
|
|
|
|
The Docker container includes health checks:
|
|
- **Endpoint**: `/health`
|
|
- **Interval**: 30 seconds
|
|
- **Timeout**: 10 seconds
|
|
- **Retries**: 3
|
|
|
|
Monitor with:
|
|
```bash
|
|
docker-compose ps
|
|
docker inspect zynktime | grep Health
|
|
```
|
|
|
|
## License
|
|
|
|
This project is for internal use with the Kleer API.
|