diff --git a/isjkhrs/crud.py b/isjkhrs/crud.py new file mode 100644 index 0000000..b2b89e8 --- /dev/null +++ b/isjkhrs/crud.py @@ -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') \ No newline at end of file diff --git a/isjkhrs/database.py b/isjkhrs/database.py new file mode 100644 index 0000000..8199b26 --- /dev/null +++ b/isjkhrs/database.py @@ -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() diff --git a/isjkhrs/isapi.py b/isjkhrs/isapi.py new file mode 100644 index 0000000..08aed6a --- /dev/null +++ b/isjkhrs/isapi.py @@ -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"}} +) diff --git a/isjkhrs/ismain.py b/isjkhrs/ismain.py index 80d5a28..e44dd5b 100644 --- a/isjkhrs/ismain.py +++ b/isjkhrs/ismain.py @@ -1,11 +1,28 @@ -from infosys.routers import general +from isjkhrs.routers import general, isjkhrsto from fastapi import APIRouter, Depends from auth import oauth2 from auth.login.schemas import login as schemas router = APIRouter() -router.include_router( - router=general.router, - prefix="", - responses={404: {"description": "info is not found"}} -) +def exec_procedure(session, proc_name, params, database: str = None): + sql_params = "" + if params: + 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"]) \ No newline at end of file diff --git a/isjkhrs/routers/general.py b/isjkhrs/routers/general.py index ba81aae..126ba42 100644 --- a/isjkhrs/routers/general.py +++ b/isjkhrs/routers/general.py @@ -27,17 +27,4 @@ async def get_address(city_id: int, db= Depends(general.get_db)): @router.get('/getRegions') async def get_region(db = Depends(general.get_db)): - 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) \ No newline at end of file + return db.execute("SELECT id, name FROM General.dbo.vRegions").fetchall() \ No newline at end of file diff --git a/kv/routers/filter.py b/isjkhrs/routers/isjkhrsto.py similarity index 86% rename from kv/routers/filter.py rename to isjkhrs/routers/isjkhrsto.py index fdd9c0f..065995e 100644 --- a/kv/routers/filter.py +++ b/isjkhrs/routers/isjkhrsto.py @@ -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 kv.database import get_db +import isjkhrs.crud as crud +from sqlalchemy.orm import Session from typing import List +import isjkhrs.schemas as schemas + router = APIRouter() -"""post""" - - @router.post('/get_filter_types', response_model=List[schemas.FilterTypeSerializer]) async def get_filter_types(request: schemas.FilterTypeInit, db: Session = Depends(get_db)): return crud.FilterViewSet.get_filter_types(db, request) @@ -21,4 +19,4 @@ async def get_filter_list(request: schemas.FilterListInit, db: Session = Depends @router.post('/set_report_filter_list', response_model=List[schemas.FilterListSerializer]) async def set_report_filter_list(request: schemas.FilterSetInit, db: Session = Depends(get_db)): - return crud.FilterViewSet.set_filter_list(db, request) + return crud.FilterViewSet.set_filter_list(db, request) \ No newline at end of file diff --git a/isjkhrs/schemas.py b/isjkhrs/schemas.py new file mode 100644 index 0000000..39d2207 --- /dev/null +++ b/isjkhrs/schemas.py @@ -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 \ No newline at end of file diff --git a/kv/__pycache__/isapi.cpython-39.pyc b/kv/__pycache__/isapi.cpython-39.pyc index 143b8d7..560a1d1 100644 Binary files a/kv/__pycache__/isapi.cpython-39.pyc and b/kv/__pycache__/isapi.cpython-39.pyc differ diff --git a/kv/crud.py b/kv/crud.py index c2df0da..711b66f 100644 --- a/kv/crud.py +++ b/kv/crud.py @@ -208,7 +208,7 @@ class PaymentViewSet: def save_receipt(db: Session, data: schemas.ReceiptSaveInit = None): try: - exec_procedure_wo_result(db, 'uspSaveReceipt', **data) + exec_procedure_wo_result(db, 'uspSaveReceipt', data.dict()) return {'msg': 'success'} except: return {'msg': 'error'} @@ -232,24 +232,6 @@ class ReportViewSet: 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""" @@ -279,6 +261,9 @@ class RecalculationViewSet: def get_withdrawing_temp(db: Session, data: schemas.WithdrawingTempInit): 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): try: exec_procedure_wo_result(db, 'uspSaveWithdrawing', **data) diff --git a/kv/isapi.py b/kv/isapi.py index cfd5fef..ba9f9af 100644 --- a/kv/isapi.py +++ b/kv/isapi.py @@ -1,6 +1,6 @@ from fastapi import Depends, APIRouter 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 typing import List 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(filter.router, prefix="/filter", tags=["FilterViewSet"]) - router.include_router(turnover.router, prefix="/turnover", tags=["TurnOverViewSet"]) router.include_router(recalculation.router, prefix="/recalculation", tags=["RecalculationViewSet"]) diff --git a/kv/routers/__pycache__/recalculation.cpython-39.pyc b/kv/routers/__pycache__/recalculation.cpython-39.pyc index bdaa4fa..7042a59 100644 Binary files a/kv/routers/__pycache__/recalculation.cpython-39.pyc and b/kv/routers/__pycache__/recalculation.cpython-39.pyc differ diff --git a/kv/routers/recalculation.py b/kv/routers/recalculation.py index 66b358d..f0aeba0 100644 --- a/kv/routers/recalculation.py +++ b/kv/routers/recalculation.py @@ -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)): 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') async def save_withdrawing(request: schemas.WithdrawingSave, db: Session = Depends(get_db)): diff --git a/kv/schemas.py b/kv/schemas.py index 1b9b42e..7d7ce44 100644 --- a/kv/schemas.py +++ b/kv/schemas.py @@ -1,4 +1,6 @@ from decimal import Decimal +from unicodedata import decimal +from numpy import datetime_as_string from pydantic import BaseModel from typing import Optional, List from datetime import date, datetime @@ -48,19 +50,6 @@ class AdvancedSearchInit(AccountInit, CityInit): 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): @@ -136,6 +125,12 @@ class WithdrawingTempInit(CashboxInit, GetTypeInit): class WithdrawingCheckInit(PersonalAccountInit, GetTypeInit, DateInit): pass +class AccrualsCanBeRecalculatedInit(BaseModel): + IDPersonalAccount: int + DateBegin: str + DateEnd: str + + class WithdrawingSave(PersonalAccountInit, WithdrawingCheckSerializer, DateInit): IDWithdrawingType: int @@ -161,12 +156,18 @@ class RecieptCalculateInit(PersonalAccountInit): AmountFine: float -class ReceiptSaveInit(RecieptCalculateInit): +class ReceiptSaveInit(BaseModel): + IDUser: int + IDCashbox: int + IDType: int + IDPersonalAccount: int IDDebtContract: int IDService: int DateBegin: date DateEnd: date IDMoneyType: int + Amount: float + AmountFine: float Note: Optional[str] = None @@ -205,7 +206,7 @@ class MeteringDeviceTypeSerializer(BaseModel): class PersonalAccountSerializer(BaseModel): IDAddress: int - IDTenants: int + IDTenants: int = None IDWorker: Optional[int] = None Address: Optional[str] = None ObjectStreetName: Optional[str] = None @@ -277,7 +278,7 @@ class EditPersonalAccountAddressInit(BaseModel): class AddressDetailInfoSerializer(BaseModel): IDAddress: int CadastralNumber: Optional[str] = None - Privatization: bool + Privatization: float Area: float AreaOwned: float AreaAdditional: float @@ -449,9 +450,9 @@ class PersonalAccountTOServicesSerializer(BaseModel): DateEnd: Optional[str] = None Spor: int Por: int - IDTariffPopulation: int - Tariff: float - TariffProvider: float + IDTariffPopulation: int = None + Tariff: float = None + TariffProvider: float = None StandartVolume: float = None Volume: float AmountSaldo: float @@ -618,14 +619,16 @@ class WithdrawingTypesSerializer(BaseModel): class WithdrawingTempSerializer(BaseModel): + IDService: int + ServiceName: Optional[str] = None + Amount: float + +class AccrualsCanBeRecalculatedSerializer(BaseModel): id: int IDService: int ServiceName: Optional[str] = None - Por: int - AmountAccrued: float Amount: float - class ObjectDetailsSerializer(BaseModel): IDObject: str IDFias: Optional[str] = None diff --git a/main.py b/main.py index 5333b6d..8e1abad 100644 --- a/main.py +++ b/main.py @@ -5,7 +5,7 @@ from fastapi.middleware.cors import CORSMiddleware from kv import kv from auth import auth from kassa import kassa -from infosys import ismain +from isjkhrs import isapi import uvicorn middleware = [Middleware( @@ -39,7 +39,7 @@ app.include_router( app.include_router( - router=ismain.router, + router=isapi.router, prefix='/is', tags=['Информационная система'], responses={404: {"description": "Not found"}}