diff --git a/.gitignore b/.gitignore index 7d765a4..d04c421 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,9 @@ -*.csv -.vscode -instance -venv/ -__pycache__ -123 -*.csv -*.db -c*.txt - -migrations/* -.idea \ No newline at end of file + .vscode + .idea + venv/ + instance/ + __pycache__/ + migrations/ + *.csv + *.db + c*.txt diff --git a/VedomostMOL.xls b/VedomostMOL.xls new file mode 100644 index 0000000..b103dca Binary files /dev/null and b/VedomostMOL.xls differ diff --git a/VedomostMOL.xlsx b/VedomostMOL.xlsx new file mode 100644 index 0000000..f505043 Binary files /dev/null and b/VedomostMOL.xlsx differ diff --git a/app.py b/app.py index e51a222..17633fb 100644 --- a/app.py +++ b/app.py @@ -8,7 +8,6 @@ import csv import random from urllib.parse import unquote - app = Flask(__name__) app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///project.db" @@ -22,7 +21,13 @@ db.init_app(app) migrate = Migrate(app, db) -@app.route("/", methods=['GET', 'POST']) + +@app.route("/login", methods=['GET', 'POST']) +def login(): + return render_template('login.html') + + +@app.route("/", methods=['GET', 'POST']) def index(): results = [] results1 = [] @@ -46,7 +51,7 @@ def index(): results1.append(s.nazvanie) aud = db.session.get(Auditory, s.aud_id) results1.append(aud.audnazvanie) - return render_template('index.html', aud=all_aud, results=results, res1=results1) + return render_template('index.html', aud=all_aud, results=results, res1=results1) return render_template('index.html', aud=all_aud, results=results, res1=results1) @@ -91,7 +96,7 @@ def searchonaud(): return render_template('searchonaud.html', aud=all_aud, res=res) -@app.route("/addaudtodb", methods=['GET', 'POST']) +@app.route("/addaudtodb", methods=['GET', 'POST']) def addaudtodb(): if request.method == 'POST': aud = request.form.get('auditory') @@ -119,26 +124,33 @@ def alloborud(): @app.route('/getall') def getall(): - oboruds = Oboruds.query.all() - oboruds_json = [{ - 'id': oborud.id, - 'invNumber': oborud.invNumber, - 'nazvanie': oborud.nazvanie, - 'raspologenie': oborud.raspologenie, - 'numberved': oborud.numberved, - 'balancenumber': oborud.balancenumber, - 'kolichestvo': oborud.kolichestvo, - 'balancenumber': oborud.balancenumber, - 'aud_id': oborud.aud_id - } for oborud in oboruds] + oborud = db.session.query(Oboruds).order_by(Oboruds.invNumber).all() + results = [] + for oboruds in oborud: + if oboruds.aud_id is None: + results.append({ + 'invNumber': oboruds.invNumber, + 'nazvanie': oboruds.nazvanie, + 'raspologenie': oboruds.raspologenie, + 'balancenumber': oboruds.balancenumber, + 'kolichestvo': oboruds.kolichestvo, + 'numberppasu': oboruds.numberppasu, + 'numberved': oboruds.numberved, + 'aud': ""}) + else: + aud = db.session.query(Auditory).filter_by(id=oboruds.aud_id).first() + results.append({ + 'invNumber': oboruds.invNumber, + 'nazvanie': oboruds.nazvanie, + 'raspologenie': oboruds.raspologenie, + 'balancenumber': oboruds.balancenumber, + 'kolichestvo': oboruds.kolichestvo, + 'numberppasu': oboruds.numberppasu, + 'numberved': oboruds.numberved, + 'aud': aud.audnazvanie}) - return jsonify(oboruds_json) - -@app.route('/updateduplicate', methods=['GET', 'POST']) -def updateduplicate(): - if request.method == 'POST': - aud = request.form.get('auditory_dubl') + return jsonify(results) @app.route('/vneaud', methods=['GET', 'POST']) @@ -149,12 +161,12 @@ def vneaud(): ak = db.session.query(Oboruds).all() for dt in data: - res.append([dt.invNumber, dt.nazvanie, dt.typeBalanse]) + res.append([dt.invNumber, dt.nazvanie]) return render_template('vneaud.html', res=res, kolvo=len(data), all_kol=len(ak)) -@app.route('/zametki', methods=['GET', 'POST']) +@app.route('/zametki', methods=['GET', 'POST']) def zametki(): zam = db.session.query(Zametki).filter(Zametki.rmdt == None).all() if request.method == 'POST': @@ -177,7 +189,7 @@ def js2(): return jsonify({'success': True}), 200, {'ContentType': 'application/json'} -@app.route('/zamsearch', methods=['GET', 'POST']) +@app.route('/zamsearch', methods=['GET', 'POST']) def zamsearch(): p = request.form.get('srch') @@ -185,42 +197,61 @@ def zamsearch(): Zametki.txtzam.contains(p)).ll() zam = [] for item in searchedZam: - zam.append([item.txtzam, item.created_date]) + zam.append([item.txtzam, item.created_date]) return render_template('zametki.html', zam=zam) @app.route('/addraspved', methods=['GET', 'POST']) def addraspved(): - if request.method == 'POST': - + if request.method == 'POST': query_string = request.data.decode() - print(query_string) un_query_string = unquote(unquote(query_string)).split(',') - print(un_query_string) - - - ob = db.session.query(Oboruds).filter_by(invNumber=un_query_string[0]).first() - ob.raspologenie=un_query_string[2] + ob.numberved = un_query_string[1] + ob.kolichestvo = un_query_string[2] + ob.balancenumber = un_query_string[3] + ob.raspologenie = un_query_string[4] + db.session.commit() db.session.close() - + return jsonify({'success': True}, 200, {'ContentType': 'application/json'}) - + + +@app.route('/addoborudasu', methods=['GET', 'POST']) +def addoborud(): + if request.method == 'POST': + query_string = request.data.decode() + + un_query_string = unquote(unquote(query_string)).split(',') + db.session.add( + Oboruds(invNumber=un_query_string[0], + nazvanie=un_query_string[5], + raspologenie=un_query_string[4], + numberved=un_query_string[1], + kolichestvo=un_query_string[2], + balancenumber=un_query_string[3] + ) + ) + + db.session.commit() + + return jsonify({'success': True}, 200, {'ContentType': 'application/json'}) + # ================================================================================== - + def ranomraspr(): - with app.app_context(): - while len(db.session.query(Oboruds).filter(Oboruds.aud_id == None).all()) > 0: - audid = random.choice(db.session.query(Auditory).all()) - oborud = random.choice(db.session.query(Oboruds).filter(Oboruds.aud_id == None).all()) - oborud.aud_id = audid.id - db.session.commit() + with app.app_context(): + while len(db.session.query(Oboruds).filter(Oboruds.aud_id is None).all()) > 0: + audid = random.choice(db.session.query(Auditory).all()) + oborud = random.choice(db.session.query(Oboruds).filter(Oboruds.aud_id is None).all()) + oborud.aud_id = audid.id + db.session.commit() def createdb(): @@ -262,13 +293,52 @@ def createdb(): for row in csv_reader: db.session.add( Oboruds(invNumber=row[0], nazvanie=row[1], typeBalanse='баланс')) - + db.session.commit() - + + +def write2excell(): + wb = xlrd.open_workbook("VedIsh.xls") + sheet = wb.sheet_by_index(0) + + newFile = copy(wb) + newSheet = newFile.get_sheet(0) + invNomerColum = 6 + + column_index = 1 + for row_idx in range(sheet.nrows): + cell_value = sheet.cell(row_idx, column_index) + + if cell_value: + + tmp_inv_number = str(cell_value).split(':')[1] + + try: + a = tmp_inv_number[1:-1] + + inv_number = int(tmp_inv_number[1:-1]) + + with app.app_context(): + auditory_obj = db.session.query(Auditory).join(Oboruds, Oboruds.aud_id == Auditory.id).filter( + Oboruds.invNumber == inv_number).first() + + print(auditory_obj.audnazvanie) + + # cur.execute("SELECT aud.audnazvanie FROM oboruds AS ob JOIN auditory AS aud ON ob.aud_id = aud.id WHERE ob.invNumber = ?", (inv_number,)) + + + except: + pass + + """ + else: + #newSheet.write(row_idx, invNomerColum, "Нет инв номера") + pass + newFile.save("Ved31.xls") + """ if __name__ == '__main__': + #write2excell() - #ranomraspr() - #createdb() - app.run(debug=True, host='0.0.0.0', port='3800') + app.run(debug=True, host='0.0.0.0', port='3800') diff --git a/backend/__init__.py b/backend/__init__.py new file mode 100644 index 0000000..e4179e8 --- /dev/null +++ b/backend/__init__.py @@ -0,0 +1,2 @@ +"""Backend package initializer.""" + 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..b18280c --- /dev/null +++ b/backend/main.py @@ -0,0 +1,43 @@ +# backend/main.py +from fastapi import FastAPI +from fastapi.responses import RedirectResponse +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.get("/") +def root(): + return RedirectResponse(url="/docs") + + +# Подключение роутов +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) 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..de24b3f --- /dev/null +++ b/backend/models.py @@ -0,0 +1,80 @@ +# backend/models.py + +from sqlalchemy import Column, Integer, String, ForeignKey, DateTime +from sqlalchemy.orm import relationship, declarative_base +import datetime + +Base = declarative_base() + + + + + + +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/__init__.py b/backend/routers/__init__.py new file mode 100644 index 0000000..3d27349 --- /dev/null +++ b/backend/routers/__init__.py @@ -0,0 +1,2 @@ +"""Routers package initializer.""" + 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..a7d5285 --- /dev/null +++ b/backend/routers/oboruds.py @@ -0,0 +1,28 @@ +from fastapi import APIRouter, Depends, HTTPException +from typing import Optional +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(aud_id: Optional[int] = None, db: Session = Depends(database.get_db)): + query = db.query(models.Oboruds) + if aud_id is not None: + query = query.filter(models.Oboruds.aud_id == aud_id) + return query.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 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/migrations/__pycache__/env.cpython-39.pyc b/migrations/__pycache__/env.cpython-39.pyc deleted file mode 100644 index 3fc4ed7..0000000 Binary files a/migrations/__pycache__/env.cpython-39.pyc and /dev/null differ diff --git a/migrations/versions/10da3140ab2e_.py b/migrations/versions/10da3140ab2e_.py new file mode 100644 index 0000000..f82f04f --- /dev/null +++ b/migrations/versions/10da3140ab2e_.py @@ -0,0 +1,32 @@ +"""empty message + +Revision ID: 10da3140ab2e +Revises: 4eacd6dcd461 +Create Date: 2024-04-05 01:25:48.931573 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '10da3140ab2e' +down_revision = '4eacd6dcd461' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('oboruds', schema=None) as batch_op: + batch_op.add_column(sa.Column('kolichestvo', sa.Integer(), nullable=True)) + + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('oboruds', schema=None) as batch_op: + batch_op.drop_column('kolichestvo') + + # ### end Alembic commands ### diff --git a/migrations/versions/4eacd6dcd461_.py b/migrations/versions/4eacd6dcd461_.py new file mode 100644 index 0000000..7bbfec8 --- /dev/null +++ b/migrations/versions/4eacd6dcd461_.py @@ -0,0 +1,54 @@ +"""empty message + +Revision ID: 4eacd6dcd461 +Revises: c208cbc25232 +Create Date: 2024-04-03 23:25:42.271936 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '4eacd6dcd461' +down_revision = 'c208cbc25232' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('oboruds', schema=None) as batch_op: + batch_op.add_column(sa.Column('numberved', sa.String(length=100), nullable=True)) + batch_op.add_column(sa.Column('numberppasu', sa.String(length=100), nullable=True)) + batch_op.add_column(sa.Column('balancenumber', sa.Integer(), nullable=True)) + batch_op.alter_column('nazvanie', + existing_type=sa.TEXT(length=500), + type_=sa.String(length=500), + existing_nullable=True) + batch_op.alter_column('raspologenie', + existing_type=sa.TEXT(length=200), + type_=sa.String(length=200), + existing_nullable=True) + batch_op.drop_column('buhnumberpp') + + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('oboruds', schema=None) as batch_op: + batch_op.add_column(sa.Column('buhnumberpp', sa.VARCHAR(length=100), nullable=True)) + batch_op.alter_column('raspologenie', + existing_type=sa.String(length=200), + type_=sa.TEXT(length=200), + existing_nullable=True) + batch_op.alter_column('nazvanie', + existing_type=sa.String(length=500), + type_=sa.TEXT(length=500), + existing_nullable=True) + batch_op.drop_column('balancenumber') + batch_op.drop_column('numberppasu') + batch_op.drop_column('numberved') + + # ### end Alembic commands ### diff --git a/migrations/versions/6fc3d1adb061_.py b/migrations/versions/6fc3d1adb061_.py new file mode 100644 index 0000000..fedf8b5 --- /dev/null +++ b/migrations/versions/6fc3d1adb061_.py @@ -0,0 +1,34 @@ +"""empty message + +Revision ID: 6fc3d1adb061 +Revises: be7c94c549e5 +Create Date: 2024-04-02 16:32:23.180273 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '6fc3d1adb061' +down_revision = 'be7c94c549e5' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('oboruds', schema=None) as batch_op: + batch_op.add_column(sa.Column('buhnumberpp', sa.String(length=100), nullable=True)) + batch_op.add_column(sa.Column('kolichestvo', sa.Integer(), nullable=True)) + + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('oboruds', schema=None) as batch_op: + batch_op.drop_column('kolichestvo') + batch_op.drop_column('buhnumberpp') + + # ### end Alembic commands ### diff --git a/migrations/versions/8e5efc4de919_.py b/migrations/versions/8e5efc4de919_.py new file mode 100644 index 0000000..a5efc2a --- /dev/null +++ b/migrations/versions/8e5efc4de919_.py @@ -0,0 +1,54 @@ +"""empty message + +Revision ID: 8e5efc4de919 +Revises: c208cbc25232 +Create Date: 2024-04-03 22:36:46.208266 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '8e5efc4de919' +down_revision = 'c208cbc25232' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('oboruds', schema=None) as batch_op: + batch_op.add_column(sa.Column('numberved', sa.String(length=100), nullable=True)) + batch_op.add_column(sa.Column('numberppasu', sa.String(length=100), nullable=True)) + batch_op.add_column(sa.Column('balancenumber', sa.Integer(), nullable=True)) + batch_op.alter_column('nazvanie', + existing_type=sa.TEXT(length=500), + type_=sa.String(length=500), + existing_nullable=True) + batch_op.alter_column('raspologenie', + existing_type=sa.TEXT(length=200), + type_=sa.String(length=200), + existing_nullable=True) + batch_op.drop_column('buhnumberpp') + + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('oboruds', schema=None) as batch_op: + batch_op.add_column(sa.Column('buhnumberpp', sa.TEXT(length=100), nullable=True)) + batch_op.alter_column('raspologenie', + existing_type=sa.String(length=200), + type_=sa.TEXT(length=200), + existing_nullable=True) + batch_op.alter_column('nazvanie', + existing_type=sa.String(length=500), + type_=sa.TEXT(length=500), + existing_nullable=True) + batch_op.drop_column('balancenumber') + batch_op.drop_column('numberppasu') + batch_op.drop_column('numberved') + + # ### end Alembic commands ### diff --git a/migrations/versions/__pycache__/256c3a3e91a2_.cpython-312.pyc b/migrations/versions/__pycache__/256c3a3e91a2_.cpython-312.pyc deleted file mode 100644 index 77081c0..0000000 Binary files a/migrations/versions/__pycache__/256c3a3e91a2_.cpython-312.pyc and /dev/null differ diff --git a/migrations/versions/__pycache__/4f95d12a8352_.cpython-312.pyc b/migrations/versions/__pycache__/4f95d12a8352_.cpython-312.pyc deleted file mode 100644 index 2889172..0000000 Binary files a/migrations/versions/__pycache__/4f95d12a8352_.cpython-312.pyc and /dev/null differ diff --git a/migrations/versions/__pycache__/50f85881169e_.cpython-312.pyc b/migrations/versions/__pycache__/50f85881169e_.cpython-312.pyc deleted file mode 100644 index aee53e0..0000000 Binary files a/migrations/versions/__pycache__/50f85881169e_.cpython-312.pyc and /dev/null differ diff --git a/migrations/versions/__pycache__/873defe09f22_.cpython-312.pyc b/migrations/versions/__pycache__/873defe09f22_.cpython-312.pyc deleted file mode 100644 index fd851b5..0000000 Binary files a/migrations/versions/__pycache__/873defe09f22_.cpython-312.pyc and /dev/null differ diff --git a/migrations/versions/__pycache__/885bdd7b5161_.cpython-312.pyc b/migrations/versions/__pycache__/885bdd7b5161_.cpython-312.pyc deleted file mode 100644 index 74241f9..0000000 Binary files a/migrations/versions/__pycache__/885bdd7b5161_.cpython-312.pyc and /dev/null differ diff --git a/migrations/versions/__pycache__/8e838956713f_.cpython-312.pyc b/migrations/versions/__pycache__/8e838956713f_.cpython-312.pyc deleted file mode 100644 index 386f4de..0000000 Binary files a/migrations/versions/__pycache__/8e838956713f_.cpython-312.pyc and /dev/null differ diff --git a/migrations/versions/__pycache__/b24baa0d98e6_.cpython-312.pyc b/migrations/versions/__pycache__/b24baa0d98e6_.cpython-312.pyc deleted file mode 100644 index 69a74a0..0000000 Binary files a/migrations/versions/__pycache__/b24baa0d98e6_.cpython-312.pyc and /dev/null differ diff --git a/migrations/versions/__pycache__/b2a61aef79e9_.cpython-312.pyc b/migrations/versions/__pycache__/b2a61aef79e9_.cpython-312.pyc deleted file mode 100644 index 6f573f0..0000000 Binary files a/migrations/versions/__pycache__/b2a61aef79e9_.cpython-312.pyc and /dev/null differ diff --git a/migrations/versions/__pycache__/be7c94c549e5_.cpython-312.pyc b/migrations/versions/__pycache__/be7c94c549e5_.cpython-312.pyc deleted file mode 100644 index 7203052..0000000 Binary files a/migrations/versions/__pycache__/be7c94c549e5_.cpython-312.pyc and /dev/null differ diff --git a/migrations/versions/__pycache__/ec6bbcd361bd_.cpython-312.pyc b/migrations/versions/__pycache__/ec6bbcd361bd_.cpython-312.pyc deleted file mode 100644 index 1d027b0..0000000 Binary files a/migrations/versions/__pycache__/ec6bbcd361bd_.cpython-312.pyc and /dev/null differ diff --git a/migrations/versions/c208cbc25232_.py b/migrations/versions/c208cbc25232_.py new file mode 100644 index 0000000..d158e4b --- /dev/null +++ b/migrations/versions/c208cbc25232_.py @@ -0,0 +1,24 @@ +"""empty message + +Revision ID: c208cbc25232 +Revises: 6fc3d1adb061, 885bdd7b5161 +Create Date: 2024-04-03 22:11:15.008480 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'c208cbc25232' +down_revision = ('6fc3d1adb061', '885bdd7b5161') +branch_labels = None +depends_on = None + + +def upgrade(): + pass + + +def downgrade(): + pass diff --git a/migrations/versions/d4a8e4c9e65a_.py b/migrations/versions/d4a8e4c9e65a_.py new file mode 100644 index 0000000..d16f67b --- /dev/null +++ b/migrations/versions/d4a8e4c9e65a_.py @@ -0,0 +1,24 @@ +"""empty message + +Revision ID: d4a8e4c9e65a +Revises: 10da3140ab2e, 8e5efc4de919 +Create Date: 2024-05-06 08:27:39.088982 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'd4a8e4c9e65a' +down_revision = ('10da3140ab2e', '8e5efc4de919') +branch_labels = None +depends_on = None + + +def upgrade(): + pass + + +def downgrade(): + pass diff --git a/models.py b/models.py index 44119b0..42084ec 100644 --- a/models.py +++ b/models.py @@ -1,37 +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)) - balancenumber = db.Column(db.String(30)) - raspologenie = db.Column(db.String(200)) - numberved = db.Column(db.String(100)) - numberppasu = db.Column(db.String(100)) - kolichestvo = db.Column(db.Integer) + id = Column(Integer, primary_key=True) + audnazvanie = Column(String) - aud_id = db.Column(db.Integer, db.ForeignKey(Auditory.id)) + 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' -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) + 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 diff --git a/serve.py b/serve.py new file mode 100644 index 0000000..3e35f73 --- /dev/null +++ b/serve.py @@ -0,0 +1,6 @@ +from waitress import serve +from app import app + + +if __name__ == '__main__': + serve(app, port='3800') diff --git a/static/css/index.css b/static/css/index.css index 72385ec..28e832a 100644 --- a/static/css/index.css +++ b/static/css/index.css @@ -8,7 +8,7 @@ body { min-width: 580px; } -.row{ +.row { text-align: center; @@ -24,7 +24,7 @@ body { header { text-align: center; - + background-color: #6A90B6; padding: 2px; } @@ -35,7 +35,7 @@ a:hover { color: #041322; } -a{ +a { color: #041322; @@ -54,7 +54,7 @@ button { .card { - width: 200px; + /*width: 200px; */ margin: 10px; border-radius: 15px; border-color: #E07D54; @@ -67,51 +67,62 @@ h5 { } - -.hidden-column{ - display: none; +.hidden-column { + display: none; } -nav{ +nav { - width:100%; + width: 100%; } -.table{ +table { word-break: break-all; + border-collapse: separate !important; } -.aud{ +.table td { + font-size: 14px; + padding: 0; + max-width: 10rem; + word-break: break-all; + border-collapse: separate !important; +} + +.aud { width: 110px; } -.inv{ +.inv { width: 400px; } -.rasp{ - max-width: 200px; +.rasp { + width: 200px; word-break: break-word; + white-space: nowrap; } -#modal_matcenn{ +#modal_matcenn { margin-left: 20px; } -.datatable{ +.datatable { background-color: whitesmoke; } +.datatable th:nth-child(7) { + width: 200px; - +} @media print { - *{ + * { font-family: "Times New Roman", Times, serif; } @@ -119,7 +130,7 @@ nav{ margin: 0; padding: 0; background-color: transparent; - + } @@ -139,29 +150,30 @@ nav{ width: 100%; } + .no-print { display: none; - } + } - table.rs-table-bordered{ - border:1px solid #000000; - margin-top:20px; + table.rs-table-bordered { + border: 1px solid #000000; + margin-top: 20px; font-size: 14pt; - - } - table.rs-table-bordered > thead > tr > th{ - border:1px solid #000000; + + } + + table.rs-table-bordered > thead > tr > th { + border: 1px solid #000000; padding: 2px; font-size: 14pt; } - table.rs-table-bordered > tbody > tr > td{ - border:1px solid #000000; + + table.rs-table-bordered > tbody > tr > td { + border: 1px solid #000000; padding: 10px; font-size: 14pt; } - - } \ No newline at end of file diff --git a/static/js/allmatc.js b/static/js/allmatc.js index c9e2668..1477f10 100644 --- a/static/js/allmatc.js +++ b/static/js/allmatc.js @@ -1,35 +1,282 @@ -function getAllData(){ - $.ajax({ +function clearTable() { + var table = document.getElementById("alldatatable"); + var rowCount = table.rows.length; - url: "/getall", - type: "get", - contentType: 'application/json', - dataType: 'json', - - success: function(response){ - console.log(response) - let data = response; - $('#datatable tbody').empty(); - $.each(response, function(index, item) { - $('#datatable tbody').append( - '
| № п/п | -№ п/п вед | +№ п/п АСУ |
+ № п/п вед |
Инв. номер | Название | Кол-во | Счёт | -Аудитория | +Ауд - я | +Расположение | +
|---|---|---|---|---|---|---|---|---|---|---|