Add graphql queries. Update handlers
parent
7bb4be9211
commit
9d01a17453
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||||
|
<data-source source="LOCAL" name="NETDBS_2@10.2.100.126" uuid="87379102-4799-4d65-9872-24e48c29e1fc">
|
||||||
|
<driver-ref>firebird</driver-ref>
|
||||||
|
<synchronize>true</synchronize>
|
||||||
|
<jdbc-driver>org.firebirdsql.jdbc.FBDriver</jdbc-driver>
|
||||||
|
<jdbc-url>jdbc:firebirdsql://10.2.100.126:3050/NETDBS_2?lc_ctype=WIN1251</jdbc-url>
|
||||||
|
<working-dir>$ProjectFileDir$</working-dir>
|
||||||
|
</data-source>
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -4,7 +4,7 @@ from fastapi.security import OAuth2PasswordBearer
|
||||||
|
|
||||||
from core.config import Config
|
from core.config import Config
|
||||||
from core.model.profile.db import ProfileDB
|
from core.model.profile.db import ProfileDB
|
||||||
from core.storage import profile
|
from core.storage import profile_storage
|
||||||
|
|
||||||
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/phone")
|
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/phone")
|
||||||
|
|
||||||
|
@ -18,4 +18,4 @@ def get_user_from_token(token: str = Depends(oauth2_scheme)) -> ProfileDB:
|
||||||
except jwt.exceptions.InvalidSignatureError as err:
|
except jwt.exceptions.InvalidSignatureError as err:
|
||||||
raise HTTPException(status_code=401, detail=str(err))
|
raise HTTPException(status_code=401, detail=str(err))
|
||||||
|
|
||||||
return profile.get_profile_by_id(data['profile_id'])
|
return profile_storage.get_profile_by_id(data['profile_id'])
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
class AppNoteDB(BaseModel):
|
||||||
|
id: int
|
||||||
|
user_id: int
|
||||||
|
task_id: int
|
||||||
|
note_status: int
|
||||||
|
tip: int
|
||||||
|
text: str
|
|
@ -1,414 +1,241 @@
|
||||||
import functools
|
|
||||||
import json
|
|
||||||
from datetime import date, datetime
|
from datetime import date, datetime
|
||||||
from typing import Self, Optional, Union, Any, Callable
|
from typing import Optional
|
||||||
|
from sqlalchemy import BIGINT, Column, ForeignKey
|
||||||
from firebird.driver import Cursor
|
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, aliased
|
||||||
from pydantic import BaseModel, Field, Json
|
|
||||||
from pypika import Query, Table
|
|
||||||
from pypika.queries import QueryBuilder
|
|
||||||
|
|
||||||
from core.database.db import redis_cache_obj
|
|
||||||
from core.storage.base import BaseStorage
|
|
||||||
|
|
||||||
from redis_cache import RedisCache
|
|
||||||
|
|
||||||
|
|
||||||
class __BaseDB(BaseModel, BaseStorage):
|
class __Base(DeclarativeBase):
|
||||||
__tablename__: str
|
pass
|
||||||
__read_only: bool = False
|
|
||||||
__table: Table | None = None
|
|
||||||
__state_changed = {}
|
|
||||||
__query: QueryBuilder | None = None
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def cache(cls) -> RedisCache:
|
|
||||||
return redis_cache_obj()
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_keys(cls):
|
|
||||||
return [x for x in cls.__dict__['__annotations__'].keys() if not x.startswith("__")]
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_table(cls) -> Self:
|
|
||||||
return Table(cls.__tablename__)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def fetch_one(cls, id: int) -> type[Self]:
|
|
||||||
t = cls.get_table()
|
|
||||||
keys = cls.get_keys()
|
|
||||||
stmt = Query.from_(t).select(*keys).where(getattr(t, keys[0]) == id)
|
|
||||||
with cls.get_cursor() as cur:
|
|
||||||
cur: Cursor
|
|
||||||
data = cur.execute(stmt.get_sql()).fetchone()
|
|
||||||
|
|
||||||
return cls(**{key: val for key, val in zip(keys, data)})
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def parse_orm(cls, row):
|
|
||||||
return cls(**{key: val for key, val in zip(cls.get_keys(), row)})
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def fetch_all(cls, where_query: QueryBuilder = None) -> list['Self']:
|
|
||||||
table = cls.get_table()
|
|
||||||
if not where_query:
|
|
||||||
stmt = Query.from_(table).select(*cls.get_keys())
|
|
||||||
else:
|
|
||||||
stmt = Query.from_(table).select(*cls.get_keys()).where(where_query)
|
|
||||||
|
|
||||||
with cls.get_cursor() as cursor:
|
|
||||||
cursor: Cursor
|
|
||||||
stmt: QueryBuilder
|
|
||||||
print(stmt)
|
|
||||||
data = cursor.execute(stmt.get_sql()).fetchall()
|
|
||||||
return [cls.parse_orm(d) for d in data]
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def fetch_related(cls) -> 'Self':
|
|
||||||
table = cls.get_table()
|
|
||||||
|
|
||||||
cls.__query = Query.from_(table)
|
|
||||||
return cls
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def create(cls, model: Self) -> Self:
|
|
||||||
if model.__read_only:
|
|
||||||
raise Exception("This model is read only")
|
|
||||||
|
|
||||||
# table = self.get_table()
|
|
||||||
|
|
||||||
# data = self.model_dump(mode='json', exclude_none=True, exclude={'id'}, exclude_unset=True)
|
|
||||||
# stmt = Query.into(table).columns(*[self.get_keys()]).insert(
|
|
||||||
# *[kwargs[key] for key in self.get_keys() if key in kwargs.keys()])
|
|
||||||
# with self.get_cursor() as cursor:
|
|
||||||
# cursor: Cursor
|
|
||||||
# cursor.execute(stmt.get_sql())
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def update(cls, model: Self) -> Self:
|
|
||||||
if model.__read_only:
|
|
||||||
raise Exception("This model is read only")
|
|
||||||
|
|
||||||
|
|
||||||
class MPLSTDB(__BaseDB):
|
class MPLSTDB(__Base):
|
||||||
__tablename__: str = "LST"
|
__tablename__ = "LST"
|
||||||
ID_LST: int
|
ID_LST: Mapped[int] = mapped_column(BIGINT, primary_key=True)
|
||||||
LST_ID_VLST: int
|
LST_ID_VLST: Mapped[int]
|
||||||
LST_NAME: str
|
LST_NAME: Mapped[str]
|
||||||
LST_NAME_SH: str
|
LST_NAME_SH: Mapped[str]
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def fetch_one(cls, id: int) -> type[Self]:
|
|
||||||
cache = cls.cache()
|
|
||||||
|
|
||||||
@cache.cache()
|
|
||||||
def wrapper(id):
|
|
||||||
return super(MPLSTDB, cls).fetch_one(id)
|
|
||||||
|
|
||||||
return wrapper(id)
|
|
||||||
|
|
||||||
|
|
||||||
class MPAppTaskDB(__BaseDB):
|
class MPAppTaskDB(__Base):
|
||||||
__tablename__: str = "APP_TASK"
|
__tablename__: str = "APP_TASK"
|
||||||
ID_APP_TASK: int | None = None
|
ID_APP_TASK: Mapped[int] = mapped_column(BIGINT, primary_key=True)
|
||||||
APP_TASK_ID_SOTR: int = None
|
APP_TASK_ID_SOTR: Mapped[int] = mapped_column(BIGINT)
|
||||||
APP_TASK_ID_APP_TASK: int = None
|
APP_TASK_ID_APP_TASK: Mapped[int] = mapped_column(BIGINT, ForeignKey("APP_TASK.ID_APP_TASK"))
|
||||||
APP_TASK_DT_START_PLN: datetime = None
|
APP_TASK_DT_START_PLN: Mapped[datetime]
|
||||||
APP_TASK_DT_END_PLN: datetime = None
|
APP_TASK_DT_END_PLN: Mapped[datetime]
|
||||||
APP_TASK_DT_START_FACT: datetime | None = None
|
APP_TASK_DT_START_FACT: Mapped[datetime | None]
|
||||||
APP_TASK_DT_END_FACT: datetime | None = None
|
APP_TASK_DT_END_FACT: Mapped[datetime | None]
|
||||||
APP_TASK_STATUS: int = None
|
APP_TASK_STATUS: Mapped[int]
|
||||||
APP_TASK_TIP: int = None
|
APP_TASK_TIP: Mapped[int]
|
||||||
APP_TASK_TEXT: str = None
|
APP_TASK_TEXT: Mapped[str]
|
||||||
APP_TASK_DEL: int = None
|
APP_TASK_DEL: Mapped[int]
|
||||||
|
|
||||||
|
subtasks: Mapped['MPAppTaskDB'] = relationship('MPAppTaskDB', remote_side=[ID_APP_TASK])
|
||||||
|
|
||||||
@property
|
|
||||||
def status(self) -> MPLSTDB:
|
|
||||||
return MPLSTDB.fetch_one(self.APP_TASK_STATUS)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_subtask(self) -> bool:
|
def is_subtask(self) -> bool:
|
||||||
return self.ID_APP_TASK != self.APP_TASK_ID_APP_TASK
|
return self.ID_APP_TASK != self.APP_TASK_ID_APP_TASK
|
||||||
|
|
||||||
@property
|
|
||||||
def task_type(self) -> MPLSTDB:
|
|
||||||
return MPLSTDB.fetch_one(self.APP_TASK_TIP)
|
|
||||||
|
|
||||||
@property
|
class MPAppEventDB(__Base):
|
||||||
def subtasks(self) -> list['MPAppTaskDB']:
|
|
||||||
t: MPAppTaskDB = MPAppTaskDB.get_table()
|
|
||||||
return MPAppTaskDB.fetch_all(
|
|
||||||
(t.APP_TASK_ID_APP_TASK == self.ID_APP_TASK) & (t.APP_TASK_ID_APP_TASK != t.ID_APP_TASK) & (
|
|
||||||
t.APP_TASK_DEL == 0))
|
|
||||||
|
|
||||||
@property
|
|
||||||
def events(self) -> list['MPAppEventDB']:
|
|
||||||
return MPAppEventDB.fetch_all(MPAppEventDB.get_table().APP_EVENT_ID_REC == self.ID_APP_TASK)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def params(self) -> list['MPAppParamDB']:
|
|
||||||
return MPAppParamDB.fetch_all(MPAppParamDB.get_table().APP_PARAM_ID_REC == self.ID_APP_TASK)
|
|
||||||
|
|
||||||
|
|
||||||
class EventData(__BaseDB):
|
|
||||||
key: MPLSTDB
|
|
||||||
value: Any
|
|
||||||
|
|
||||||
|
|
||||||
class MPAppEventDB(__BaseDB):
|
|
||||||
__tablename__: str = "APP_EVENT"
|
__tablename__: str = "APP_EVENT"
|
||||||
ID_APP_EVENT: int = None
|
ID_APP_EVENT: Mapped[int] = mapped_column(primary_key=True)
|
||||||
APP_EVENT_ID_SOTR: int = None
|
APP_EVENT_ID_SOTR: Mapped[int]
|
||||||
APP_EVENT_ID_REC: int = None
|
APP_EVENT_ID_REC: Mapped[int]
|
||||||
APP_EVENT_VID: int = None
|
APP_EVENT_VID: Mapped[int]
|
||||||
APP_EVENT_TIP: int = None
|
APP_EVENT_TIP: Mapped[int]
|
||||||
APP_EVENT_DT: datetime | None = None
|
APP_EVENT_DT: Mapped[datetime | None]
|
||||||
APP_EVENT_TEXT: str | None = None
|
APP_EVENT_TEXT: Mapped[str | None]
|
||||||
APP_EVENT_DATA: Json
|
APP_EVENT_DATA: Mapped[str]
|
||||||
APP_EVENT_DEL: int = 0
|
APP_EVENT_DEL: Mapped[int]
|
||||||
|
|
||||||
@property
|
|
||||||
def event_type(self) -> MPLSTDB:
|
|
||||||
return MPLSTDB.fetch_one(self.APP_EVENT_TIP)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def event_data(self) -> list[EventData]:
|
|
||||||
return [EventData(key=MPLSTDB.fetch_one(key), value=value) for d in list(self.APP_EVENT_DATA) for key, value in
|
|
||||||
d.items()]
|
|
||||||
|
|
||||||
|
|
||||||
class MPMSTDB(__BaseDB):
|
class MPMSTDB(__Base):
|
||||||
__read_only = True
|
|
||||||
__tablename__ = "MST"
|
__tablename__ = "MST"
|
||||||
ID_MST: int = Field(default=0)
|
ID_MST: Mapped[int] = mapped_column(primary_key=True)
|
||||||
MST_PR_OTHER: int = Field(default=0)
|
MST_PR_OTHER: Mapped[int]
|
||||||
MST_ID_KG: int = Field(default=0)
|
MST_ID_KG: Mapped[int]
|
||||||
MST_ID_SRV: int = Field(default=0)
|
MST_ID_SRV: Mapped[int]
|
||||||
MST_ID_SETTLEMENT: Optional[int] = Field(default=0)
|
MST_ID_SETTLEMENT: Mapped[Optional[int]]
|
||||||
MST_SID: Optional[str] = Field(default=None)
|
MST_SID: Mapped[Optional[str]]
|
||||||
MST_NAME: Optional[str] = Field(default=None)
|
MST_NAME: Mapped[Optional[str]]
|
||||||
MST_CLI_NAME: Optional[str] = Field(default=None)
|
MST_CLI_NAME: Mapped[Optional[str]]
|
||||||
MST_CODE: int = Field(default=0)
|
MST_CODE: Mapped[int]
|
||||||
MST_CODE_PODR_NDS: int | None = Field(default=0)
|
MST_CODE_PODR_NDS: Mapped[int | None]
|
||||||
MST_CODE_PODR_BN: int | None = Field(default=0)
|
MST_CODE_PODR_BN: Mapped[int | None]
|
||||||
MST_PR_TTNINPUT: int = Field(default=0)
|
MST_PR_TTNINPUT: Mapped[int]
|
||||||
MST_PR_TTNOUTPUT: int = Field(default=0)
|
MST_PR_TTNOUTPUT: Mapped[int]
|
||||||
MST_PR_AEX: int = Field(default=0)
|
MST_PR_AEX: Mapped[int]
|
||||||
MST_PR_AEX_ADR: Optional[int] = Field(default=0)
|
MST_PR_AEX_ADR: Mapped[Optional[int]]
|
||||||
MST_ID_MST_TTNOUTPUT: int = Field(default=0)
|
MST_ID_MST_TTNOUTPUT: Mapped[int]
|
||||||
MST_PR_SORT: int = Field(default=0)
|
MST_PR_SORT: Mapped[int]
|
||||||
MST_PR_PVZ: int = Field(default=0)
|
MST_PR_PVZ: Mapped[int]
|
||||||
MST_PR_VIRT: int = Field(default=0)
|
MST_PR_VIRT: Mapped[int]
|
||||||
MST_PR_INOTHER: int = Field(default=0)
|
MST_PR_INOTHER: Mapped[int]
|
||||||
MST_PR_ZAKG: int = Field(default=0)
|
MST_PR_ZAKG: Mapped[int]
|
||||||
MST_PR_FAR: int = Field(default=0)
|
MST_PR_FAR: Mapped[int]
|
||||||
MST_PR_KKT: int = Field(default=0)
|
MST_PR_KKT: Mapped[int]
|
||||||
MST_PR_CC: int = Field(default=0)
|
MST_PR_CC: Mapped[int]
|
||||||
MST_PR_AS: int = Field(default=0)
|
MST_PR_AS: Mapped[int]
|
||||||
MST_KM: int = Field(default=0)
|
MST_KM: Mapped[int]
|
||||||
MST_MP: int = Field(default=0)
|
MST_MP: Mapped[int]
|
||||||
MST_ID_AGENT_AS: int = Field(default=0)
|
MST_ID_AGENT_AS: Mapped[int]
|
||||||
MST_PR_NOLIM_AS: int = Field(default=0)
|
MST_PR_NOLIM_AS: Mapped[int]
|
||||||
MST_PR_WC_AS: int = Field(default=0)
|
MST_PR_WC_AS: Mapped[int]
|
||||||
MST_PR_TRS: int = Field(default=0)
|
MST_PR_TRS: Mapped[int]
|
||||||
MST_ID_REGION: int = Field(default=0)
|
MST_ID_REGION: Mapped[int]
|
||||||
MST_ADDRESS_CODE: int = Field(default=0)
|
MST_ADDRESS_CODE: Mapped[int]
|
||||||
MST_ID_KLADR_DOM: Optional[int] = Field(default=0)
|
MST_ID_KLADR_DOM: Mapped[Optional[int]]
|
||||||
MST_SHIR: float = Field(default=0.0)
|
MST_SHIR: Mapped[float]
|
||||||
MST_DOLG: float = Field(default=0.0)
|
MST_DOLG: Mapped[float]
|
||||||
MST_ADR_STOR: Optional[str] = Field(default=None)
|
MST_ADR_STOR: Mapped[Optional[str]]
|
||||||
MST_FUNC_MASK: int = Field(default=0)
|
MST_FUNC_MASK: Mapped[int]
|
||||||
MST_ID_SRV_CALL: int = Field(default=0)
|
MST_ID_SRV_CALL: Mapped[int]
|
||||||
MST_ID_MST_CALL: int = Field(default=0)
|
MST_ID_MST_CALL: Mapped[int]
|
||||||
MST_PR_DIRECT: int = Field(default=0)
|
MST_PR_DIRECT: Mapped[int]
|
||||||
MST_NAME_DIRECT: Optional[str] = Field(default=None)
|
MST_NAME_DIRECT: Mapped[Optional[str]]
|
||||||
MST_PR_NOTE: int = Field(default=0)
|
MST_PR_NOTE: Mapped[int]
|
||||||
MST_PR_NOTSITE: int = Field(default=0)
|
MST_PR_NOTSITE: Mapped[int]
|
||||||
MST_PR_GREEN: int = Field(default=0)
|
MST_PR_GREEN: Mapped[int]
|
||||||
MST_PR_GREENORK: int = Field(default=0)
|
MST_PR_GREENORK: Mapped[int]
|
||||||
MST_PR_GREENPRINTER: int = Field(default=0)
|
MST_PR_GREENPRINTER: Mapped[int]
|
||||||
MST_PR_VID_TR_VD: int = Field(default=0)
|
MST_PR_VID_TR_VD: Mapped[int]
|
||||||
MST_PR_BAN_IN: int = Field(default=0)
|
MST_PR_BAN_IN: Mapped[int]
|
||||||
MST_PR_NO_CLIENT_CODES: int = Field(default=0)
|
MST_PR_NO_CLIENT_CODES: Mapped[int]
|
||||||
MST_PR_NO_STTN02: int = Field(default=0)
|
MST_PR_NO_STTN02: Mapped[int]
|
||||||
MST_PR_NO_EEU: int = Field(default=0)
|
MST_PR_NO_EEU: Mapped[int]
|
||||||
MST_VID_CALC_FOBYOM: int = Field(default=0)
|
MST_VID_CALC_FOBYOM: Mapped[int]
|
||||||
MST_TXT: Optional[str] = Field(default=None)
|
MST_TXT: Mapped[Optional[str]]
|
||||||
MST_DEL: int = Field(default=0)
|
MST_DEL: Mapped[int]
|
||||||
MST_CH: Optional[datetime] = Field(default=None)
|
MST_CH: Mapped[Optional[datetime]]
|
||||||
MST_WCH: int = Field(default=0)
|
MST_WCH: Mapped[int]
|
||||||
MST_IMP: Optional[datetime] = Field(default=None)
|
MST_IMP: Mapped[Optional[datetime]]
|
||||||
MST_MPOST: int = Field(default=0)
|
MST_MPOST: Mapped[int]
|
||||||
MST_SEANS: int = Field(default=0)
|
MST_SEANS: Mapped[int]
|
||||||
MST_OWNERMST: int = Field(default=0)
|
MST_OWNERMST: Mapped[int]
|
||||||
MST_CR: Optional[datetime] = Field(default=None)
|
MST_CR: Mapped[Optional[datetime]]
|
||||||
MST_WCR: int = Field(default=0)
|
MST_WCR: Mapped[int]
|
||||||
MST_FIMP: Optional[datetime] = Field(default=None)
|
MST_FIMP: Mapped[Optional[datetime]]
|
||||||
MST_ID_MST_SYNONYM: int = Field(default=0)
|
MST_ID_MST_SYNONYM: Mapped[int]
|
||||||
MST_NAME_OLD: Optional[str] = Field(default=None)
|
MST_NAME_OLD: Mapped[Optional[str]]
|
||||||
MST_SRC_OLD: int = Field(default=0)
|
MST_SRC_OLD: Mapped[int]
|
||||||
MST_UPPERNAME_OLD: Optional[str] = Field(default=None)
|
MST_UPPERNAME_OLD: Mapped[Optional[str]]
|
||||||
MST_TXT_AEX: Optional[str] = Field(default=None)
|
MST_TXT_AEX: Mapped[Optional[str]]
|
||||||
MST_PR_NODOOR_AEX: int = Field(default=0)
|
MST_PR_NODOOR_AEX: Mapped[int]
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def fetch_one(cls, id: int) -> type[Self]:
|
|
||||||
cache = cls.cache()
|
|
||||||
|
|
||||||
@cache.cache()
|
|
||||||
def wrapper(id):
|
|
||||||
return super(MPMSTDB, cls).fetch_one(id)
|
|
||||||
|
|
||||||
return wrapper(id)
|
|
||||||
|
|
||||||
|
|
||||||
class MPTRSDB(__BaseDB):
|
class MPTRSDB(__Base):
|
||||||
__tablename__ = "TRS"
|
__tablename__ = "TRS"
|
||||||
__read_only = True
|
ID_TRS: Mapped[int] = mapped_column(primary_key=True)
|
||||||
ID_TRS: int = Field(default=0)
|
TRS_PR_TEST: Mapped[int]
|
||||||
TRS_PR_TEST: int = Field(default=0)
|
TRS_PR_TEST_ID_SOTR: Mapped[int]
|
||||||
TRS_PR_TEST_ID_SOTR: int = Field(default=0)
|
TRS_PR_TEST_DT: Mapped[Optional[datetime]]
|
||||||
TRS_PR_TEST_DT: Optional[datetime] = Field(default=None)
|
TRS_PR: Mapped[int]
|
||||||
TRS_PR: int = Field(default=0)
|
TRS_PR_UP: Mapped[int]
|
||||||
TRS_PR_UP: int = Field(default=0)
|
TRS_ID_LST_PR: Mapped[int]
|
||||||
TRS_ID_LST_PR: int = Field(default=0)
|
TRS_ID_LST_VID: Mapped[int]
|
||||||
TRS_ID_LST_VID: int = Field(default=0)
|
TRS_ID_LSTU_TIP: Mapped[int]
|
||||||
TRS_ID_LSTU_TIP: int = Field(default=0)
|
TRS_SID: Mapped[Optional[str]]
|
||||||
TRS_SID: Optional[str] = Field(default=None)
|
TRS_SID_GOST: Mapped[Optional[str]]
|
||||||
TRS_SID_GOST: Optional[str] = Field(default=None)
|
TRS_SID_OLD: Mapped[Optional[str]]
|
||||||
TRS_SID_OLD: Optional[str] = Field(default=None)
|
TRS_SRC_OLD: Mapped[int]
|
||||||
TRS_SRC_OLD: int = Field(default=0)
|
TRS_PR_VLAD: Mapped[int]
|
||||||
TRS_PR_VLAD: int = Field(default=0)
|
TRS_ID_AGENT_AS: Mapped[int]
|
||||||
TRS_ID_AGENT_AS: int = Field(default=0)
|
TRS_VES: Mapped[float]
|
||||||
TRS_VES: float = Field(default=0.0)
|
TRS_OBYOM: Mapped[float]
|
||||||
TRS_OBYOM: float = Field(default=0.0)
|
TRS_PR_LTOR: Mapped[int]
|
||||||
TRS_PR_LTOR: int = Field(default=0)
|
TRS_PR_LLEN: Mapped[int]
|
||||||
TRS_PR_LLEN: int = Field(default=0)
|
TRS_PR_LTOP: Mapped[int]
|
||||||
TRS_PR_LTOP: int = Field(default=0)
|
TRS_PR_TEPL: Mapped[int]
|
||||||
TRS_PR_TEPL: int = Field(default=0)
|
TRS_PR_TEPL_WHERE: Mapped[int]
|
||||||
TRS_PR_TEPL_WHERE: int = Field(default=0)
|
TRS_OBYOM_TEPL: Mapped[float]
|
||||||
TRS_OBYOM_TEPL: float = Field(default=0.0)
|
TRS_PR_NOZAGRGRUZ: Mapped[int]
|
||||||
TRS_PR_NOZAGRGRUZ: int = Field(default=0)
|
TRS_CNT_AXIS: Mapped[int]
|
||||||
TRS_CNT_AXIS: int = Field(default=0)
|
TRS_PRIM: Mapped[Optional[str]]
|
||||||
TRS_PRIM: Optional[str] = Field(default=None)
|
TRS_INFO: Mapped[Optional[str]]
|
||||||
TRS_INFO: Optional[str] = Field(default=None)
|
TRS_TARA: Mapped[Optional[float]]
|
||||||
TRS_TARA: Optional[float] = Field(default=0.0)
|
TRS_TYPEPROPERTY: Mapped[int]
|
||||||
TRS_TYPEPROPERTY: int = Field(default=0)
|
TRS_DOGAREND: Mapped[Optional[str]]
|
||||||
TRS_DOGAREND: Optional[str] = Field(default=None)
|
TRS_1C_D_AKT: Mapped[Optional[date]]
|
||||||
TRS_1C_D_AKT: Optional[date] = Field(default=None)
|
TRS_1C_NOMMSG: Mapped[int]
|
||||||
TRS_1C_NOMMSG: int = Field(default=0)
|
TRS_1C_DEL: Mapped[int]
|
||||||
TRS_1C_DEL: int = Field(default=0)
|
TRS_1C_DATEEND: Mapped[Optional[date]]
|
||||||
TRS_1C_DATEEND: Optional[date] = Field(default=None)
|
TRS_DEL: Mapped[int]
|
||||||
TRS_DEL: int = Field(default=0)
|
TRS_CR: Mapped[Optional[datetime]]
|
||||||
TRS_CR: Optional[datetime] = Field(default=None)
|
TRS_WCR: Mapped[int]
|
||||||
TRS_WCR: int = Field(default=0)
|
TRS_CH: Mapped[Optional[datetime]]
|
||||||
TRS_CH: Optional[datetime] = Field(default=None)
|
TRS_WCH: Mapped[int]
|
||||||
TRS_WCH: int = Field(default=0)
|
TRS_OWNERMST: Mapped[int]
|
||||||
TRS_OWNERMST: int = Field(default=0)
|
TRS_SEANS: Mapped[int]
|
||||||
TRS_SEANS: int = Field(default=0)
|
TRS_IMP: Mapped[Optional[datetime]]
|
||||||
TRS_IMP: Optional[datetime] = Field(default=None)
|
TRS_FIMP: Mapped[Optional[datetime]]
|
||||||
TRS_FIMP: Optional[datetime] = Field(default=None)
|
TRS_MPOST: Mapped[int]
|
||||||
TRS_MPOST: int = Field(default=0)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def fetch_one(cls, id: int) -> type[Self]:
|
|
||||||
cache = cls.cache()
|
|
||||||
|
|
||||||
@cache.cache()
|
|
||||||
def wrapper(id):
|
|
||||||
return super(MPTRSDB, cls).fetch_one(id)
|
|
||||||
|
|
||||||
return wrapper(id)
|
|
||||||
|
|
||||||
|
|
||||||
class MPMarshDB(__BaseDB):
|
class MPMarshDB(__Base):
|
||||||
__read_only = True
|
|
||||||
__tablename__ = "MARSH"
|
__tablename__ = "MARSH"
|
||||||
ID_MARSH: int = Field(default=0)
|
ID_MARSH: Mapped[int] = mapped_column(primary_key=True)
|
||||||
MARSH_PR: int = Field(default=0)
|
MARSH_PR: Mapped[int]
|
||||||
MARSH_PR_PLAN: int = Field(default=0)
|
MARSH_PR_PLAN: Mapped[int]
|
||||||
MARSH_PR_VLAD: int = Field(default=0)
|
MARSH_PR_VLAD: Mapped[int]
|
||||||
MARSH_PR_DOP: int = Field(default=0)
|
MARSH_PR_DOP: Mapped[int]
|
||||||
MARSH_PR_TEPL: int = Field(default=0)
|
MARSH_PR_TEPL: Mapped[int]
|
||||||
MARSH_KEY_GPREF: Optional[str] = Field(default=None, min_length=1, max_length=16)
|
MARSH_KEY_GPREF: Mapped[Optional[str]]
|
||||||
MARSH_KEY_PREF: Optional[str] = Field(default=None, min_length=1, max_length=32)
|
MARSH_KEY_PREF: Mapped[Optional[str]]
|
||||||
MARSH_NAME: Optional[str] = Field(default=None, min_length=1, max_length=128)
|
MARSH_NAME: Mapped[Optional[str]]
|
||||||
MARSH_D_N: Optional[date] = Field(default=None)
|
MARSH_D_N: Mapped[Optional[date]]
|
||||||
MARSH_D_K: Optional[date] = Field(default=None)
|
MARSH_D_K: Mapped[Optional[date]]
|
||||||
MARSH_ID_MST_OTPR: int = Field(default=0)
|
MARSH_ID_MST_OTPR: Mapped[int]
|
||||||
MARSH_ID_MST_NAZN: int = Field(default=0)
|
MARSH_ID_MST_NAZN: Mapped[int]
|
||||||
MARSH_DAYS_WEEK: int = Field(default=0)
|
MARSH_DAYS_WEEK: Mapped[int]
|
||||||
MARSH_T_OTPR: float = Field(default=0.0)
|
MARSH_T_OTPR: Mapped[float]
|
||||||
MARSH_DATE_OUT: Optional[date] = Field(default=None)
|
MARSH_DATE_OUT: Mapped[Optional[date]]
|
||||||
MARSH_PRICE: Optional[float] = Field(default=0.0)
|
MARSH_PRICE: Mapped[Optional[float]]
|
||||||
MARSH_KM: Optional[float] = Field(default=0.0)
|
MARSH_KM: Mapped[Optional[float]]
|
||||||
MARSH_TXT: Optional[str] = Field(default=None, min_length=1, max_length=512)
|
MARSH_TXT: Mapped[Optional[str]]
|
||||||
MARSH_DEL: int = Field(default=0)
|
MARSH_DEL: Mapped[int]
|
||||||
|
|
||||||
|
|
||||||
class MPMarshTRSDB(__BaseDB):
|
class MPMarshTRSDB(__Base):
|
||||||
__tablename__ = "MARSH_TRS"
|
__tablename__ = "MARSH_TRS"
|
||||||
__read_only = True
|
ID_MARSH_TRS: Mapped[int] = mapped_column(primary_key=True)
|
||||||
ID_MARSH_TRS: int = Field(default=0)
|
MARSH_TRS_ID_MARSH: Mapped[int]
|
||||||
MARSH_TRS_ID_MARSH: int = Field(default=0)
|
MARSH_TRS_DATE: Mapped[Optional[date]]
|
||||||
MARSH_TRS_DATE: Optional[date] = Field(default=None)
|
MARSH_TRS_ID_TRS: Mapped[int]
|
||||||
MARSH_TRS_ID_TRS: int = Field(default=0)
|
MARSH_TRS_TRS_PR_COLDONLY: Mapped[Optional[int]]
|
||||||
MARSH_TRS_TRS_PR_COLDONLY: Optional[int] = Field(default=0)
|
MARSH_TRS_ID_PRIC: Mapped[int]
|
||||||
MARSH_TRS_ID_PRIC: int = Field(default=0)
|
MARSH_TRS_PRIC_PR_COLDONLY: Mapped[Optional[int]]
|
||||||
MARSH_TRS_PRIC_PR_COLDONLY: Optional[int] = Field(default=0)
|
MARSH_TRS_ID_SOTR: Mapped[int]
|
||||||
MARSH_TRS_ID_SOTR: int = Field(default=0)
|
MARSH_TRS_DT_DELIVERY: Mapped[Optional[datetime]]
|
||||||
MARSH_TRS_DT_DELIVERY: Optional[datetime] = Field(default=None)
|
MARSH_TRS_PR: Mapped[int]
|
||||||
MARSH_TRS_PR: int = Field(default=0)
|
MARSH_TRS_COMMENT: Mapped[Optional[str]]
|
||||||
MARSH_TRS_COMMENT: Optional[str] = Field(default=None, max_length=4096)
|
MARSH_TRS_TARIFF: Mapped[float]
|
||||||
MARSH_TRS_TARIFF: float = Field(default=0.0)
|
MARSH_TRS_DEL: Mapped[int]
|
||||||
MARSH_TRS_DEL: int = Field(default=0)
|
MARSH_TRS_OWNERMST: Mapped[int]
|
||||||
MARSH_TRS_OWNERMST: int = Field(default=0)
|
MARSH_TRS_MPOST: Mapped[Optional[int]]
|
||||||
MARSH_TRS_MPOST: Optional[int] = Field(default=0)
|
MARSH_TRS_CR: Mapped[Optional[datetime]]
|
||||||
MARSH_TRS_CR: Optional[datetime] = Field(default=None)
|
MARSH_TRS_WCR: Mapped[int]
|
||||||
MARSH_TRS_WCR: int = Field(default=0)
|
MARSH_TRS_IMP: Mapped[Optional[datetime]]
|
||||||
MARSH_TRS_IMP: Optional[datetime] = Field(default=None)
|
MARSH_TRS_CH: Mapped[Optional[datetime]]
|
||||||
MARSH_TRS_CH: Optional[datetime] = Field(default=None)
|
MARSH_TRS_WCH: Mapped[int]
|
||||||
MARSH_TRS_WCH: int = Field(default=0)
|
MARSH_TRS_SEANS: Mapped[int]
|
||||||
MARSH_TRS_SEANS: int = Field(default=0)
|
MARSH_TRS_FIMP: Mapped[Optional[datetime]]
|
||||||
MARSH_TRS_FIMP: Optional[datetime] = Field(default=None)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def marsh(self) -> MPMarshDB:
|
|
||||||
return MPMarshDB.fetch_one(self.MARSH_TRS_ID_MARSH)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def trs(self) -> MPTRSDB:
|
|
||||||
return MPTRSDB.fetch_one(self.MARSH_TRS_ID_TRS)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def trailer(self) -> MPTRSDB:
|
|
||||||
return MPTRSDB.fetch_one(self.MARSH_TRS_ID_PRIC)
|
|
||||||
|
|
||||||
|
|
||||||
class MPAppParamDB(__BaseDB):
|
class MPAppParamDB(__Base):
|
||||||
__tablename__ = "APP_PARAM"
|
__tablename__ = "APP_PARAM"
|
||||||
__read_only = True
|
APP_PARAM_ID_REC: Mapped[int] = mapped_column(primary_key=True)
|
||||||
APP_PARAM_ID_REC: int = Field(default=0)
|
APP_PARAM_STR: Mapped[Optional[str]]
|
||||||
APP_PARAM_STR: Optional[str] = Field(default=None, min_length=1, max_length=1024)
|
APP_PARAM_VID: Mapped[int]
|
||||||
APP_PARAM_VID: int = Field(default=0)
|
APP_PARAM_TIP: Mapped[int]
|
||||||
APP_PARAM_TIP: int = Field(default=0)
|
APP_PARAM_DEL: Mapped[int]
|
||||||
APP_PARAM_DEL: int = Field(default=0)
|
APP_PARAM_CR: Mapped[Optional[datetime]]
|
||||||
APP_PARAM_CR: Optional[datetime] = Field(default=None)
|
APP_PARAM_WCR: Mapped[int]
|
||||||
APP_PARAM_WCR: int = Field(default=0)
|
APP_PARAM_CH: Mapped[Optional[datetime]]
|
||||||
APP_PARAM_CH: Optional[datetime] = Field(default=None)
|
APP_PARAM_WCH: Mapped[int]
|
||||||
APP_PARAM_WCH: int = Field(default=0)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def param_type(self) -> MPLSTDB:
|
|
||||||
return MPLSTDB.fetch_one(self.APP_PARAM_TIP)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def related_table(self) -> Union['MPMSTDB', 'MPMarshTRSDB', 'MPTRSDB', 'MPMarshDB']:
|
# SET RELATIONS
|
||||||
query = {
|
|
||||||
"ID_MARSH_TRS": MPMarshTRSDB,
|
|
||||||
"ID_MST": MPMSTDB,
|
|
||||||
"ID_TRS": MPTRSDB,
|
|
||||||
"ID_MARSH": MPMarshDB
|
|
||||||
}
|
|
||||||
return query[self.param_type.LST_NAME_SH].fetch_one(self.APP_PARAM_STR)
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
|
from .base import BaseStorage
|
||||||
from .profile_storage import Storage as ProfileStorage
|
from .profile_storage import Storage as ProfileStorage
|
||||||
from .task_storage import Storage as TaskStorage
|
from .task_storage import Storage as TaskStorage
|
||||||
|
from .note_storage import Storage as NoteStorage
|
||||||
|
|
||||||
|
base_storage = BaseStorage()
|
||||||
|
profile_storage = ProfileStorage()
|
||||||
|
task_storage = TaskStorage()
|
||||||
|
note_storage = NoteStorage()
|
||||||
|
|
||||||
profile = ProfileStorage()
|
|
||||||
task = TaskStorage()
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import socket
|
import socket
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from typing import ContextManager
|
from typing import ContextManager, NewType, TypeVar
|
||||||
|
|
||||||
import sqlalchemy
|
import sqlalchemy
|
||||||
from firebird.driver import Cursor, Connection
|
from firebird.driver import Cursor, Connection
|
||||||
|
@ -9,6 +9,11 @@ from sqlalchemy import text
|
||||||
from core.database.db import engine
|
from core.database.db import engine
|
||||||
|
|
||||||
|
|
||||||
|
def row_to_type(self: sqlalchemy.Row):
|
||||||
|
return type("KeyedROW", (), {key.upper(): val for key, val in self._mapping.items()})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class BaseStorage:
|
class BaseStorage:
|
||||||
_pool = engine
|
_pool = engine
|
||||||
|
|
||||||
|
@ -56,3 +61,6 @@ where ID_SEANS = RDB$GET_CONTEXT('USER_SESSION', 'ID_SEANS');
|
||||||
# yield cursor
|
# yield cursor
|
||||||
# finally:
|
# finally:
|
||||||
# cursor.close()
|
# cursor.close()
|
||||||
|
|
||||||
|
|
||||||
|
sqlalchemy.Row.row_to_type = row_to_type
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
import datetime
|
||||||
|
import json
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
import sqlalchemy
|
||||||
|
from sqlalchemy import text
|
||||||
|
from .base import BaseStorage
|
||||||
|
from ..model.note.db import AppNoteDB
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Storage(BaseStorage):
|
||||||
|
def fetch_all_notes_for_user(self, user_id: int):
|
||||||
|
stmt = text("""
|
||||||
|
select * from APP_NOTE where APP_NOTE_ID_SOTR = :user_id and APP_NOTE_DEL = 0;
|
||||||
|
""")
|
||||||
|
with self.get_session() as session:
|
||||||
|
session: sqlalchemy.Connection
|
||||||
|
res = [x.row_to_type() for x in session.execute(stmt, {
|
||||||
|
"user_id": user_id
|
||||||
|
}).fetchall()]
|
||||||
|
return [AppNoteDB(id=row.ID_APP_NOTE, user_id=row.APP_NOTE_ID_SOTR, task_id=row.APP_NOTE_ID_APP_TASK,
|
||||||
|
note_status=row.APP_NOTE_STATUS, tip=row.APP_NOTE_TIP, text=row.APP_NOTE_TEXT) for row in res]
|
||||||
|
|
||||||
|
def update_note(self, id: int, status: int, user_id: int):
|
||||||
|
stmt = text("""
|
||||||
|
insert into APP_EVENT (APP_EVENT_DT, APP_EVENT_ID_SOTR, APP_EVENT_TEXT, APP_EVENT_DATA, APP_EVENT_VID, APP_EVENT_ID_REC) values (current_timestamp, :user_id, 'Изменен статус уведомлений', :event_data, 8797, :note_id)
|
||||||
|
""")
|
||||||
|
|
||||||
|
event_data = json.dumps([{"8794": str(status)}], separators=(',', ":"))
|
||||||
|
|
||||||
|
with self.get_session() as session:
|
||||||
|
session: sqlalchemy.Connection
|
||||||
|
session.execute(stmt, {
|
||||||
|
"user_id": user_id,
|
||||||
|
"event_data": event_data,
|
||||||
|
"note_id": id
|
||||||
|
})
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
def create_note(self, user_id: int, note_text: str, time_created: datetime.datetime, task_id: Optional[int] = None):
|
||||||
|
stmt = text("""
|
||||||
|
insert into APP_EVENT (APP_EVENT_DT, APP_EVENT_ID_SOTR, APP_EVENT_TEXT, APP_EVENT_DATA, APP_EVENT_VID) values (:time_created, :user_id, :text, :event_data, 8795)
|
||||||
|
""")
|
||||||
|
|
||||||
|
if (task_id is not None):
|
||||||
|
event_data = json.dumps([{"ID_APP_TASK": str(task_id)}], separators=(",", ":"))
|
||||||
|
else:
|
||||||
|
event_data = None
|
||||||
|
with self.get_session() as session:
|
||||||
|
session: sqlalchemy.Connection
|
||||||
|
session.execute(stmt, {
|
||||||
|
"time_created": time_created,
|
||||||
|
"user_id": user_id,
|
||||||
|
"text": note_text,
|
||||||
|
"event_data": event_data
|
||||||
|
})
|
||||||
|
session.commit()
|
|
@ -1,13 +1,17 @@
|
||||||
import typing
|
import typing
|
||||||
from dataclasses import field
|
|
||||||
|
from core.model.note.db import AppNoteDB
|
||||||
|
from core.model.task.db import DBAppTask, DBSubTask, DBEvent, DBMarsh, DBTRS, DBMST, Location
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import Union
|
|
||||||
|
|
||||||
import strawberry
|
import strawberry
|
||||||
|
from strawberry.types import Info
|
||||||
|
from sqlalchemy import select
|
||||||
|
|
||||||
from core.model.task.enums import MarshTemperatureProperty
|
from core.model.task.enums import StatusEnum
|
||||||
from core.storage import task
|
from core.storage import base_storage, task_storage, note_storage
|
||||||
|
|
||||||
|
|
||||||
@strawberry.enum
|
@strawberry.enum
|
||||||
|
@ -30,87 +34,136 @@ class MarshTemperaturePropertyQl(Enum):
|
||||||
UNDEFINED = 0
|
UNDEFINED = 0
|
||||||
|
|
||||||
|
|
||||||
|
@strawberry.enum
|
||||||
|
class MarshTemperaturePropertyQL(Enum):
|
||||||
|
HOT = 1
|
||||||
|
COLD = 2
|
||||||
|
UNDEFINED = 0
|
||||||
|
|
||||||
|
|
||||||
@strawberry.type
|
@strawberry.type
|
||||||
class Query:
|
class Query:
|
||||||
|
|
||||||
@strawberry.field
|
@strawberry.field
|
||||||
def tasks(self, user_id: str) -> list['AppTaskQL']:
|
def tasks(self, user_id: str, is_planned: typing.Optional[bool] = False, is_completed: typing.Optional[bool] = False) -> list['AppTaskQL']:
|
||||||
tasks = task.fetch_tasks_with_subtasks(user_id=int(user_id))
|
tasks = task_storage.fetch_tasks_with_subtasks(user_id)
|
||||||
returned_list: list['AppTaskQL'] = []
|
|
||||||
for t in tasks:
|
|
||||||
updated_task = AppTaskQL(
|
|
||||||
id=str(t.id),
|
|
||||||
start_pln=t.start_pln,
|
|
||||||
end_pln=t.end_pln,
|
|
||||||
start_fact=t.start_fact,
|
|
||||||
end_fact=t.end_fact,
|
|
||||||
status=t.status.value,
|
|
||||||
task_type=t.task_type.value,
|
|
||||||
text=t.text,
|
|
||||||
route=MarshQL(
|
|
||||||
id=str(t.route.id),
|
|
||||||
temperature_property=t.route.temperature_property.value,
|
|
||||||
name=t.route.name,
|
|
||||||
trailer=TRSQL(
|
|
||||||
id=str(t.route.trailer.id),
|
|
||||||
gost=t.route.trailer.gost
|
|
||||||
) if t.route.trailer else None,
|
|
||||||
truck=TRSQL(
|
|
||||||
id=str(t.route.truck.id),
|
|
||||||
gost=t.route.truck.gost
|
|
||||||
) if t.route.truck else None,
|
|
||||||
) if t.route else None,
|
|
||||||
events=[EventQl(
|
|
||||||
id=e.id,
|
|
||||||
type=e.type,
|
|
||||||
text=e.text,
|
|
||||||
event_data=e.event_data,
|
|
||||||
event_datetime=e.event_datetime
|
|
||||||
) for e in t.events]
|
|
||||||
)
|
|
||||||
returned_list.append(updated_task)
|
|
||||||
|
|
||||||
return returned_list
|
if is_planned:
|
||||||
|
return [x for x in tasks if x.status == StatusEnum.NOT_DEFINED]
|
||||||
|
if is_completed:
|
||||||
|
return [x for x in tasks if x.status == StatusEnum.COMPLETED]
|
||||||
|
|
||||||
|
return tasks
|
||||||
|
|
||||||
|
@strawberry.field
|
||||||
|
def task(self, user_id: str, task_id: typing.Optional[str] = None, is_active: typing.Optional[bool] = None) -> \
|
||||||
|
typing.Optional[
|
||||||
|
'AppTaskQL']:
|
||||||
|
tasks = task_storage.fetch_tasks_with_subtasks(user_id)
|
||||||
|
|
||||||
|
if task_id is not None:
|
||||||
|
try:
|
||||||
|
return next(t for t in tasks if t.id == int(task_id))
|
||||||
|
except StopIteration:
|
||||||
|
return None
|
||||||
|
if is_active is not None:
|
||||||
|
try:
|
||||||
|
return next(t for t in tasks if t.status == StatusEnum.IN_PROGRESS)
|
||||||
|
except StopIteration:
|
||||||
|
return None
|
||||||
|
|
||||||
|
@strawberry.field
|
||||||
|
def notes(self, user_id: str) -> list['AppNoteQL']:
|
||||||
|
return note_storage.fetch_all_notes_for_user(int(user_id))
|
||||||
|
|
||||||
|
@strawberry.field
|
||||||
|
def subtask(self, user_id: str, subtask_id: str) -> typing.Optional['SubtaskQL']:
|
||||||
|
try:
|
||||||
|
return next(s for t in task_storage.fetch_tasks_with_subtasks(int(user_id)) for s in t.subtasks if
|
||||||
|
s.id == int(subtask_id))
|
||||||
|
except StopIteration:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
@strawberry.type
|
@strawberry.experimental.pydantic.type(model=Location)
|
||||||
class AppTaskQL:
|
class LocationQL:
|
||||||
|
lat: float
|
||||||
|
lon: float
|
||||||
|
|
||||||
|
|
||||||
|
@strawberry.experimental.pydantic.type(model=DBMST)
|
||||||
|
class MSTQL:
|
||||||
|
name: str
|
||||||
|
location: LocationQL
|
||||||
|
|
||||||
|
|
||||||
|
@strawberry.experimental.pydantic.type(model=DBSubTask)
|
||||||
|
class SubtaskQL:
|
||||||
id: str
|
id: str
|
||||||
start_pln: datetime
|
start_pln: strawberry.auto
|
||||||
end_pln: datetime
|
end_pln: strawberry.auto
|
||||||
start_fact: datetime | None
|
start_fact: strawberry.auto
|
||||||
end_fact: datetime | None
|
end_fact: strawberry.auto
|
||||||
status: StatusEnumQl
|
status: StatusEnumQl
|
||||||
task_type: TaskTypeEnumQl
|
task_type: int
|
||||||
text: str
|
text: str
|
||||||
|
|
||||||
events = []
|
station: typing.Optional[MSTQL] = None
|
||||||
subtasks = []
|
|
||||||
route = None
|
|
||||||
|
|
||||||
|
|
||||||
@strawberry.type
|
@strawberry.experimental.pydantic.type(model=DBEvent)
|
||||||
class MarshQL:
|
class AppEventQL:
|
||||||
id: str
|
id: str
|
||||||
temperature_property: MarshTemperaturePropertyQl
|
|
||||||
name: str
|
|
||||||
trailer: typing.Optional['TRSQL'] = None
|
|
||||||
truck: typing.Optional['TRSQL'] = None
|
|
||||||
|
|
||||||
|
|
||||||
@strawberry.type
|
|
||||||
class TRSQL:
|
|
||||||
id: str | None
|
|
||||||
gost: str | None
|
|
||||||
|
|
||||||
|
|
||||||
@strawberry.type
|
|
||||||
class EventQl:
|
|
||||||
id: int
|
|
||||||
type: str
|
type: str
|
||||||
text: str
|
text: str
|
||||||
event_data: dict
|
|
||||||
event_datetime: datetime
|
event_datetime: datetime
|
||||||
|
|
||||||
|
|
||||||
|
@strawberry.experimental.pydantic.type(model=DBTRS)
|
||||||
|
class TRSQL:
|
||||||
|
gost: str | None
|
||||||
|
|
||||||
|
|
||||||
|
@strawberry.experimental.pydantic.type(model=DBMarsh)
|
||||||
|
class AppRouteQL:
|
||||||
|
temperature_property: MarshTemperaturePropertyQL
|
||||||
|
name: str
|
||||||
|
trailer: typing.Optional[TRSQL]
|
||||||
|
truck: typing.Optional[TRSQL]
|
||||||
|
|
||||||
|
|
||||||
|
@strawberry.experimental.pydantic.type(model=AppNoteDB)
|
||||||
|
class AppNoteQL:
|
||||||
|
id: str
|
||||||
|
user_id: str
|
||||||
|
task_id: str
|
||||||
|
note_status: int
|
||||||
|
tip: int
|
||||||
|
text: str
|
||||||
|
|
||||||
|
|
||||||
|
@strawberry.experimental.pydantic.type(model=DBAppTask)
|
||||||
|
class AppTaskQL:
|
||||||
|
id: str
|
||||||
|
profile_id: strawberry.auto
|
||||||
|
start_pln: strawberry.auto
|
||||||
|
end_pln: strawberry.auto
|
||||||
|
start_fact: strawberry.auto
|
||||||
|
end_fact: strawberry.auto
|
||||||
|
status: StatusEnumQl
|
||||||
|
task_type: int
|
||||||
|
text: strawberry.auto
|
||||||
|
|
||||||
|
events: list[AppEventQL]
|
||||||
|
subtasks: list[SubtaskQL]
|
||||||
|
route: 'AppRouteQL'
|
||||||
|
|
||||||
|
@strawberry.field
|
||||||
|
def active_subtask(self) -> typing.Optional[SubtaskQL]:
|
||||||
|
try:
|
||||||
|
return next(x for x in self.subtasks if x.status == x.status.IN_PROGRESS)
|
||||||
|
except StopIteration:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
schema = strawberry.Schema(query=Query)
|
schema = strawberry.Schema(query=Query)
|
||||||
|
|
|
@ -8,7 +8,7 @@ from pydantic_extra_types.phone_numbers import PhoneNumber
|
||||||
|
|
||||||
from core.config import Config
|
from core.config import Config
|
||||||
from core.errors.auth.errors import profile_not_founded, incorrect_phone_number
|
from core.errors.auth.errors import profile_not_founded, incorrect_phone_number
|
||||||
from core.storage import profile
|
from core.storage import profile_storage
|
||||||
|
|
||||||
router = APIRouter(prefix="/auth")
|
router = APIRouter(prefix="/auth")
|
||||||
|
|
||||||
|
@ -34,19 +34,19 @@ async def get_authorization_code(req: PhoneNumberRequest):
|
||||||
if not 10 <= len(req.phoneNumber) <= 12:
|
if not 10 <= len(req.phoneNumber) <= 12:
|
||||||
incorrect_phone_number()
|
incorrect_phone_number()
|
||||||
|
|
||||||
p = profile.get_profile_by_phone("".join(char for char in req.phoneNumber if char.isdigit()))
|
p = profile_storage.get_profile_by_phone("".join(char for char in req.phoneNumber if char.isdigit()))
|
||||||
if not p:
|
if not p:
|
||||||
profile_not_founded()
|
profile_not_founded()
|
||||||
return {"code": profile.generate_profile_auth_code(p.id, p.phone_number)}
|
return {"code": profile_storage.generate_profile_auth_code(p.id, p.phone_number)}
|
||||||
|
|
||||||
|
|
||||||
@router.post("/phone/code")
|
@router.post("/phone/code")
|
||||||
async def get_access_token(form_data: OAuth2PasswordRequestForm = Depends()) -> Token:
|
async def get_access_token(form_data: OAuth2PasswordRequestForm = Depends()) -> Token:
|
||||||
p = profile.get_profile_by_phone(''.join(char for char in form_data.username if char.isdigit()))
|
p = profile_storage.get_profile_by_phone(''.join(char for char in form_data.username if char.isdigit()))
|
||||||
if not p:
|
if not p:
|
||||||
profile_not_founded()
|
profile_not_founded()
|
||||||
|
|
||||||
check = profile.check_profile_code(p.id, form_data.password)
|
check = profile_storage.check_profile_code(p.id, form_data.password)
|
||||||
if not check:
|
if not check:
|
||||||
raise HTTPException(status_code=403, detail="Incorrect code")
|
raise HTTPException(status_code=403, detail="Incorrect code")
|
||||||
|
|
||||||
|
|
|
@ -10,21 +10,21 @@ from core.model.profile.db import ProfileDB
|
||||||
from core.model.task.db import DBAppTask, DBSubTask, DBEvent
|
from core.model.task.db import DBAppTask, DBSubTask, DBEvent
|
||||||
from core.model.task.enums import StatusEnum
|
from core.model.task.enums import StatusEnum
|
||||||
from core.model.task.requests import SetTaskStatusActiveRequest, SetSubtaskStatusRequest, UpdTaskRequest, UpdTaskData
|
from core.model.task.requests import SetTaskStatusActiveRequest, SetSubtaskStatusRequest, UpdTaskRequest, UpdTaskData
|
||||||
from core.storage import task
|
from core.storage import task_storage
|
||||||
|
|
||||||
from core.model.task.db2 import MPAppTaskDB
|
from core.model.task.db2 import MPAppTaskDB
|
||||||
|
|
||||||
router = APIRouter(prefix="/tasks", tags=["Tasks and subtasks"])
|
router = APIRouter(prefix="/tasks", tags=["Tasks and subtasks"])
|
||||||
|
|
||||||
|
|
||||||
@router.get("/test", description="Fetch Task for authenticated user")
|
# @router.get("/test", description="Fetch Task for authenticated user")
|
||||||
async def get_task_test(user: ProfileDB = Depends(get_user_from_token)) -> list[MPAppTaskDB]:
|
# async def get_task_test(user: ProfileDB = Depends(get_user_from_token)) -> list[MPAppTaskDB]:
|
||||||
return MPAppTaskDB.fetch_all()
|
# return MPAppTaskDB.fetch_all()
|
||||||
|
|
||||||
|
|
||||||
@router.get("", description="Fetch Task for authenticated user")
|
@router.get("", description="Fetch Task for authenticated user")
|
||||||
async def get_tasks(user: ProfileDB = Depends(get_user_from_token)) -> list[DBAppTask]:
|
async def get_tasks(user: ProfileDB = Depends(get_user_from_token)) -> list[DBAppTask]:
|
||||||
return task.fetch_tasks_with_subtasks(user.id)
|
return task_storage.fetch_tasks_with_subtasks(user.id)
|
||||||
|
|
||||||
|
|
||||||
@router.post("")
|
@router.post("")
|
||||||
|
@ -83,7 +83,7 @@ async def upd_task(req: UpdTaskRequest, user: ProfileDB = Depends(get_user_from_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks = task.fetch_tasks_with_subtasks(user.id)
|
tasks = task_storage.fetch_tasks_with_subtasks(user.id)
|
||||||
available_tasks_ids = [x.id for x in tasks] + [sbt.id for t in tasks for sbt in t.subtasks]
|
available_tasks_ids = [x.id for x in tasks] + [sbt.id for t in tasks for sbt in t.subtasks]
|
||||||
|
|
||||||
req.data.sort(key=lambda u: u.dt)
|
req.data.sort(key=lambda u: u.dt)
|
||||||
|
@ -123,21 +123,21 @@ async def upd_task(req: UpdTaskRequest, user: ProfileDB = Depends(get_user_from_
|
||||||
except KeyError as exc:
|
except KeyError as exc:
|
||||||
update_task_by_chain_failed(exc)
|
update_task_by_chain_failed(exc)
|
||||||
|
|
||||||
[task.update_task(event, user.id) for event in req.data]
|
[task_storage.update_task(event, user.id) for event in req.data]
|
||||||
return task.fetch_tasks_with_subtasks(user.id)
|
return task_storage.fetch_tasks_with_subtasks(user.id)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/planned")
|
@router.get("/planned")
|
||||||
async def get_planned_tasks(user: ProfileDB = Depends(get_user_from_token)) -> list[DBAppTask]:
|
async def get_planned_tasks(user: ProfileDB = Depends(get_user_from_token)) -> list[DBAppTask]:
|
||||||
# TODO Rebuild this method to fetch only planned tasks
|
# TODO Rebuild this method to fetch only planned tasks
|
||||||
tasks = task.fetch_tasks_with_subtasks(user_id=user.id)
|
tasks = task_storage.fetch_tasks_with_subtasks(user_id=user.id)
|
||||||
return [x for x in tasks if x.status == StatusEnum.NOT_DEFINED]
|
return [x for x in tasks if x.status == StatusEnum.NOT_DEFINED]
|
||||||
|
|
||||||
|
|
||||||
@router.get("/active")
|
@router.get("/active")
|
||||||
async def get_active_task(user: ProfileDB = Depends(get_user_from_token)) -> DBAppTask | dict:
|
async def get_active_task(user: ProfileDB = Depends(get_user_from_token)) -> DBAppTask | dict:
|
||||||
# TODO Rebuild this method to fetch only active tasks
|
# TODO Rebuild this method to fetch only active tasks
|
||||||
tasks = task.fetch_tasks_with_subtasks(user_id=user.id)
|
tasks = task_storage.fetch_tasks_with_subtasks(user_id=user.id)
|
||||||
try:
|
try:
|
||||||
return next(x for x in tasks if x.status == StatusEnum.IN_PROGRESS)
|
return next(x for x in tasks if x.status == StatusEnum.IN_PROGRESS)
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
|
@ -147,7 +147,7 @@ async def get_active_task(user: ProfileDB = Depends(get_user_from_token)) -> DBA
|
||||||
@router.get("/completed")
|
@router.get("/completed")
|
||||||
async def get_active_task(user: ProfileDB = Depends(get_user_from_token)) -> list[DBAppTask]:
|
async def get_active_task(user: ProfileDB = Depends(get_user_from_token)) -> list[DBAppTask]:
|
||||||
# TODO Rebuild this method to fetch only active tasks
|
# TODO Rebuild this method to fetch only active tasks
|
||||||
tasks = task.fetch_tasks_with_subtasks(user_id=user.id)
|
tasks = task_storage.fetch_tasks_with_subtasks(user_id=user.id)
|
||||||
return [x for x in tasks if x.status == StatusEnum.COMPLETED]
|
return [x for x in tasks if x.status == StatusEnum.COMPLETED]
|
||||||
|
|
||||||
|
|
||||||
|
@ -170,7 +170,7 @@ async def get_active_task(user: ProfileDB = Depends(get_user_from_token)) -> lis
|
||||||
@router.get("/{task_id}/subtasks")
|
@router.get("/{task_id}/subtasks")
|
||||||
async def get_subtasks(user: ProfileDB = Depends(get_user_from_token), task_id: int = Path()) -> list[DBSubTask]:
|
async def get_subtasks(user: ProfileDB = Depends(get_user_from_token), task_id: int = Path()) -> list[DBSubTask]:
|
||||||
# TODO Rebuild this method to fetch only subtasks
|
# TODO Rebuild this method to fetch only subtasks
|
||||||
tasks = task.fetch_tasks_with_subtasks(user_id=user.id)
|
tasks = task_storage.fetch_tasks_with_subtasks(user_id=user.id)
|
||||||
try:
|
try:
|
||||||
t = next(x for x in tasks if x.id == task_id)
|
t = next(x for x in tasks if x.id == task_id)
|
||||||
return t.subtasks
|
return t.subtasks
|
||||||
|
@ -181,11 +181,11 @@ async def get_subtasks(user: ProfileDB = Depends(get_user_from_token), task_id:
|
||||||
@router.post("/subtask")
|
@router.post("/subtask")
|
||||||
async def set_status_to_subtask(req_data: SetSubtaskStatusRequest,
|
async def set_status_to_subtask(req_data: SetSubtaskStatusRequest,
|
||||||
user: ProfileDB = Depends(get_user_from_token)) -> DBSubTask:
|
user: ProfileDB = Depends(get_user_from_token)) -> DBSubTask:
|
||||||
tasks = task.fetch_tasks_with_subtasks(user_id=user.id)
|
tasks = task_storage.fetch_tasks_with_subtasks(user_id=user.id)
|
||||||
try:
|
try:
|
||||||
subtask = next(subtask for t in tasks for subtask in t.subtasks if subtask.id == req_data.subtask_id)
|
subtask = next(subtask for t in tasks for subtask in t.subtasks if subtask.id == req_data.subtask_id)
|
||||||
|
|
||||||
task.set_subtask_to_completed(subtask_id=subtask.id, profile_id=user.id, dt=req_data.finished_dt)
|
task_storage.set_subtask_to_completed(subtask_id=subtask.id, profile_id=user.id, dt=req_data.finished_dt)
|
||||||
subtask.status = StatusEnum.COMPLETED
|
subtask.status = StatusEnum.COMPLETED
|
||||||
return subtask
|
return subtask
|
||||||
|
|
||||||
|
@ -196,7 +196,7 @@ async def set_status_to_subtask(req_data: SetSubtaskStatusRequest,
|
||||||
@router.get("/{task_id}/events")
|
@router.get("/{task_id}/events")
|
||||||
async def get_events(user: ProfileDB = Depends(get_user_from_token), task_id: int = Path()) -> list[DBEvent]:
|
async def get_events(user: ProfileDB = Depends(get_user_from_token), task_id: int = Path()) -> list[DBEvent]:
|
||||||
# TODO Rebuild this method to fetch only events
|
# TODO Rebuild this method to fetch only events
|
||||||
tasks = task.fetch_tasks_with_subtasks(user_id=user.id)
|
tasks = task_storage.fetch_tasks_with_subtasks(user_id=user.id)
|
||||||
try:
|
try:
|
||||||
t = next(x for x in tasks if x.id == task_id)
|
t = next(x for x in tasks if x.id == task_id)
|
||||||
return [x for x in t.events if x.type == "Change"]
|
return [x for x in t.events if x.type == "Change"]
|
||||||
|
|
Loading…
Reference in New Issue