feat: add FastAPI backend with PostgreSQL and start script fixes
- Add server/ directory with FastAPI backend - Fix server/start.sh to properly handle venv on Windows/Git Bash - Add alembic migrations and pyproject.toml - Add server tests Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
1
server/src/app/schemas/__init__.py
Normal file
1
server/src/app/schemas/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
__all__ = ["employee", "reimbursement"]
|
||||
67
server/src/app/schemas/bootstrap.py
Normal file
67
server/src/app/schemas/bootstrap.py
Normal file
@@ -0,0 +1,67 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pydantic import BaseModel, EmailStr, Field, field_validator
|
||||
|
||||
|
||||
class BootstrapCompanyRead(BaseModel):
|
||||
name: str
|
||||
code: str
|
||||
admin_email: str
|
||||
|
||||
|
||||
class BootstrapConnectionRead(BaseModel):
|
||||
host: str
|
||||
port: int
|
||||
|
||||
|
||||
class BootstrapDatabaseRead(BaseModel):
|
||||
driver: str
|
||||
host: str
|
||||
port: int
|
||||
name: str
|
||||
username: str
|
||||
password_configured: bool
|
||||
|
||||
|
||||
class BootstrapCacheRead(BaseModel):
|
||||
enabled: bool
|
||||
url: str
|
||||
|
||||
|
||||
class BootstrapStateRead(BaseModel):
|
||||
initialized: bool
|
||||
company: BootstrapCompanyRead
|
||||
web: BootstrapConnectionRead
|
||||
server: BootstrapConnectionRead
|
||||
database: BootstrapDatabaseRead
|
||||
redis: BootstrapCacheRead
|
||||
|
||||
|
||||
class BootstrapSetupPayload(BaseModel):
|
||||
company_name: str = Field(min_length=2, max_length=80)
|
||||
company_code: str = Field(default="", max_length=32)
|
||||
admin_email: EmailStr | None = None
|
||||
|
||||
postgres_host: str = Field(min_length=1, max_length=255)
|
||||
postgres_port: int = Field(default=5432, ge=1, le=65535)
|
||||
postgres_db: str = Field(min_length=1, max_length=128)
|
||||
postgres_user: str = Field(min_length=1, max_length=128)
|
||||
postgres_password: str = Field(min_length=1, max_length=255)
|
||||
|
||||
redis_url: str | None = Field(default=None, max_length=255)
|
||||
|
||||
@field_validator(
|
||||
"company_name",
|
||||
"company_code",
|
||||
"postgres_host",
|
||||
"postgres_db",
|
||||
"postgres_user",
|
||||
"postgres_password",
|
||||
"redis_url",
|
||||
mode="before",
|
||||
)
|
||||
@classmethod
|
||||
def strip_string(cls, value: str | None) -> str | None:
|
||||
if value is None:
|
||||
return None
|
||||
return value.strip()
|
||||
24
server/src/app/schemas/employee.py
Normal file
24
server/src/app/schemas/employee.py
Normal file
@@ -0,0 +1,24 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, EmailStr
|
||||
|
||||
|
||||
class EmployeeCreate(BaseModel):
|
||||
employee_no: str
|
||||
name: str
|
||||
department: str
|
||||
email: EmailStr
|
||||
|
||||
|
||||
class EmployeeRead(BaseModel):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
id: str
|
||||
employee_no: str
|
||||
name: str
|
||||
department: str
|
||||
email: EmailStr
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
30
server/src/app/schemas/reimbursement.py
Normal file
30
server/src/app/schemas/reimbursement.py
Normal file
@@ -0,0 +1,30 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
|
||||
from pydantic import BaseModel, ConfigDict
|
||||
|
||||
|
||||
class ReimbursementCreate(BaseModel):
|
||||
request_no: str
|
||||
employee_id: str
|
||||
title: str
|
||||
category: str
|
||||
amount: Decimal
|
||||
reason: str | None = None
|
||||
|
||||
|
||||
class ReimbursementRead(BaseModel):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
id: str
|
||||
request_no: str
|
||||
employee_id: str
|
||||
title: str
|
||||
category: str
|
||||
status: str
|
||||
amount: Decimal
|
||||
reason: str | None
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
Reference in New Issue
Block a user