6 Commits

Author SHA1 Message Date
Your Name
31f1fcecc4 feat: add Docker Compose setup with bind-mount appdata directory
- Dockerfile builds image with app source in /app_src
- docker-entrypoint.sh syncs code from image on each start, inits DB
- docker-compose.yml mounts ./appdata:/app for easy backup
- backend/init_db.py for safe DB init (no drop_all)
- backend/database.py supports DATABASE_URL env var
- .dockerignore excludes venv, __pycache__, *.db, .git

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 12:15:37 +03:00
Your Name
67e7ab6f94 style: increase button padding via .btn override
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 17:05:40 +03:00
Your Name
913e23b966 style: add padding to buttons so text is not cramped
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 17:04:41 +03:00
Your Name
7219fbdada style: revert button color to original #E07D54
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 17:03:48 +03:00
Your Name
92fc020d94 style: change button color to black (#000000)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 17:01:25 +03:00
Your Name
dca8a0dbcf style: replace blue buttons with original #E07D54 color
Override Bootstrap btn-primary and btn-outline-primary to match the original project's button color.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 16:59:22 +03:00
7 changed files with 118 additions and 7 deletions

13
.dockerignore Normal file
View File

@@ -0,0 +1,13 @@
venv/
backend/venv/
**/__pycache__/
*.pyc
*.pyo
*.db
.git/
.gitignore
.vscode/
.idea/
data/
*.xls
*.xlsx

15
Dockerfile Normal file
View File

@@ -0,0 +1,15 @@
FROM python:3.11-slim
COPY requirements.txt /app_src/requirements.txt
RUN pip install --no-cache-dir -r /app_src/requirements.txt
COPY backend/ /app_src/backend/
COPY frontend/ /app_src/frontend/
COPY docker-entrypoint.sh /app_src/docker-entrypoint.sh
RUN chmod +x /app_src/docker-entrypoint.sh
WORKDIR /app
EXPOSE 8000
ENTRYPOINT ["/app_src/docker-entrypoint.sh"]

View File

@@ -1,10 +1,13 @@
# backend/database.py # backend/database.py
import os
from sqlalchemy import create_engine from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, scoped_session from sqlalchemy.orm import sessionmaker, scoped_session
SQLALCHEMY_DATABASE_URL = "sqlite:///./app.db" # или PostgreSQL URL SQLALCHEMY_DATABASE_URL = os.getenv("DATABASE_URL", "sqlite:///./app.db")
engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}) connect_args = {"check_same_thread": False} if SQLALCHEMY_DATABASE_URL.startswith("sqlite") else {}
engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args=connect_args)
SessionLocal = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine)) SessionLocal = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine))
def get_db(): def get_db():

27
backend/init_db.py Normal file
View File

@@ -0,0 +1,27 @@
from sqlalchemy.orm import sessionmaker
from backend.models import Base, User
from backend.database import engine
from backend.security import get_password_hash
def init_db():
Base.metadata.create_all(bind=engine)
Session = sessionmaker(bind=engine)
db = Session()
try:
if not db.query(User).filter(User.username == 'admin').first():
db.add(User(
username='admin',
password_hash=get_password_hash('admin'),
role='admin',
))
db.commit()
print("Created default admin user (login: admin / password: admin)")
finally:
db.close()
if __name__ == "__main__":
init_db()

10
docker-compose.yml Normal file
View File

@@ -0,0 +1,10 @@
services:
app:
build: .
ports:
- "8000:8000"
volumes:
- ./appdata:/app
environment:
- DATABASE_URL=sqlite:////app/data/app.db
restart: unless-stopped

11
docker-entrypoint.sh Normal file
View File

@@ -0,0 +1,11 @@
#!/bin/sh
set -e
# Sync app code from image on every start (keeps code fresh after rebuilds)
rm -rf /app/backend /app/frontend
cp -r /app_src/backend /app_src/frontend /app/
mkdir -p /app/data
python -m backend.init_db
exec uvicorn backend.main:app --host 0.0.0.0 --port 8000

View File

@@ -38,6 +38,38 @@ button {
background-color: #E07D54; background-color: #E07D54;
margin-top: 5px; margin-top: 5px;
margin-bottom: 5px; margin-bottom: 5px;
padding: 6px 14px;
}
.btn {
padding: 8px 20px;
}
.btn-sm {
padding: 5px 12px;
}
.btn-primary {
background-color: #E07D54;
border-color: #E07D54;
color: #fff;
}
.btn-primary:hover, .btn-primary:focus, .btn-primary:active {
background-color: #c86a3d;
border-color: #c86a3d;
color: #fff;
}
.btn-outline-primary {
color: #E07D54;
border-color: #E07D54;
}
.btn-outline-primary:hover, .btn-outline-primary:focus, .btn-outline-primary:active {
background-color: #E07D54;
border-color: #E07D54;
color: #fff;
} }
.card { .card {
@@ -177,13 +209,13 @@ td.inv-col, th.inv-col {
} }
.table { .table {
border: 1px solid #000000; border: 1px solid #E07D54;
margin-top: 20px; margin-top: 20px;
font-size: 12pt; font-size: 12pt;
} }
.table th, .table td { .table th, .table td {
border: 1px solid #000000; border: 1px solid #E07D54;
padding: 5px; padding: 5px;
font-size: 12pt; font-size: 12pt;
word-break: normal; word-break: normal;
@@ -199,19 +231,19 @@ td.inv-col, th.inv-col {
} }
table.rs-table-bordered { table.rs-table-bordered {
border: 1px solid #000000; border: 1px solid #E07D54;
margin-top: 20px; margin-top: 20px;
font-size: 14pt; font-size: 14pt;
} }
table.rs-table-bordered > thead > tr > th { table.rs-table-bordered > thead > tr > th {
border: 1px solid #000000; border: 1px solid #E07D54;
padding: 2px; padding: 2px;
font-size: 14pt; font-size: 14pt;
} }
table.rs-table-bordered > tbody > tr > td { table.rs-table-bordered > tbody > tr > td {
border: 1px solid #000000; border: 1px solid #E07D54;
padding: 10px; padding: 10px;
font-size: 14pt; font-size: 14pt;
} }