Изменен ИС ЖКХ РС
This commit is contained in:
48
isjkhrs/crud.py
Normal file
48
isjkhrs/crud.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
from sqlalchemy.orm import Session
|
||||||
|
from sqlalchemy import text
|
||||||
|
from isjkhrs.database import get_table
|
||||||
|
from isjkhrs import schemas
|
||||||
|
|
||||||
|
def exec_procedure(session, proc_name, params, database: str = None):
|
||||||
|
sql_params = ",".join([f"@{name}='{value}'" if type(value) in [str] else f"@{name}={value}"
|
||||||
|
for name, value in params.items()])
|
||||||
|
dbstr = ""
|
||||||
|
if database:
|
||||||
|
dbstr = f"[{database}]."
|
||||||
|
sql_string = """
|
||||||
|
DECLARE @return_value int;
|
||||||
|
EXEC @return_value = {dbstr}[dbo].[{proc_name}] {params};
|
||||||
|
SELECT 'Return Value' = @return_value;
|
||||||
|
""".format(dbstr=dbstr, proc_name=proc_name, params=sql_params)
|
||||||
|
data = session.execute(sql_string).fetchall()
|
||||||
|
session.commit()
|
||||||
|
session.expire_all()
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def exec_procedure_wo_result(session, proc_name, params, database: str = None):
|
||||||
|
sql_params = ",".join([f"@{name}='{value}'" if type(value) in [str] else f"@{name}={value}"
|
||||||
|
for name, value in params.items()])
|
||||||
|
dbstr = ""
|
||||||
|
if database:
|
||||||
|
dbstr = f"[{database}]."
|
||||||
|
sql_string = """
|
||||||
|
EXEC {dbstr}[dbo].[{proc_name}] {params}
|
||||||
|
""".format(dbstr=dbstr, proc_name=proc_name, params=sql_params)
|
||||||
|
session.execute(sql_string)
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
|
||||||
|
class FilterViewSet:
|
||||||
|
"""get"""
|
||||||
|
|
||||||
|
"""post"""
|
||||||
|
|
||||||
|
def get_filter_types(db: Session, data: schemas.FilterTypeInit):
|
||||||
|
return exec_procedure(db, 'uspGetFilterTypes', data.dict(), 'ISJKHRSTO')
|
||||||
|
|
||||||
|
def get_filter_list(db: Session, data: schemas.FilterListInit):
|
||||||
|
return exec_procedure(db, 'uspGetFilterList', data.dict(), 'ISJKHRSTO')
|
||||||
|
|
||||||
|
def set_filter_list(db: Session, data: schemas.FilterSetInit):
|
||||||
|
return exec_procedure_wo_result(db, 'uspSetFilterList', data.dict(), 'ISJKHRSTO')
|
61
isjkhrs/database.py
Normal file
61
isjkhrs/database.py
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
from sqlalchemy import create_engine, Table
|
||||||
|
from sqlalchemy.ext.declarative import declarative_base
|
||||||
|
from sqlalchemy.orm import sessionmaker
|
||||||
|
from typing import Optional, Dict
|
||||||
|
from dataclasses import dataclass
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Database:
|
||||||
|
engine: str
|
||||||
|
name: str
|
||||||
|
host: str
|
||||||
|
user: str
|
||||||
|
password: str
|
||||||
|
options: Optional[Dict] = None
|
||||||
|
|
||||||
|
def get_url(self):
|
||||||
|
option_str = ""
|
||||||
|
if self.options:
|
||||||
|
opt = [name+'='+'+'.join(value.split())
|
||||||
|
for name, value in self.options.items()]
|
||||||
|
option_str = "?"+"&".join(opt)
|
||||||
|
return f"{self.engine}://{self.user}:{self.password}@{self.host}/{self.name}{option_str}"
|
||||||
|
|
||||||
|
|
||||||
|
data = {}
|
||||||
|
|
||||||
|
with open('settings', 'r') as settings:
|
||||||
|
data_str = settings.read()
|
||||||
|
data = json.loads(data_str)
|
||||||
|
db = Database(**data.get('database'))
|
||||||
|
|
||||||
|
SQL_ALCHEMY_DATABASE_URL_MSSQL = db.get_url()
|
||||||
|
|
||||||
|
|
||||||
|
engine = create_engine(
|
||||||
|
SQL_ALCHEMY_DATABASE_URL_MSSQL, connect_args={"check_same_thread": False}
|
||||||
|
)
|
||||||
|
|
||||||
|
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
||||||
|
|
||||||
|
Base = declarative_base()
|
||||||
|
|
||||||
|
|
||||||
|
def get_table(tablename: str, dbname: str = None) -> Table:
|
||||||
|
metadata = Base.metadata
|
||||||
|
metadata.reflect(bind=engine)
|
||||||
|
|
||||||
|
if dbname == None:
|
||||||
|
dbname = db.name
|
||||||
|
|
||||||
|
return Table(tablename, metadata, schema=dbname+'.dbo', autoload=True, autoload_with=engine)
|
||||||
|
|
||||||
|
|
||||||
|
def get_db():
|
||||||
|
db = SessionLocal()
|
||||||
|
try:
|
||||||
|
yield db
|
||||||
|
finally:
|
||||||
|
db.close()
|
13
isjkhrs/isapi.py
Normal file
13
isjkhrs/isapi.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
from fastapi import APIRouter, Depends
|
||||||
|
from auth import oauth2
|
||||||
|
from auth.login.schemas import login as schemas
|
||||||
|
|
||||||
|
from isjkhrs import ismain
|
||||||
|
|
||||||
|
router = APIRouter()
|
||||||
|
|
||||||
|
router.include_router(
|
||||||
|
router=ismain.router,
|
||||||
|
prefix="",
|
||||||
|
responses={404: {"description": "IS is Not found"}}
|
||||||
|
)
|
@ -1,11 +1,28 @@
|
|||||||
from infosys.routers import general
|
from isjkhrs.routers import general, isjkhrsto
|
||||||
from fastapi import APIRouter, Depends
|
from fastapi import APIRouter, Depends
|
||||||
from auth import oauth2
|
from auth import oauth2
|
||||||
from auth.login.schemas import login as schemas
|
from auth.login.schemas import login as schemas
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
router.include_router(
|
def exec_procedure(session, proc_name, params, database: str = None):
|
||||||
router=general.router,
|
sql_params = ""
|
||||||
prefix="",
|
if params:
|
||||||
responses={404: {"description": "info is not found"}}
|
sql_params = ",".join([f"@{name}='{value}'" if type(value) in [str] else f"@{name}={value}"
|
||||||
)
|
for name, value in params.items()])
|
||||||
|
dbstr = ""
|
||||||
|
if database:
|
||||||
|
dbstr = f"[{database}]."
|
||||||
|
sql_string = """
|
||||||
|
DECLARE @return_value int;
|
||||||
|
EXEC @return_value = {dbstr}[dbo].[{proc_name}] {params};
|
||||||
|
SELECT 'Return Value' = @return_value;
|
||||||
|
""".format(dbstr=dbstr, proc_name=proc_name, params=sql_params)
|
||||||
|
print(sql_string)
|
||||||
|
data = session.execute(sql_string).fetchall()
|
||||||
|
session.commit()
|
||||||
|
session.expire_all()
|
||||||
|
return data
|
||||||
|
|
||||||
|
router.include_router(general.router, prefix="", tags=["is"])
|
||||||
|
|
||||||
|
router.include_router(isjkhrsto.router, prefix="/filter", tags=["FilterViewSet"])
|
@ -28,16 +28,3 @@ async def get_address(city_id: int, db= Depends(general.get_db)):
|
|||||||
@router.get('/getRegions')
|
@router.get('/getRegions')
|
||||||
async def get_region(db = Depends(general.get_db)):
|
async def get_region(db = Depends(general.get_db)):
|
||||||
return db.execute("SELECT id, name FROM General.dbo.vRegions").fetchall()
|
return db.execute("SELECT id, name FROM General.dbo.vRegions").fetchall()
|
||||||
|
|
||||||
@router.post('/get_filter_types', response_model=List[schemas.FilterTypeSerializer])
|
|
||||||
async def get_filter_types(request: schemas.FilterTypeInit, db: Session = Depends(general.get_db)):
|
|
||||||
return db.FilterViewSet.get_filter_types(db, request)
|
|
||||||
|
|
||||||
|
|
||||||
@router.post('/get_filter_list', response_model=List[schemas.FilterListSerializer])
|
|
||||||
async def get_filter_list(request: schemas.FilterListInit, db: Session = Depends(general.get_db)):
|
|
||||||
return crud.FilterViewSet.get_filter_list(db, request)
|
|
||||||
|
|
||||||
@router.post('/set_report_filter_list', response_model=List[schemas.FilterListSerializer])
|
|
||||||
async def set_report_filter_list(request: schemas.FilterSetInit, db: Session = Depends(general.get_db)):
|
|
||||||
return crud.FilterViewSet.set_filter_list(db, request)
|
|
@ -1,14 +1,12 @@
|
|||||||
import kv.schemas as schemas
|
|
||||||
import kv.crud as crud
|
|
||||||
from kv.database import get_db
|
|
||||||
from sqlalchemy.orm import Session
|
|
||||||
from fastapi import APIRouter, Depends
|
from fastapi import APIRouter, Depends
|
||||||
|
from kv.database import get_db
|
||||||
|
import isjkhrs.crud as crud
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
from typing import List
|
from typing import List
|
||||||
|
import isjkhrs.schemas as schemas
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
"""post"""
|
|
||||||
|
|
||||||
|
|
||||||
@router.post('/get_filter_types', response_model=List[schemas.FilterTypeSerializer])
|
@router.post('/get_filter_types', response_model=List[schemas.FilterTypeSerializer])
|
||||||
async def get_filter_types(request: schemas.FilterTypeInit, db: Session = Depends(get_db)):
|
async def get_filter_types(request: schemas.FilterTypeInit, db: Session = Depends(get_db)):
|
||||||
return crud.FilterViewSet.get_filter_types(db, request)
|
return crud.FilterViewSet.get_filter_types(db, request)
|
32
isjkhrs/schemas.py
Normal file
32
isjkhrs/schemas.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
from decimal import Decimal
|
||||||
|
from pydantic import BaseModel
|
||||||
|
from typing import Optional, List
|
||||||
|
from datetime import date, datetime
|
||||||
|
|
||||||
|
|
||||||
|
class FilterTypeInit(BaseModel):
|
||||||
|
IDUser: int
|
||||||
|
GetType: int
|
||||||
|
NeedClear: bool
|
||||||
|
|
||||||
|
|
||||||
|
class FilterListInit(BaseModel):
|
||||||
|
IDUser: int = 1
|
||||||
|
IDFilterType: int
|
||||||
|
|
||||||
|
|
||||||
|
class FilterSetInit(FilterListInit):
|
||||||
|
IDFilterObject: int
|
||||||
|
NeedClear: bool
|
||||||
|
|
||||||
|
class FilterTypeSerializer(BaseModel):
|
||||||
|
ID: int
|
||||||
|
Name: Optional[str] = None
|
||||||
|
IDParent: int = None
|
||||||
|
OrderField: int
|
||||||
|
|
||||||
|
|
||||||
|
class FilterListSerializer(BaseModel):
|
||||||
|
ID: int
|
||||||
|
Name: Optional[str] = None
|
||||||
|
IsChecked: bool
|
Binary file not shown.
23
kv/crud.py
23
kv/crud.py
@ -208,7 +208,7 @@ class PaymentViewSet:
|
|||||||
|
|
||||||
def save_receipt(db: Session, data: schemas.ReceiptSaveInit = None):
|
def save_receipt(db: Session, data: schemas.ReceiptSaveInit = None):
|
||||||
try:
|
try:
|
||||||
exec_procedure_wo_result(db, 'uspSaveReceipt', **data)
|
exec_procedure_wo_result(db, 'uspSaveReceipt', data.dict())
|
||||||
return {'msg': 'success'}
|
return {'msg': 'success'}
|
||||||
except:
|
except:
|
||||||
return {'msg': 'error'}
|
return {'msg': 'error'}
|
||||||
@ -232,24 +232,6 @@ class ReportViewSet:
|
|||||||
return exec_procedure(db, 'uspGetRentRegisterNotices', **data)
|
return exec_procedure(db, 'uspGetRentRegisterNotices', **data)
|
||||||
|
|
||||||
|
|
||||||
"""ReportFilterViewSet"""
|
|
||||||
|
|
||||||
|
|
||||||
class FilterViewSet:
|
|
||||||
"""get"""
|
|
||||||
|
|
||||||
"""post"""
|
|
||||||
|
|
||||||
def get_filter_types(db: Session, data: schemas.FilterTypeInit):
|
|
||||||
return exec_procedure(db, 'uspGetFilterTypes', data.dict())
|
|
||||||
|
|
||||||
def get_filter_list(db: Session, data: schemas.FilterListInit):
|
|
||||||
return exec_procedure(db, 'uspGetFilterList', data.dict())
|
|
||||||
|
|
||||||
def set_filter_list(db: Session, data: schemas.FilterSetInit):
|
|
||||||
return exec_procedure_wo_result(db, 'uspSetFilterList', data.dict())
|
|
||||||
|
|
||||||
|
|
||||||
"""AccrualViewSet"""
|
"""AccrualViewSet"""
|
||||||
|
|
||||||
|
|
||||||
@ -279,6 +261,9 @@ class RecalculationViewSet:
|
|||||||
def get_withdrawing_temp(db: Session, data: schemas.WithdrawingTempInit):
|
def get_withdrawing_temp(db: Session, data: schemas.WithdrawingTempInit):
|
||||||
return exec_procedure(db, 'uspGetWithdrawingTemp', **data)
|
return exec_procedure(db, 'uspGetWithdrawingTemp', **data)
|
||||||
|
|
||||||
|
def get_accruals_can_be_recalculated(db: Session, data: schemas.AccrualsCanBeRecalculatedInit):
|
||||||
|
return exec_procedure(db, 'uspGetAccrualsCanBeRecalculated', data.dict())
|
||||||
|
|
||||||
def save_withdrawing(db: Session, data: schemas.WithdrawingSave = None):
|
def save_withdrawing(db: Session, data: schemas.WithdrawingSave = None):
|
||||||
try:
|
try:
|
||||||
exec_procedure_wo_result(db, 'uspSaveWithdrawing', **data)
|
exec_procedure_wo_result(db, 'uspSaveWithdrawing', **data)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from fastapi import Depends, APIRouter
|
from fastapi import Depends, APIRouter
|
||||||
from requests import Session
|
from requests import Session
|
||||||
from kv.routers import address, objectvs, payment, personalaccount, reference, report, accrual, filter, turnover, recalculation
|
from kv.routers import address, objectvs, payment, personalaccount, reference, report, accrual, turnover, recalculation
|
||||||
from kv.database import get_db, get_table
|
from kv.database import get_db, get_table
|
||||||
from typing import List
|
from typing import List
|
||||||
from kv import schemas
|
from kv import schemas
|
||||||
@ -47,8 +47,6 @@ router.include_router(reference.router, prefix="/reference", tags=["ReferenceVie
|
|||||||
|
|
||||||
router.include_router(report.router, prefix="/report", tags=["ReportViewSet"])
|
router.include_router(report.router, prefix="/report", tags=["ReportViewSet"])
|
||||||
|
|
||||||
router.include_router(filter.router, prefix="/filter", tags=["FilterViewSet"])
|
|
||||||
|
|
||||||
router.include_router(turnover.router, prefix="/turnover", tags=["TurnOverViewSet"])
|
router.include_router(turnover.router, prefix="/turnover", tags=["TurnOverViewSet"])
|
||||||
|
|
||||||
router.include_router(recalculation.router, prefix="/recalculation", tags=["RecalculationViewSet"])
|
router.include_router(recalculation.router, prefix="/recalculation", tags=["RecalculationViewSet"])
|
||||||
|
Binary file not shown.
@ -27,6 +27,10 @@ async def set_report_filter_list(request: schemas.WithdrawingCheckInit, db: Sess
|
|||||||
async def get_withdrawing_temp(request: schemas.WithdrawingTempInit, db: Session = Depends(get_db)):
|
async def get_withdrawing_temp(request: schemas.WithdrawingTempInit, db: Session = Depends(get_db)):
|
||||||
return crud.RecalculationViewSet.get_withdrawing_temp(db, request)
|
return crud.RecalculationViewSet.get_withdrawing_temp(db, request)
|
||||||
|
|
||||||
|
@router.post('/get_accruals_can_be_recalculated', response_model=List[schemas.AccrualsCanBeRecalculatedSerializer])
|
||||||
|
async def get_accruals_can_be_recalculated(request: schemas.AccrualsCanBeRecalculatedInit, db: Session = Depends(get_db)):
|
||||||
|
return crud.RecalculationViewSet.get_accruals_can_be_recalculated(db, request)
|
||||||
|
|
||||||
|
|
||||||
@router.post('/save_withdrawing')
|
@router.post('/save_withdrawing')
|
||||||
async def save_withdrawing(request: schemas.WithdrawingSave, db: Session = Depends(get_db)):
|
async def save_withdrawing(request: schemas.WithdrawingSave, db: Session = Depends(get_db)):
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
from unicodedata import decimal
|
||||||
|
from numpy import datetime_as_string
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from typing import Optional, List
|
from typing import Optional, List
|
||||||
from datetime import date, datetime
|
from datetime import date, datetime
|
||||||
@ -48,19 +50,6 @@ class AdvancedSearchInit(AccountInit, CityInit):
|
|||||||
Patronymic: Optional[str] = None
|
Patronymic: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
class FilterTypeInit(BaseModel):
|
|
||||||
IDUser: int
|
|
||||||
GetType: int
|
|
||||||
NeedClear: bool
|
|
||||||
|
|
||||||
|
|
||||||
class FilterListInit(BaseModel):
|
|
||||||
IDUser: int = 1
|
|
||||||
IDFilterType: int
|
|
||||||
|
|
||||||
|
|
||||||
class FilterSetInit(FilterListInit):
|
|
||||||
IDFilterObject: int
|
|
||||||
|
|
||||||
|
|
||||||
class WithdrawingCheckSerializer(BaseModel):
|
class WithdrawingCheckSerializer(BaseModel):
|
||||||
@ -136,6 +125,12 @@ class WithdrawingTempInit(CashboxInit, GetTypeInit):
|
|||||||
class WithdrawingCheckInit(PersonalAccountInit, GetTypeInit, DateInit):
|
class WithdrawingCheckInit(PersonalAccountInit, GetTypeInit, DateInit):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class AccrualsCanBeRecalculatedInit(BaseModel):
|
||||||
|
IDPersonalAccount: int
|
||||||
|
DateBegin: str
|
||||||
|
DateEnd: str
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class WithdrawingSave(PersonalAccountInit, WithdrawingCheckSerializer, DateInit):
|
class WithdrawingSave(PersonalAccountInit, WithdrawingCheckSerializer, DateInit):
|
||||||
IDWithdrawingType: int
|
IDWithdrawingType: int
|
||||||
@ -161,12 +156,18 @@ class RecieptCalculateInit(PersonalAccountInit):
|
|||||||
AmountFine: float
|
AmountFine: float
|
||||||
|
|
||||||
|
|
||||||
class ReceiptSaveInit(RecieptCalculateInit):
|
class ReceiptSaveInit(BaseModel):
|
||||||
|
IDUser: int
|
||||||
|
IDCashbox: int
|
||||||
|
IDType: int
|
||||||
|
IDPersonalAccount: int
|
||||||
IDDebtContract: int
|
IDDebtContract: int
|
||||||
IDService: int
|
IDService: int
|
||||||
DateBegin: date
|
DateBegin: date
|
||||||
DateEnd: date
|
DateEnd: date
|
||||||
IDMoneyType: int
|
IDMoneyType: int
|
||||||
|
Amount: float
|
||||||
|
AmountFine: float
|
||||||
Note: Optional[str] = None
|
Note: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
@ -205,7 +206,7 @@ class MeteringDeviceTypeSerializer(BaseModel):
|
|||||||
|
|
||||||
class PersonalAccountSerializer(BaseModel):
|
class PersonalAccountSerializer(BaseModel):
|
||||||
IDAddress: int
|
IDAddress: int
|
||||||
IDTenants: int
|
IDTenants: int = None
|
||||||
IDWorker: Optional[int] = None
|
IDWorker: Optional[int] = None
|
||||||
Address: Optional[str] = None
|
Address: Optional[str] = None
|
||||||
ObjectStreetName: Optional[str] = None
|
ObjectStreetName: Optional[str] = None
|
||||||
@ -277,7 +278,7 @@ class EditPersonalAccountAddressInit(BaseModel):
|
|||||||
class AddressDetailInfoSerializer(BaseModel):
|
class AddressDetailInfoSerializer(BaseModel):
|
||||||
IDAddress: int
|
IDAddress: int
|
||||||
CadastralNumber: Optional[str] = None
|
CadastralNumber: Optional[str] = None
|
||||||
Privatization: bool
|
Privatization: float
|
||||||
Area: float
|
Area: float
|
||||||
AreaOwned: float
|
AreaOwned: float
|
||||||
AreaAdditional: float
|
AreaAdditional: float
|
||||||
@ -449,9 +450,9 @@ class PersonalAccountTOServicesSerializer(BaseModel):
|
|||||||
DateEnd: Optional[str] = None
|
DateEnd: Optional[str] = None
|
||||||
Spor: int
|
Spor: int
|
||||||
Por: int
|
Por: int
|
||||||
IDTariffPopulation: int
|
IDTariffPopulation: int = None
|
||||||
Tariff: float
|
Tariff: float = None
|
||||||
TariffProvider: float
|
TariffProvider: float = None
|
||||||
StandartVolume: float = None
|
StandartVolume: float = None
|
||||||
Volume: float
|
Volume: float
|
||||||
AmountSaldo: float
|
AmountSaldo: float
|
||||||
@ -618,14 +619,16 @@ class WithdrawingTypesSerializer(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
class WithdrawingTempSerializer(BaseModel):
|
class WithdrawingTempSerializer(BaseModel):
|
||||||
|
IDService: int
|
||||||
|
ServiceName: Optional[str] = None
|
||||||
|
Amount: float
|
||||||
|
|
||||||
|
class AccrualsCanBeRecalculatedSerializer(BaseModel):
|
||||||
id: int
|
id: int
|
||||||
IDService: int
|
IDService: int
|
||||||
ServiceName: Optional[str] = None
|
ServiceName: Optional[str] = None
|
||||||
Por: int
|
|
||||||
AmountAccrued: float
|
|
||||||
Amount: float
|
Amount: float
|
||||||
|
|
||||||
|
|
||||||
class ObjectDetailsSerializer(BaseModel):
|
class ObjectDetailsSerializer(BaseModel):
|
||||||
IDObject: str
|
IDObject: str
|
||||||
IDFias: Optional[str] = None
|
IDFias: Optional[str] = None
|
||||||
|
4
main.py
4
main.py
@ -5,7 +5,7 @@ from fastapi.middleware.cors import CORSMiddleware
|
|||||||
from kv import kv
|
from kv import kv
|
||||||
from auth import auth
|
from auth import auth
|
||||||
from kassa import kassa
|
from kassa import kassa
|
||||||
from infosys import ismain
|
from isjkhrs import isapi
|
||||||
import uvicorn
|
import uvicorn
|
||||||
|
|
||||||
middleware = [Middleware(
|
middleware = [Middleware(
|
||||||
@ -39,7 +39,7 @@ app.include_router(
|
|||||||
|
|
||||||
|
|
||||||
app.include_router(
|
app.include_router(
|
||||||
router=ismain.router,
|
router=isapi.router,
|
||||||
prefix='/is',
|
prefix='/is',
|
||||||
tags=['Информационная система'],
|
tags=['Информационная система'],
|
||||||
responses={404: {"description": "Not found"}}
|
responses={404: {"description": "Not found"}}
|
||||||
|
Reference in New Issue
Block a user