diff --git a/backend/create_new_db.py b/backend/create_new_db.py new file mode 100644 index 0000000..dece05e --- /dev/null +++ b/backend/create_new_db.py @@ -0,0 +1,5 @@ +from backend.models import Base +from backend.database import engine + +Base.metadata.drop_all(bind=engine) # Опционально, если вдруг есть +Base.metadata.create_all(bind=engine) \ No newline at end of file diff --git a/backend/database.py b/backend/database.py new file mode 100644 index 0000000..14d745a --- /dev/null +++ b/backend/database.py @@ -0,0 +1,15 @@ +# backend/database.py +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker, scoped_session + +SQLALCHEMY_DATABASE_URL = "sqlite:///./app.db" # или PostgreSQL URL + +engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}) +SessionLocal = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine)) + +def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close() diff --git a/backend/main.py b/backend/main.py new file mode 100644 index 0000000..a1e2ac4 --- /dev/null +++ b/backend/main.py @@ -0,0 +1,37 @@ +# backend/main.py +from fastapi import FastAPI +from fastapi.middleware.cors import CORSMiddleware + +from backend.routers.equipment_types import equipment_types +from backend.routers.auditories import auditories +from backend.routers.oboruds import oboruds +from backend.routers.components import components +from backend.routers.rashodniki import consumables +from backend.routers.zametki import zametki + + + + +app = FastAPI() + +# Для фронтенда Vue.js +app.add_middleware( + CORSMiddleware, + allow_origins=["*"], # заменить на ['http://localhost:5173'] для безопасности + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + +@app.get("/ping") +def ping(): + return {"message": "pong"} + + +# Подключение роутов +app.include_router(equipment_types) +app.include_router(auditories) +app.include_router(oboruds) +app.include_router(components) +app.include_router(consumables) +app.include_router(zametki) \ No newline at end of file diff --git a/backend/migrate_data.py b/backend/migrate_data.py new file mode 100644 index 0000000..c1c7689 --- /dev/null +++ b/backend/migrate_data.py @@ -0,0 +1,69 @@ +import sys +from sqlalchemy import create_engine, text +from sqlalchemy.orm import sessionmaker +from backend.database import SessionLocal as NewSession +from backend import models + +OLD_DB_URL = "sqlite:///./backend/old_app.db" +old_engine = create_engine(OLD_DB_URL, connect_args={"check_same_thread": False}) +OldSession = sessionmaker(bind=old_engine) +old_db = OldSession() + +new_db = NewSession() + +def log(msg: str): + print(f"[INFO] {msg}", file=sys.stderr) + +def migrate(): + log("Запуск переноса данных из old_app.db → app.db") + + # Тип оборудования по умолчанию + log("Добавление типа оборудования по умолчанию: 'Неизвестно'") + default_type = models.EquipmentType(name="Неизвестно") + new_db.add(default_type) + new_db.commit() + + # Перенос аудиторий + log("Перенос аудиторий...") + auditory_map = {} + aud_rows = old_db.execute(text("SELECT id, audnazvanie FROM auditory")).fetchall() + for aud in aud_rows: + new_aud = models.Auditory(audnazvanie=aud.audnazvanie) + new_db.add(new_aud) + new_db.flush() + auditory_map[aud.id] = new_aud.id + log(f" → перенесено: {len(aud_rows)}") + + # Перенос оборудования + log("Перенос оборудования...") + ob_rows = old_db.execute(text("SELECT * FROM oboruds")).fetchall() + for ob in ob_rows: + new_ob = models.Oboruds( + invNumber=ob.invNumber, + nazvanie=ob.nazvanie, + raspologenie=ob.raspologenie, + numberppasu=ob.numberppasu, + kolichestvo=ob.kolichestvo, + aud_id=auditory_map.get(ob.aud_id), + type_id=default_type.id + ) + new_db.add(new_ob) + log(f" → перенесено: {len(ob_rows)}") + + # Перенос заметок + log("Перенос заметок...") + z_rows = old_db.execute(text("SELECT * FROM zametki")).fetchall() + for z in z_rows: + new_z = models.Zametki( + txtzam=z.txtzam, + created_date=z.created_date, + rmdt=z.rmdt + ) + new_db.add(new_z) + log(f" → перенесено: {len(z_rows)}") + + new_db.commit() + log("✅ Перенос завершён успешно.") + +if __name__ == "__main__": + migrate() diff --git a/backend/models.py b/backend/models.py new file mode 100644 index 0000000..2a2d12b --- /dev/null +++ b/backend/models.py @@ -0,0 +1,82 @@ +# backend/models.py + +from sqlalchemy import Column, Integer, String, ForeignKey, DateTime +from sqlalchemy.orm import relationship, declarative_base +import datetime +from flask_sqlalchemy import SQLAlchemy + +Base = declarative_base() + +db = SQLAlchemy() + + + + + +class Auditory(Base): + __tablename__ = 'auditories' + + id = Column(Integer, primary_key=True) + audnazvanie = Column(String) + + oboruds = relationship("Oboruds", back_populates="auditory") + + +class EquipmentType(Base): + __tablename__ = 'equipment_types' + + id = Column(Integer, primary_key=True) + name = Column(String, unique=True, nullable=False) + + oboruds = relationship("Oboruds", back_populates="type") + + +class Oboruds(Base): + __tablename__ = 'oboruds' + + id = Column(Integer, primary_key=True) + invNumber = Column(Integer) + nazvanie = Column(String(500)) + raspologenie = Column(String(200)) + numberppasu = Column(String(100)) + kolichestvo = Column(Integer) + + aud_id = Column(Integer, ForeignKey("auditories.id")) + auditory = relationship("Auditory", back_populates="oboruds") + + type_id = Column(Integer, ForeignKey("equipment_types.id")) + type = relationship("EquipmentType", back_populates="oboruds") + + components = relationship("Component", back_populates="oborud") + consumables = relationship("Consumable", back_populates="oborud") + + +class Component(Base): + __tablename__ = 'components' + + id = Column(Integer, primary_key=True) + name = Column(String, nullable=False) + description = Column(String) + + oborud_id = Column(Integer, ForeignKey("oboruds.id")) + oborud = relationship("Oboruds", back_populates="components") + + +class Consumable(Base): + __tablename__ = 'consumables' + + id = Column(Integer, primary_key=True) + name = Column(String, nullable=False) + description = Column(String) + + oborud_id = Column(Integer, ForeignKey("oboruds.id")) + oborud = relationship("Oboruds", back_populates="consumables") + + +class Zametki(Base): + __tablename__ = 'zametki' + + id = Column(Integer, primary_key=True) + txtzam = Column(String(10000)) + created_date = Column(DateTime, default=datetime.datetime.utcnow) + rmdt = Column(DateTime) diff --git a/backend/requirements.txt b/backend/requirements.txt new file mode 100644 index 0000000..fc366fb Binary files /dev/null and b/backend/requirements.txt differ diff --git a/backend/routers/auditories.py b/backend/routers/auditories.py new file mode 100644 index 0000000..3e7c1c9 --- /dev/null +++ b/backend/routers/auditories.py @@ -0,0 +1,18 @@ +from fastapi import APIRouter, Depends +from sqlalchemy.orm import Session +from .. import models, schemas, database + +auditories = APIRouter(prefix="/auditories", tags=["auditories"]) + +@auditories.post("/", response_model=schemas.AuditoryRead) +def create_auditory(item: schemas.AuditoryCreate, db: Session = Depends(database.get_db)): + obj = models.Auditory(**item.dict()) + db.add(obj) + db.commit() + db.refresh(obj) + return obj + +@auditories.get("/", response_model=list[schemas.AuditoryRead]) +def list_auditories(db: Session = Depends(database.get_db)): + return db.query(models.Auditory).all() + diff --git a/backend/routers/components.py b/backend/routers/components.py new file mode 100644 index 0000000..d8cb387 --- /dev/null +++ b/backend/routers/components.py @@ -0,0 +1,18 @@ +from fastapi import APIRouter, Depends +from sqlalchemy.orm import Session +from .. import models, schemas, database + + +components = APIRouter(prefix="/components", tags=["components"]) + +@components.post("/", response_model=schemas.ComponentRead) +def create_component(item: schemas.ComponentCreate, db: Session = Depends(database.get_db)): + obj = models.Component(**item.dict()) + db.add(obj) + db.commit() + db.refresh(obj) + return obj + +@components.get("/", response_model=list[schemas.ComponentRead]) +def list_components(db: Session = Depends(database.get_db)): + return db.query(models.Component).all() diff --git a/backend/routers/equipment_types.py b/backend/routers/equipment_types.py new file mode 100644 index 0000000..868e2f3 --- /dev/null +++ b/backend/routers/equipment_types.py @@ -0,0 +1,17 @@ +from fastapi import APIRouter, Depends +from sqlalchemy.orm import Session +from .. import models, schemas, database + +equipment_types = APIRouter(prefix="/equipment-types", tags=["equipment_types"]) + +@equipment_types.post("/", response_model=schemas.EquipmentTypeRead) +def create_equipment_type(item: schemas.EquipmentTypeCreate, db: Session = Depends(database.get_db)): + obj = models.EquipmentType(**item.dict()) + db.add(obj) + db.commit() + db.refresh(obj) + return obj + +@equipment_types.get("/", response_model=list[schemas.EquipmentTypeRead]) +def list_equipment_types(db: Session = Depends(database.get_db)): + return db.query(models.EquipmentType).all() diff --git a/backend/routers/oboruds.py b/backend/routers/oboruds.py new file mode 100644 index 0000000..b017c05 --- /dev/null +++ b/backend/routers/oboruds.py @@ -0,0 +1,24 @@ +from fastapi import APIRouter, Depends +from sqlalchemy.orm import Session +from .. import models, schemas, database + +oboruds = APIRouter(prefix="/oboruds", tags=["oboruds"]) + +@oboruds.post("/", response_model=schemas.OborudRead) +def create_oborud(item: schemas.OborudCreate, db: Session = Depends(database.get_db)): + obj = models.Oboruds(**item.dict()) + db.add(obj) + db.commit() + db.refresh(obj) + return obj + +@oboruds.get("/", response_model=list[schemas.OborudRead]) +def list_oboruds(db: Session = Depends(database.get_db)): + return db.query(models.Oboruds).all() + +@oboruds.get("/{oborud_id}", response_model=schemas.OborudRead) +def get_oborud(oborud_id: int, db: Session = Depends(database.get_db)): + obj = db.query(models.Oboruds).filter(models.Oboruds.id == oborud_id).first() + if not obj: + raise HTTPException(status_code=404, detail="Oborud not found") + return obj \ No newline at end of file diff --git a/backend/routers/rashodniki.py b/backend/routers/rashodniki.py new file mode 100644 index 0000000..e8bfe28 --- /dev/null +++ b/backend/routers/rashodniki.py @@ -0,0 +1,17 @@ +from fastapi import APIRouter, Depends +from sqlalchemy.orm import Session +from .. import models, schemas, database + +consumables = APIRouter(prefix="/consumables", tags=["consumables"]) + +@consumables.post("/", response_model=schemas.ConsumableRead) +def create_consumable(item: schemas.ConsumableCreate, db: Session = Depends(database.get_db)): + obj = models.Consumable(**item.dict()) + db.add(obj) + db.commit() + db.refresh(obj) + return obj + +@consumables.get("/", response_model=list[schemas.ConsumableRead]) +def list_consumables(db: Session = Depends(database.get_db)): + return db.query(models.Consumable).all() diff --git a/backend/routers/zametki.py b/backend/routers/zametki.py new file mode 100644 index 0000000..00e1730 --- /dev/null +++ b/backend/routers/zametki.py @@ -0,0 +1,17 @@ +from fastapi import APIRouter, Depends +from sqlalchemy.orm import Session +from .. import models, schemas, database + +zametki = APIRouter(prefix="/zametki", tags=["zametki"]) + +@zametki.post("/", response_model=schemas.ZametkaRead) +def create_zametka(item: schemas.ZametkaCreate, db: Session = Depends(database.get_db)): + obj = models.Zametki(**item.dict()) + db.add(obj) + db.commit() + db.refresh(obj) + return obj + +@zametki.get("/", response_model=list[schemas.ZametkaRead]) +def list_zametki(db: Session = Depends(database.get_db)): + return db.query(models.Zametki).all() diff --git a/backend/schemas.py b/backend/schemas.py new file mode 100644 index 0000000..6b476ec --- /dev/null +++ b/backend/schemas.py @@ -0,0 +1,102 @@ +# backend/schemas.py + +from pydantic import BaseModel +from typing import Optional, List +from datetime import datetime + + +# === Equipment Type === +class EquipmentTypeBase(BaseModel): + name: str + +class EquipmentTypeCreate(EquipmentTypeBase): + pass + +class EquipmentTypeRead(EquipmentTypeBase): + id: int + + class Config: + orm_mode = True + + +# === Component === +class ComponentBase(BaseModel): + name: str + description: Optional[str] = None + +class ComponentCreate(ComponentBase): + oborud_id: int + +class ComponentRead(ComponentBase): + id: int + + class Config: + orm_mode = True + + +# === Consumable === +class ConsumableBase(BaseModel): + name: str + description: Optional[str] = None + +class ConsumableCreate(ConsumableBase): + oborud_id: int + +class ConsumableRead(ConsumableBase): + id: int + + class Config: + orm_mode = True + + +# === Oborud === +class OborudBase(BaseModel): + invNumber: Optional[int] + nazvanie: str + raspologenie: Optional[str] = None + numberppasu: Optional[str] = None + kolichestvo: Optional[int] = None + aud_id: int + type_id: int + +class OborudCreate(OborudBase): + pass + +class OborudRead(OborudBase): + id: int + type: EquipmentTypeRead + components: List[ComponentRead] = [] + consumables: List[ConsumableRead] = [] + + class Config: + orm_mode = True + + +# === Auditory === +class AuditoryBase(BaseModel): + audnazvanie: str + +class AuditoryCreate(AuditoryBase): + pass + +class AuditoryRead(AuditoryBase): + id: int + + class Config: + orm_mode = True + + +# === Zametka === +class ZametkaBase(BaseModel): + txtzam: str + rmdt: Optional[datetime] = None + +class ZametkaCreate(ZametkaBase): + pass + +class ZametkaRead(ZametkaBase): + id: int + created_date: datetime + + class Config: + orm_mode = True diff --git a/models.py b/models.py index 772481f..42084ec 100644 --- a/models.py +++ b/models.py @@ -1,32 +1,76 @@ +# backend/models.py -from flask_sqlalchemy import SQLAlchemy +from sqlalchemy import Column, Integer, String, ForeignKey, DateTime +from sqlalchemy.orm import relationship, declarative_base import datetime -db = SQLAlchemy() +Base = declarative_base() -class Auditory(db.Model): - id = db.Column(db.Integer, primary_key=True, autoincrement=True) - audnazvanie=db.Column(db.String) - oboruds = db.relationship('Oboruds') - +class Auditory(Base): + __tablename__ = 'auditories' - -class Oboruds(db.Model): - id = db.Column(db.Integer, primary_key=True, autoincrement=True) - invNumber=db.Column(db.Integer) - nazvanie=db.Column(db.String(500)) - raspologenie = db.Column(db.String(200)) - numberved = db.Column(db.String(100)) - numberppasu = db.Column(db.String(100)) - kolichestvo = db.Column(db.Integer) - balancenumber = db.Column(db.Integer) - aud_id = db.Column(db.Integer, db.ForeignKey(Auditory.id)) + id = Column(Integer, primary_key=True) + audnazvanie = Column(String) + + oboruds = relationship("Oboruds", back_populates="auditory") -class Zametki(db.Model): - id = db.Column(db.Integer, primary_key=True, autoincrement=True) - txtzam=db.Column(db.String(10000)) - created_date = db.Column(db.DateTime, default=datetime.datetime.utcnow) - rmdt = db.Column(db.DateTime) +class EquipmentType(Base): + __tablename__ = 'equipment_types' + id = Column(Integer, primary_key=True) + name = Column(String, unique=True, nullable=False) + + oboruds = relationship("Oboruds", back_populates="type") + + +class Oboruds(Base): + __tablename__ = 'oboruds' + + id = Column(Integer, primary_key=True) + invNumber = Column(Integer) + nazvanie = Column(String(500)) + raspologenie = Column(String(200)) + numberppasu = Column(String(100)) + kolichestvo = Column(Integer) + + aud_id = Column(Integer, ForeignKey("auditories.id")) + auditory = relationship("Auditory", back_populates="oboruds") + + type_id = Column(Integer, ForeignKey("equipment_types.id")) + type = relationship("EquipmentType", back_populates="oboruds") + + components = relationship("Component", back_populates="oborud") + consumables = relationship("Consumable", back_populates="oborud") + + +class Component(Base): + __tablename__ = 'components' + + id = Column(Integer, primary_key=True) + name = Column(String, nullable=False) + description = Column(String) + + oborud_id = Column(Integer, ForeignKey("oboruds.id")) + oborud = relationship("Oboruds", back_populates="components") + + +class Consumable(Base): + __tablename__ = 'consumables' + + id = Column(Integer, primary_key=True) + name = Column(String, nullable=False) + description = Column(String) + + oborud_id = Column(Integer, ForeignKey("oboruds.id")) + oborud = relationship("Oboruds", back_populates="consumables") + + +class Zametki(Base): + __tablename__ = 'zametki' + + id = Column(Integer, primary_key=True) + txtzam = Column(String(10000)) + created_date = Column(DateTime, default=datetime.datetime.utcnow) + rmdt = Column(DateTime) diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 867d559..0000000 Binary files a/requirements.txt and /dev/null differ