first commit

This commit is contained in:
berkay 2024-11-07 17:44:29 +03:00
commit 643d6d8f65
247 changed files with 420800 additions and 0 deletions

93
.dockerignore Normal file
View File

@ -0,0 +1,93 @@
# Git
.git
.gitignore
.gitattributes
# CI
.codeclimate.yml
.travis.yml
.taskcluster.yml
# Docker
docker-compose.yml
service_app/Dockerfile
.docker
.dockerignore
# Byte-compiled / optimized / DLL files
**/__pycache__/
**/*.py[cod]
# C extensions
*.so
# Distribution / packaging
.Python
service_app/env/
build/
develop-eggs/
dist/
downloads/
eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.cache
nosetests.xml
coverage.xml
# Translations
*.mo
*.pot
# Django stuff:
*.log
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Virtual environment
service_app/.env
.venv/
venv/
# PyCharm
.idea
# Python mode for VIM
.ropeproject
**/.ropeproject
# Vim swap files
**/*.swp
# VS Code
.vscode/
test_application/

162
.gitignore vendored Normal file
View File

@ -0,0 +1,162 @@
# ---> Python
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.idea/
.Python
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
service_app/.env
.venv
service_app/env/
venv/
service_app/env/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

1
.python-version Normal file
View File

@ -0,0 +1 @@
3.12

88
README.md Normal file
View File

@ -0,0 +1,88 @@
uv add arrow alembic fastapi uvicorn sqlalchemy-mixins redis psycopg2-binary pymongo rsa redmail unidecode textdistance pandas faker requests cryptography
user_creds_create
user_creds_update
timezone Comparator must be used as GMT+0 and users GMT+X
[Base Collection don't have find_one / find_all bla bla]ApiEnumDropdown: functions [
enum_class = mapped_column(String, nullable=False, comment="Enum Constant Name")
key = mapped_column(String, nullable=False, comment="Enum Key")
value = mapped_column(String, nullable=False, comment="Enum Value")
description = mapped_column(String, nullable=True)
]
BuildType: functions [
build_type = mapped_column(String, nullable=False, comment="Build Type")
description = mapped_column(String, nullable=True)
]
OccupantType: functions [
occupant_type = mapped_column(String, nullable=False, comment="Occupant Type")
description = mapped_column(String, nullable=True)
]
create & update & select
is_confirmed = True
find_one / find_all is found @Database
is_confirmed = False raise Exception Record is in database but not confirmed by supervisor
find_or_create -> If record is not found create it
if found.is_deleted = True: return "Record is found but deleted. Please contact your supervisor"
if found.is_confirmed = False: return "Record is found but not confirmed by supervisor"
update Which fields are possible to update
except
- is_confirmed
delete -> Update is_deleted = True
except
- id
destroy -> Only available for system
patch -> Only available for system [event] Retrieve available events for token user
+ Occupant Information +
Occupant [Settings] -> Event Group [Settings]
Occupant [Accounts] -> Event Group [Accounts]
Occupant [Decision Book] -> Event Group [Decision Book]
Occupant [Projects] -> Event Group [Projects]
Occupant [Events] -> Event Group [Events]
Occupant [Company] -> Event Group [Company]
Occupant [People] -> Event Group [People]
Occupant [Build] -> Event Group [Build]
Occupant [Address] -> Event Group [Address]
ApiActions:
insert_
insert_bulk
update_
update_bulk
delete_
delete_bulk
patch_
patch_bulk
InnerJoin:
pass
class FilterFromUser:
raise_exception = FilterModelofEvent(**filter_records)
HTTP_404_NOT_FOUND make available for Next.js
HTTP_401_UNAUTHORIZED make available for Next.js
HTTP_403_FORBIDDEN make available for Next.js
HTTP_400_BAD_REQUEST make available for Next.js
class DecisionBookDecisionBookItemsListEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"eb36de59-8268-4d96-80b6-5d01c12bf0b1": "building_decision_book_items_list",
}
event_description = "List Decision Book Items"

View File

@ -0,0 +1,131 @@
BuildDecisionBook:
|occupant_type |occupant_description |occupant_code|occupant_category|occupant_category_type|
|------------------------|---------------------------------|-------------|-----------------|----------------------|
|Toplantı Başkanı |Toplantı Başkanı |MT-PRS |Toplantı |MT |
|Toplantı Katip |Toplantıda tutanak tutan kişi |MT-WRT |Toplantı |MT |
|Toplantı Katılımcısı |Toplantıda sadece katılan kişi |MT-ATT |Toplantı |MT |
|Toplantı Danışman |Toplantıda danışmanlık yapan kişi|MT-ADV |Toplantı |MT |
|Daire Sahibi |Daire Sahibi |FL-OWN |Daire |FL |
|Daire Kiracısı |Daire Kiracısı |FL-TEN |Daire |FL |
|Daire Sakini |Daire Sakini |FL-RES |Daire |FL |
|Daire Sakini Vekili |Daire Sakini Vekili |FL-REP |Daire |FL |
|Bina Avukatı |Bina Avukatı |BU-ATT |Bina |BU |
|Bina Avukatı Yardımcısı |Bina Avukatı Yardımcısı |BU-ATA |Bina |BU |
|Bina Denetmen Yardımcısı|Bina Denetmen Yardımcısı |BU-SPA |Bina |BU |
|Bina Denetmeni |Bina Denetmeni |BU-SPV |Bina |BU |
|Bina Yönetici Yardımcısı|Bina Yönetici Yardımcısı |BU-MNA |Bina |BU |
|Bina Yöneticisi |Bina Yöneticisi |BU-MNG |Bina |BU |
|Bina Muhasabecisi |Bina Muhasabecisi |BU-ACC |Bina |BU |
1. Events[]
2. Events[]
Occupant:
...
Category:
::Category + CategoryType
- Bina (BU) -> Build
- Daire (FL) -> BuildPart
- Toplantı (MT) -> Decision Book
Service:
MT-PRS -> [Toplantı] Başkanı
MT-WRT -> [Toplantı] Katip
MT-ATT -> [Toplantı] Katılımcısı
MT-ADV -> [Toplantı] Danışman
1. Action Endpoint: /build/decision_book/items/create
2. Action Endpoint: /build/decision_book/person/create
3. Action Endpoint: /build/decision_book/invitation/send
occupant_type & employee
occupant X -> Restriction Optimum How to map =>
Build Need -> 1 yr annual meeting
API -> REQ[Toplantı] -> Client[Occ, Emp] -> Select[Com, Bul] -> Event -> Service
Module: Build Management
1. Service [Toplantı] Olagan - OPTIONAL
2. Service [Toplantı] Olağanüstü + OPTIONAL
3. Service [Toplantı] Ihtiyaç + OPTIONAL
4. Service [Toplantı] Karar + OPTIONAL
4. Service [Bina] Yönetim - OPTIONAL
5. Service [Bina] Yasal İşler - OPTIONAL
6. Service [Bina] Temizlik - OPTIONAL
7. Service [Bina] Isınma Sistemi - OPTIONAL
8. Service [Bina] Güvenlik Sistemi + OPTIONAL
9. Service [Bina] Bakım + OPTIONAL
10. Service [Bina] Onarım + OPTIONAL
11. Service [Daire] Kiralama + OPTIONAL
12. Service [Daire] Satış + OPTIONAL
13. Service [Daire] Tadiilat + OPTIONAL
14. Service [Daire] Temizlik + OPTIONAL
Pazarlama:
P1. Build Management Module (1, 4, 5, 6, 7)
P2. Build Management Gold Module (P1 + 8, 14)
P3. Build Management Platinum Module (P2 + 9, 10, 11, 12, 13)
P4. Build Management Custom Module (X, X, X ...)
1 Module -> n Service -> n Event(Unique 4 each establishment) -> n Action(Unique 4 each establishment)
Occupant Client:
- Services with same name and @DataBase Addresses can not be clarified due to event -> service relation
Schema:
Toplantı Karar Mapping:
- A Create Meeting Invitation [MT-PRS] +BookInvatationTable ->
- B Create Decision Book Attendance [MT-PRS] +BookPersonTable ->
- C Create Decision Book
- D Create Decision Book Items
- E Verify Decision Book [MT-PRS]
- F Announce Decision Book is verified
Buy -> Service[Toplantı Karar] Database Address: id[1]
- A Create Meeting Invitation Action: 3
:: [Event:1]Send invitation to all occupants via EMAIL
- B Create Decision Book Attendance Action: 2
:: [Event:2]Create attendance for all occupants from EMAIL
- C Create Decision Book Items Action: 1
:: [Event:3]Create items for all occupants from OCCUPANT_TYPE[MT-WRT] individual is responsible for Note TAKING
Buy -> Service[Toplantı Karar AI] Database Address: id[2]
- A Create Meeting Invitation Action: 3
:: [Event:1]Send invitation to all occupants via EMAIL
- B Create Decision Book Attendance Action: 2
:: [Event:2]Create attendance for all occupants from EMAIL
- D Create Decision Book Items AI Action: 1
:: [Event:4] [Event:3] + individual takes note via different [Service] fee : 0.20Cent
Buy -> Service[Toplantı Karar AI + Storage] Database Address: id[3]
- A Create Meeting Invitation Action: 3
:: [Event:1]Send invitation to all occupants via EMAIL
- B Create Decision Book Attendance Action: 2
:: [Event:2]Create attendance for all occupants from EMAIL and store @Data fees : 0.50Cent
- D Create Decision Book Items AI Action: 7
:: [Event:4] [Event:3] + individual takes note via different [Service] fee : 0.20Cent
Employee Client:
- Services with same name and @DataBase Addresses can not be clarified due to event -> service relation
Buy -> Service[Toplantı 15] Database Address: id[3]
-> Clearance of Event Bulk
Note-taking via AI implementation Action: 1

View File

@ -0,0 +1,138 @@
BuildDecisionBook:
|occupant_type |occupant_description |occupant_code|occupant_category|occupant_category_type|
|------------------------|---------------------------------|-------------|-----------------|----------------------|
|Toplantı Başkanı |Toplantı Başkanı |MT-PRS |Toplantı |MT |
|Toplantı Katip |Toplantıda tutanak tutan kişi |MT-WRT |Toplantı |MT |
|Toplantı Katılımcısı |Toplantıda sadece katılan kişi |MT-ATT |Toplantı |MT |
|Toplantı Danışman |Toplantıda danışmanlık yapan kişi|MT-ADV |Toplantı |MT |
|Daire Sahibi |Daire Sahibi |FL-OWN |Daire |FL |
|Daire Kiracısı |Daire Kiracısı |FL-TEN |Daire |FL |
|Daire Sakini |Daire Sakini |FL-RES |Daire |FL |
|Daire Sakini Vekili |Daire Sakini Vekili |FL-REP |Daire |FL |
|Bina Avukatı |Bina Avukatı |BU-ATT |Bina |BU |
|Bina Avukatı Yardımcısı |Bina Avukatı Yardımcısı |BU-ATA |Bina |BU |
|Bina Denetmen Yardımcısı|Bina Denetmen Yardımcısı |BU-SPA |Bina |BU |
|Bina Denetmeni |Bina Denetmeni |BU-SPV |Bina |BU |
|Bina Yönetici Yardımcısı|Bina Yönetici Yardımcısı |BU-MNA |Bina |BU |
|Bina Yöneticisi |Bina Yöneticisi |BU-MNG |Bina |BU |
|Bina Muhasabecisi |Bina Muhasabecisi |BU-ACC |Bina |BU |
Occupant Objesi Toplantı:
------------------------------------------------------------------------------------------------------------------------
MT-PRS:
1. Toplantıdan Sorumludur. Toplantıyı yönetir.
2. Kararlar alınırken toplantıyı yönetir.
3 Alınan kararları katılımcılara onaylatır
4. Alınan kararları bir metne dönüştürür.
5. Katibe yazdırır.
6. Yazılan metini kontrol eder ve onaylar.
7. Metne itiraz edenler olursa, her itirazı kayıt ettirir.
8. Eğer toplantı olağan toplantı ise ve aidatı ilgilendirioyorsa
9. Aidat kararlarını katip tarafından rakamsal değerler ile yazdırır.
10. Aidat kararlarını onaylar.
11. Alınan karar bir tadilat ise, açıklamalarını yazdırır.
12. Projeyi açtırır.
13. Alınan kararları yasal bir sureç takip ediyor ise yasal takip sürecini açar ve hukuki süreci başlatır/takip eder.
MT-WRT:
1. Toplantıda başkanın aldığı kararları metne çevirmek ile görevlidir.
2. Borçlandırma, Proje, Yasal süreçlerinin tanımlanmasını sağlar.
MT-ATT:
1. Toplantıda alınana kararlara tanıklık eder.
2. Itirazı var ise itiraz eder.
3. Itirazı yok ise kararları onaylar.
MT-ADV:
1. Toplantıda alınan kararlarlara onay veremez veya itiraz edemez.
2. Toplantıda karar alınırken danışmanlık yapar.
BU-MNG:
1 Toplantı tarihi belirliyor. +
2. Toplantı davetini ilgili tarihi ile duyunur. -
3. Toplantı günü yeterli kriterler oluşmuş ise toplantıyı başlatır. -
4. Divan Kurulunu kurar. -
5. Toplantı başkanını ve katibi deneteledikten sonra başkana toplantıyı devreder.
------------------------------------------------------------------------------------------------------------------------
{"enum_class": "MeetingTypes", "type_code": "RBM", "type_name": "Regular Building Meeting"},
{"enum_class": "MeetingTypes", "type_code": "DBM", "type_name": "Disaster Building Meeting"},
{"enum_class": "MeetingTypes", "type_code": "EBM", "type_name": "Emergency Building Meeting"},
Düzenli Bina Toplantısı (RBM) Servisi:
2. Tarihinin belirlenirmesi.
3. Tarihinin duyurulması.
4. %51 kişinin toplantıya katılması zorunludur.
5. %51 sağlanmadıysa bir sonraki tarihe ertelenir.
6. 2 tarihte kritere bakılmaksızın toplantı başlatılır. (Kaç kişinin katılacağına bakılmaz)
7. Divan Kurulu kurulur.
8. Toplantı başkanı ve katibi belirlenir.
9. Toplantı toplantı başkanına devredilir.
10. Toplantı tipine göre bir karar alınır.
11. Karar kurul tarafından istişare edilir.
12. Karar kurul tarafından onaylanır.
13. Karar katip tarafından yazılır.
14. Karar başkan tarafından onaylanır. (Katibin yazdığı metin kontrol edilir)
15. Bir sonraki karara geçilir.
16. Karar defterine katılımcılar tarafından imza atılır.
17. Karar defteri yeni Bina Yöneticisine teslim edilir.
Olaganüstü Bina Toplantısı (DBM) Servisi:
2. Tarihinin belirlenirmesi.
3. Tarihinin duyurulması.
7. Divan Kurulu kurulur.
8. Toplantı başkanı ve katibi belirlenir.
9. Toplantı toplantı başkanına devredilir.
10. Toplantı tipine göre bir karar alınır.
11. Karar kurul tarafından istişare edilir.
12. Karar kurul tarafından onaylanır.
13. Karar katip tarafından yazılır.
14. Karar başkan tarafından onaylanır. (Katibin yazdığı metin kontrol edilir)
15. Bir sonraki karara geçilir.
16. Karar defterine katılımcılar tarafından imza atılır.
Acil Bina Toplantısı (EBM) Servisi:
2. Tarihinin belirlenirmesi.
3. Tarihinin duyurulması.
7. Divan Kurulu kurulur.
8. Toplantı başkanı ve katibi belirlenir.
9. Toplantı toplantı başkanına devredilir.
10. Toplantı tipine göre bir karar alınır.
11. Karar kurul tarafından istişare edilir.
12. Karar kurul tarafından onaylanır.
13. Karar katip tarafından yazılır.
14. Karar başkan tarafından onaylanır. (Katibin yazdığı metin kontrol edilir)
15. Bir sonraki karara geçilir.
16. Karar defterine katılımcılar tarafından imza atılır.
Meeting:
1. Tipini belirlenmesi.
2. Tarihinin belirlenirmesi.
3. Tarihinin duyurulması.
4. %51 kişinin toplantıya katılması zorunludur.
5. %51 sağlanmadıysa bir sonraki tarihe ertelenir.
6. 2 tarihte kritere bakılmaksızın toplantı başlatılır. (Kaç kişinin katılacağına bakılmaz)
7. Divan Kurulu kurulur.
8. Toplantı başkanı ve katibi belirlenir.
9. Toplantı toplantı başkanına devredilir.
10. Toplantı tipine göre bir karar alınır.
11. Karar kurul tarafından istişare edilir.
12. Karar kurul tarafından onaylanır.
13. Karar katip tarafından yazılır.
14. Karar başkan tarafından onaylanır. (Katibin yazdığı metin kontrol edilir)
15. Bir sonraki karara geçilir.
16. Karar defterine katılımcılar tarafından imza atılır.
17. Karar defteri yeni Bina Yöneticisine teslim edilir.

View File

@ -0,0 +1,508 @@
from sqlalchemy import (
create_engine,
UUID,
Column,
Integer,
String,
ForeignKey,
Boolean,
DateTime,
func,
text,
Index,
UniqueConstraint,
)
from sqlalchemy.orm import relationship, declarative_base
from .base import CrudMixin
from sqlalchemy_mixins.serialize import SerializeMixin
from sqlalchemy_mixins.repr import ReprMixin
from sqlalchemy_mixins.smartquery import SmartQueryMixin
Base = declarative_base()
class CrudCollection(Base, CrudMixin, ReprMixin, SmartQueryMixin, SerializeMixin):
__abstract__ = True
__repr__ = ReprMixin.__repr__
id: int = Column(Integer, primary_key=True)
uu_id: str = Column(
UUID, server_default=text("gen_random_uuid()"), index=True, unique=True
)
createdate = Column(DateTime, default=func.now())
updatedate = Column(DateTime, default=func.now(), onupdate=func.now())
createperson = Column(Integer, ForeignKey("persons.id"), nullable=True)
updateperson = Column(Integer, ForeignKey("persons.id"), nullable=True)
active = Column(Boolean, default=True)
delete = Column(Boolean, default=False)
replicationid = Column(Integer)
class Address(CrudCollection):
__tablename__ = "address"
__table_args__ = (
Index("_address_ndx_00", country_code, b_state, city, district),
{"comment": "Address Information"},
)
country_code = mapped_column(
String(9), server_default="TR", nullable=False, comment="Country Code"
)
city = mapped_column(String(24), nullable=False, comment="City")
district = mapped_column(String(24), nullable=False, comment="District")
b_state = mapped_column(String(24), server_default="")
neighborhood = mapped_column(String(24), server_default="")
street = mapped_column(String(24), server_default="")
postcode = mapped_column(String(8), server_default="")
latitude = mapped_column(Numeric(20, 12), server_default="0")
longitude = mapped_column(Numeric(20, 12), server_default="0")
official_companies: Mapped["Company"] = relationship(
"Company",
back_populates="official_address",
foreign_keys="Company.official_address_id",
)
class Company(CrudCollection):
__tablename__ = "companies"
__table_args__ = (
UniqueConstraint("tax_number", name="uq_companies_tax_number"),
{"comment": "İşletmelerin bilgilerini tutar"},
)
official_name = mapped_column(String, nullable=True, comment="Şirketin resmi adı")
public_name = Column(String, nullable=False, comment="Şirketin bilinen adı")
tax_number = Column(String, nullable=False, unique=True, comment="Vergi numarası")
organizations = relationship("Organization", back_populates="company")
locations = relationship("Location", back_populates="company")
default_lang_type = mapped_column(String(5), server_default="TR")
default_money_type = mapped_column(String(5), server_default="TL")
is_commercial = mapped_column(Boolean, server_default="True")
is_blacklist = mapped_column(Boolean, server_default="False")
official_address_id = mapped_column(ForeignKey("address.id"))
parent_id = mapped_column(ForeignKey("company.id"))
official_address: Mapped[List["Address"]] = relationship(
"Address",
back_populates="official_companies",
foreign_keys=[official_address_id],
)
class Organization(CrudCollection):
__tablename__ = "organizations"
__table_args__ = {"comment": "Her şirketin organizasyon yapısını tutar"}
name = Column(String, nullable=False, comment="Organizasyonun adı")
company_id = Column(
Integer, ForeignKey("companies.id"), nullable=False, comment="Şirket ID"
)
valid_from = Column(
DateTime, default=func.now(), comment="Geçerlilik başlangıç tarihi"
)
valid_to = Column(DateTime, nullable=True, comment="Geçerlilik bitiş tarihi")
company = relationship("Company", back_populates="organizations")
employees = relationship("Employee", back_populates="organization")
locations = relationship("Location", back_populates="organization")
phones = relationship("Phone", back_populates="organization")
menus = relationship("Menu", back_populates="organization")
class Location(CrudCollection):
__tablename__ = "locations"
__table_args__ = {
"comment": "Şirketin farklı lokasyonlarını (depo, ofis, şube, büro vb.) tutar"
}
name = Column(String, nullable=False, comment="Lokasyon adı")
address = Column(String, nullable=False, comment="Lokasyon adresi")
location_type = Column(
String, nullable=False, comment="Lokasyon türü (depo, ofis, şube, büro vb.)"
)
company_id = Column(
Integer, ForeignKey("companies.id"), nullable=False, comment="Şirket ID"
)
organization_id = Column(
Integer,
ForeignKey("organizations.id"),
nullable=False,
comment="Organizasyon ID",
)
company = relationship("Company", back_populates="locations")
organization = relationship("Organization", back_populates="locations")
class Person(CrudCollection):
__tablename__ = "persons"
__table_args__ = (
UniqueConstraint("identity_number", name="uq_persons_identity_number"),
{"comment": "Kişilerin bilgilerini tutar"},
)
first_name = Column(String, nullable=False, comment="İlk isim")
last_name = Column(String, nullable=False, comment="Soy isim")
identity_number = Column(
String, nullable=False, unique=True, comment="Kimlik numarası"
)
mother_name = Column(String, nullable=False, comment="Anne adı")
father_name = Column(String, nullable=False, comment="Baba adı")
birth_place = Column(String, nullable=False, comment="Doğum yeri")
birth_date = Column(DateTime, nullable=False, comment="Doğum tarihi")
gender = Column(String, nullable=False, comment="Cinsiyet")
nationality_code = Column(String, nullable=False, comment="Ülke kimlik kodu")
employees = relationship("Employee", back_populates="person")
users = relationship("User", back_populates="person")
class Employee(CrudCollection):
__tablename__ = "employees"
__table_args__ = (
UniqueConstraint("person_id", name="uq_employee_person_id"),
{"comment": "Çalışanların bilgilerini tutar"},
)
person_id = Column(
Integer,
ForeignKey("persons.id"),
nullable=False,
unique=True,
comment="Kişi ID",
)
organization_id = Column(
Integer,
ForeignKey("organizations.id"),
nullable=False,
comment="Organizasyon ID",
)
person = relationship("Person", back_populates="employees")
organization = relationship("Organization", back_populates="employees")
processes = relationship("EmployeeProcess", back_populates="employee")
permissions = relationship("Permission", back_populates="employee")
salaries = relationship("Salary", back_populates="employee")
performances = relationship("Performance", back_populates="employee")
"""
class User(CrudCollection):
__tablename__ = 'users'
__table_args__ = (
UniqueConstraint('email', name='uq_users_email'),
UniqueConstraint('phone_number', name='uq_users_phone_number'),
{'comment': 'Kullanıcıların giriş bilgilerini tutar'}
)
person_id = Column(Integer, ForeignKey('persons.id'), nullable=False, comment='Kişi ID')
email = Column(String, nullable=True, unique=True, comment='E-posta adresi')
phone_number = Column(String, nullable=True, unique=True, comment='Telefon numarası')
password_hash = Column(String, nullable=False, comment='Parola hash değeri')
person = relationship('Person', back_populates='users')
login_attempts = relationship('LoginAttempt', back_populates='user')
class LoginAttempt(CrudCollection):
__tablename__ = 'login_attempts'
__table_args__ = {'comment': 'Kullanıcıların giriş denemelerini tutar'}
user_id = Column(Integer, ForeignKey('users.id'), nullable=False, comment='Kullanıcı ID')
timestamp = Column(DateTime, default=func.now(), nullable=False, comment='Giriş deneme zamanı')
success = Column(Boolean, default=False, nullable=False, comment='Giriş başarılı mı')
user = relationship('User', back_populates='login_attempts')
"""
class Process(CrudCollection):
__tablename__ = "processes"
__table_args__ = {"comment": "İş süreçlerinin tanımlamalarını tutar"}
name = Column(String, nullable=False, comment="Süreç adı")
employee_processes = relationship("EmployeeProcess", back_populates="process")
emails = relationship("Email", back_populates="process")
class EmployeeProcess(CrudCollection):
__tablename__ = "employee_processes"
__table_args__ = {
"comment": "Çalışan ile iş süreçleri arasındaki ilişkileri ve yetkileri tutar"
}
employee_id = Column(
Integer, ForeignKey("employees.id"), nullable=False, comment="Çalışan ID"
)
process_id = Column(
Integer, ForeignKey("processes.id"), nullable=False, comment="Süreç ID"
)
can_add = Column(Boolean, default=False, comment="Ekleme yetkisi")
can_update = Column(Boolean, default=False, comment="Güncelleme yetkisi")
can_delete = Column(Boolean, default=False, comment="Silme yetkisi")
employee = relationship("Employee", back_populates="processes")
process = relationship("Process", back_populates="employee_processes")
class Permission(CrudCollection):
__tablename__ = "permissions"
__table_args__ = {"comment": "Yetkileri tanımlar ve çalışanlara devredilebilir"}
employee_id = Column(
Integer, ForeignKey("employees.id"), nullable=False, comment="Çalışan ID"
)
granted_to = Column(
Integer,
ForeignKey("employees.id"),
nullable=True,
comment="Yetki verilen çalışan ID",
) # Temporary delegation
permission_type = Column(
String, nullable=False, comment="Yetki türü (add, update, delete)"
)
valid_until = Column(DateTime, nullable=True, comment="Geçerlilik bitiş tarihi")
employee = relationship(
"Employee", foreign_keys=[employee_id], back_populates="permissions"
)
granted_employee = relationship("Employee", foreign_keys=[granted_to])
class Performance(CrudCollection):
__tablename__ = "performances"
__table_args__ = {"comment": "Çalışanların performanslarını tutar"}
employee_id = Column(
Integer, ForeignKey("employees.id"), nullable=False, comment="Çalışan ID"
)
review_date = Column(DateTime, nullable=False, comment="Değerlendirme tarihi")
score = Column(Float, nullable=False, comment="Performans puanı")
notes = Column(String, nullable=True, comment="Notlar")
employee = relationship("Employee", back_populates="performances")
class Salary(CrudCollection):
__tablename__ = "salaries"
__table_args__ = {"comment": "Çalışanların maaş bilgilerini tutar"}
employee_id = Column(
Integer, ForeignKey("employees.id"), nullable=False, comment="Çalışan ID"
)
salary_amount = Column(Float, nullable=False, comment="Maaş miktarı")
effective_date = Column(DateTime, nullable=False, comment="Geçerlilik tarihi")
employee = relationship("Employee", back_populates="salaries")
class Email(CrudCollection):
__tablename__ = "emails"
__table_args__ = {
"comment": "İş süreçlerine ve çalışanlara e-posta gönderimlerini takip eder"
}
process_id = Column(
Integer, ForeignKey("processes.id"), nullable=False, comment="Süreç ID"
)
recipient = Column(String, nullable=False, comment="Alıcı e-posta adresi")
subject = Column(String, nullable=False, comment="E-posta konusu")
body = Column(String, nullable=False, comment="E-posta içeriği")
sent_date = Column(
DateTime, default=func.now(), nullable=False, comment="Gönderim tarihi"
)
process = relationship("Process", back_populates="emails")
class Phone(CrudCollection):
__tablename__ = "phones"
__table_args__ = {"comment": "Organizasyonlara ait telefon bilgilerini tutar"}
organization_id = Column(
Integer,
ForeignKey("organizations.id"),
nullable=False,
comment="Organizasyon ID",
)
phone_number = Column(String, nullable=False, comment="Telefon numarası")
phone_type = Column(
String, nullable=False, comment="Telefon türü (Sabit, Mobil vb.)"
)
organization = relationship("Organization", back_populates="phones")
class Menu(CrudCollection):
__tablename__ = "menus"
__table_args__ = (
Index("ix_menus_title", "title"),
{"comment": "Menü öğelerini tutar"},
)
title = Column(String, nullable=False, comment="Menü başlığı")
link = Column(String, nullable=False, comment="Menü bağlantısı")
icon = Column(String, nullable=True, comment="Menü simgesi")
order = Column(Integer, nullable=False, default=0, comment="Menü sıralaması")
organization_id = Column(
Integer,
ForeignKey("organizations.id"),
nullable=False,
comment="Organizasyon ID",
)
page_id = Column(Integer, ForeignKey("pages.id"), nullable=True, comment="Sayfa ID")
sub_menus = relationship(
"SubMenu", back_populates="menu", cascade="all, delete-orphan"
)
organization = relationship("Organization", back_populates="menus")
page = relationship("Page", back_populates="menus")
class SubMenu(CrudCollection):
__tablename__ = "sub_menus"
__table_args__ = (
Index("ix_sub_menus_title", "title"),
{"comment": "Alt menü öğelerini tutar"},
)
menu_id = Column(
Integer, ForeignKey("menus.id"), nullable=False, comment="Ana Menü ID"
)
title = Column(String, nullable=False, comment="Alt Menü başlığı")
link = Column(String, nullable=False, comment="Alt Menü bağlantısı")
icon = Column(String, nullable=True, comment="Alt Menü simgesi")
order = Column(Integer, nullable=False, default=0, comment="Alt Menü sıralaması")
layer = Column(Integer, nullable=False, default=0, comment="Alt Menü seviyesi")
page_id = Column(Integer, ForeignKey("pages.id"), nullable=True, comment="Sayfa ID")
menu = relationship("Menu", back_populates="sub_menus")
page = relationship("Page", back_populates="sub_menus")
class Page(CrudCollection):
__tablename__ = "pages"
__table_args__ = {"comment": "Uygulamada kullanılacak sayfaları tutar"}
title = Column(String, nullable=False, comment="Sayfa başlığı")
path = Column(String, nullable=False, comment="Sayfa yolu")
menus = relationship("Menu", back_populates="page")
sub_menus = relationship("SubMenu", back_populates="page")
functions = relationship("Function", back_populates="page")
class Function(CrudCollection):
__tablename__ = "functions"
__table_args__ = {
"comment": "Uygulamada kullanılacak fonksiyon parçacıklarını tutar"
}
name = Column(String, nullable=False, comment="Fonksiyon adı")
description = Column(String, nullable=True, comment="Fonksiyon açıklaması")
code = Column(String, nullable=False, comment="Fonksiyon kodu")
page_id = Column(
Integer, ForeignKey("pages.id"), nullable=False, comment="Sayfa ID"
)
page = relationship("Page", back_populates="functions")
from sqlalchemy.exc import NoResultFound
def authenticate(email=None, phone_number=None, password=None):
try:
if email:
user = session.query(User).filter(User.email == email).one()
elif phone_number:
user = session.query(User).filter(User.phone_number == phone_number).one()
else:
return False
# Şifre doğrulama (gerçek şifre doğrulama fonksiyonu kullanılmalıdır)
if user.password_hash == password:
login_attempt = LoginAttempt(user_id=user.id, success=True)
session.add(login_attempt)
session.commit()
return True
else:
login_attempt = LoginAttempt(user_id=user.id, success=False)
session.add(login_attempt)
session.commit()
return False
except NoResultFound:
return False
# PostgreSQL veritabanına bağlan
engine = create_engine("postgresql://username:password@localhost/mydatabase")
Base.metadata.create_all(engine)
# Oturum oluştur
Session = sessionmaker(bind=engine)
session = Session()
# Örnek veriler ekle
company = Company(name="My Company", tax_number="1234567890")
session.add(company)
session.commit()
organization = Organization(name="IT Department", company_id=company.id)
session.add(organization)
session.commit()
location = Location(
name="Main Office",
address="123 Main St",
location_type="Office",
company_id=company.id,
organization_id=organization.id,
)
session.add(location)
session.commit()
person = Person(
first_name="John",
last_name="Doe",
identity_number="9876543210",
mother_name="Jane Doe",
father_name="Joe Doe",
birth_place="New York",
birth_date="1980-01-01",
gender="Male",
nationality_code="US",
)
session.add(person)
session.commit()
employee = Employee(person_id=person.id, organization_id=organization.id)
session.add(employee)
session.commit()
user = User(
person_id=person.id,
email="john.doe@example.com",
phone_number="555-1234",
password_hash="hashed_password",
)
session.add(user)
session.commit()
login_attempt = LoginAttempt(user_id=user.id, success=True)
session.add(login_attempt)
session.commit()
process = Process(name="Code Review")
session.add(process)
session.commit()
employee_process = EmployeeProcess(
employee_id=employee.id,
process_id=process.id,
can_add=True,
can_update=True,
can_delete=False,
)
session.add(employee_process)
session.commit()
permission = Permission(
employee_id=employee.id, permission_type="add", valid_until=None
)
session.add(permission)
session.commit()
performance = Performance(employee_id=employee.id, review_date="2023-01-01", score=4.5)
session.add(performance)
session.commit()
salary = Salary(
employee_id=employee.id,
amount=5000.0,
effective_from="2023-01-01",
effective_to="2024-01-01",
)
session.add(salary)
session.commit()
phone1 = Phone(
organization_id=organization.id, phone_number="555-1234", phone_type="mobil"
)
session.add(phone1)
phone2 = Phone(
organization_id=organization.id, phone_number="555-5678", phone_type="sabit"
)
session.add(phone2)
session.commit()
email = Email(process_id=process.id, email_address="codereview@example.com")
session.add(email)
session.commit()

View File

@ -0,0 +1,73 @@
Event.Controller
class Person:
1. Berkay Karatay
2. Melih Asd
...
class User:
Berkay User
Melih User
...
class Company:
Evyos
...
class Departments:
General Managment
Information Tech. Dep.
Sales
...
class Duties:
General Manager
Backend Developer
Area Manager
...
class Occupant:
job_resp: Boolean true | false true
resp_empp_id Employees[1]
Bina Sakini
...
class Employees:
1. st - en - Person 1
...
class Events:
1. Cari Hesap kontrol
2. Cari Hesap Gözlem
3. Cari Hesap Oluştur
Cari Hesap [WAG]
Kazan Dairesi İşleri
Daire Bilgileri [HAG]
Sorumlu Kişiye Mail [WAG]
Bina Bilgileri [HAG]
Wag APi Service Build
Hag APi Service Build
...
class BudgetRecords:
CRUD Row(s)
CompanyBudgetRecords:
/list
/create
/update
/delete
/destroy
CompanyEmployees:
1 insan(class Person) + 1 görev(class CompanyDuty)
CompanyDuty:
n(görev) kümesi
CompanyDepartments:
n(duty) kümesi

View File

@ -0,0 +1,18 @@
OccupantTypes
Token (Save AS) => User => Employee => Menu
+ User ID && User UUID
+ People ID && People UUID
+ User Info
+ Employee ID && Employee UUID
+ CompanyId + CompanyUUID
+ DutyId + Duty UUID [duty_id]
+ OccupantTypesId + OccupantTypesUUID + OccupantTypes [String]
+ Priority ID, Priority Code [priority_id ,priority_code]
+ Request [IP + header]
+ Reachable Module List[id]
+ List of reachable Endpoint Codes [Array] ???

View File

@ -0,0 +1,23 @@
class User:
email = karatay.berkay@gmail.com
via: email | phone | user_tag
phone: tanımlı
is_occupant True
...
class User:
email = karatay.berkay@evyos.com.tr
via: email X | phone | user_tag
phone: +90 111 11 11
is_occupant False
...
class Person:
Person -> User -> Email | Phone
@gmail
@evyos.com.tr

View File

@ -0,0 +1,95 @@
class Person:
1. Berkay Karatay
2. Melih Asd
3. Osman
...
class User:
Berkay User
Melih User
...
class Company:
Evyos
...
class Departments:
General Managment
Information Tech. Dep.
Sales
...
class Duties:
General Manager
Backend Developer
Area Manager
Kazan Manager
...
class Occupant:
job_resp: Boolean true | false true
resp_empp_id Employees[1]
Bina Sakini
...
class Employees:
1. st - en - Person 1
3. st - en - Person 3
...
class Events2Employees:
class Events2Occupants:
class Events:
1. Cari Hesap kontrol
2. Cari Hesap Gözlem
3. Cari Hesap Oluştur
Cari Hesap [WAG]
Kazan Dairesi İşleri
Daire Bilgileri [HAG]
Sorumlu Kişiye Mail [WAG]
Bina Bilgileri [HAG]
Wag APi Service Build
Hag APi Service Build
...
class BudgetRecords:
CRUD Row(s)
CompanyBudgetRecords:
/list
/create
/update
/delete
/destroy
CompanyEmployees:
1 insan(class Person) + 1 görev(class CompanyDuty)
CompanyDuty:
n(görev) kümesi
CompanyDepartments:
n(duty) kümesi
[Login Action]
Person -> User
Query: Event
Company -> Department -> Duty -> Employee -> Person | (n) Occupant -> Person
Company : evyos.com
Department : Satış Dep.
Duty : Temsilci
Employee: Berkay Karatay[Person]
(n) Occupant
Occupant: Melih[Person]
Occupant: Songül[Person]
Occupant: Günay[Person]

View File

@ -0,0 +1,52 @@
Building.Controller
class Person:
1. Berkay Karatay
...
class User:
Berkay User
...
class Build:
response_company_id:
X resp_employee: (person_id old version)
class Employee2Parts:
build_id:
part_id:
resp_employee: Person + Duty
...
class LivingSpace:
is_tenant_live:
build_parts_id:
owner_person_id:
life_person_id:
...
[Login Action]
Person -> User
Build -> Parts -> Employee -> Person
! Check is_occupant is true or false
Query: LivingSpace
Person -> Occupant -> LivingSpace -> (n)Part -> (n)Build
Query: Employee2Parts
Person -> Employee -> (n)Build [Employee2Parts]
Occupant & Employee[]
Occupant: Tenant | Owner n(Record)
LivingSpace[Info] && Event[]
Employee:
Build[Info] && Event[]

View File

@ -0,0 +1,408 @@
#### Application Draft ####
Token (Save AS) => User => Employee => Menu
+ User ID
+ People ID
+ User Info
+ Employee ID
+ Request [IP + header]
+ List of reachable Endpoint Codes [Array]
+ CompanyId + CompanyUUID
+ DutyId + DutyUUID [duty_id]
+ Priority ID, Priority Code [priority_id ,priority_code]
Company & Customer [Common Attributes]
o User
o People
--- Customer [Structure]
Build +
BuildPart +
is_rentable = True (Life Space)
is_rentable = False (Non-life Space)
LivingSpace [Property] + // a human living in BuildPart in a given timeline
LivingSpace Branches
Property[Owner] +
Property[Tenant] +
Financial Assets +
--- Company [Gives Service]
Company +
Employee +
Company Responsiablity = Company[Employee] => Group[Customer]
--- Services [Receives Services]
+ Property Renovation Dues [Customer Financial Assets ]
+ Property Goverment Tax Dues [Customer Financial Assets ]
+ Property Building Dues [Customer Financial Assets ]
+ Heating Systems [HAG]
Optional Extra tutu
+ Cooling Systems [HAG]
+ Landscape Systems [HAG]
User Logins:
1. Company[Employee]
2. Property[Tenant]
3. Property[Owner]
- Primary Company Schema -
# Primary Company Roles #
SystemAdmin [Static] [Root Manager] [Application's Primary Management Office Employee]
+ Accesses all role and priviliges maintains management
Example: Groot => User can manage all access and permissions, access rules can not be manupilated or deleted
SystemUser [Static] < SystemAdmin
+ System storage and services are maintained by this role
- Can not reach any personel data in any case
I. Database [Database Manager]
II. Network [Network Manager]
III. Application Services [Application Manager]
Example: => IT Department of manager [Primary Company]
[System Admin] => SystemAdmin99 [People]
[Database Manager] => SystemUser96 [People]
[Network Manager] => SystemUser97 [People]
[Application Manager] => SystemUser98 [People]
for each company:
* Creates Company: [Company] = ABC Company
* Creates Employee: [Owner] & [SuperUser] = Owner & SuperUser
* Assigns Employee to Company: ABC Company Owner & ABC Company SuperUser
* Creates People: [People] = Jonathan
* Assigns People to Employee: [People] Jonathan -> [Employee] Owner = ABC Company Owner Jonathan
// if Owner==None: ilk atanan superuser=Owner
[Application Manager] => Company => Employee => People
- API -
// APi has primary company in its default settings
# Company Employee #
[Application Manager] Actions
Employee > Owner > People 1
Employee > SuperUser > People 1
Owner [Static] < [Application Manager] Johantan
* Can receive Access Token[Login]
* [Application Manager] => with SystemAdmin approval
- [Data] Can NOT manupilate data 4ex Change company info
- [Employee] Can create any role or permissions without any approval in its [Company]
SuperUser [Static] < [Application Manager] Johantan
* Can receive Access Token[Login]
* [Application Manager] => SystemAdmin approval
+ [Employee] Can create any role or permissions without any approval in its [Company]
+ [Data] Can manupilate data 4ex Change company info
- [Company] Can only receive [Data] to its own company [ReadOnly]
- SuperUser -> can grant User SuperUser => SystemAdmin approval
[SuperUser] => Employee => Rules&Restrictions
User:
[Dynamic] < [Application Manager]
// Defined Role 4ex [SuperUser] => access right [Login] = Access Token API connect
Annotations:
- When [SuperUser] creates a [Employee] approval=False until [Owner] approval & [Application Manager] sets approval=True
- Simult Test Algorith Codelanacak !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- Crud Collection'da mutlaka expire ile ilgili bi function olacak
- filter listlerin active, delete, regular(active==True and delete==False) function ayrı olacak
- create action lar BaseModellerin içinde olacak ya da (Optional) create, update rule based Inhert kulllan
- Pydanticler model_dump ve excluded_dump olarak inhr.
- Responselar herbiri Response status code, message, completed, data şeklinde olacak
- Create a initilizer with compose yaml.
- Cache ip address to avoid unnecessary request to Api[IP]
Build -> Data
Financial Assets -> Data
Personal Info -> People
Company A -> Company B -> Company C
Company B -> Company D
Company B -> Company E
Company B -> Company Z
score A > B > C
evyos A ankara A ayranci C
Company
1.Company A
2.Company B
3.Company C
4.Company D
5.Company E
6.Company F
Organization Cluster
1. Evyos Evyos Organizasyonu 385 0
2. Ankara Evyos Organizasyonu 385 1
3. Ayrancı Evyos Organizasyonu 385 2
4. BEsat Evyos Organizasyonu 385 2
5. KEsat Evyos Organizasyonu 385 2
6. Keklik Evyos Organizasyonu 385 3
7. İlker Evyos Organizasyonu 385 3
8. İstanbul Evyos Organizasyonu 385 1
9. Kayseri Evyos Organizasyonu 385 2
READ => company_id IN (2, 3, 4, 5, 6, 7)
WRITE => company_id IN (2)
READ => build_id IN (22, 333, 4444, 555, 6, 7)
WRITE => company_id IN (2)
Employee
id company_id employee
1 1 Genel Mudur Company A
2 1 Bekçi Company A
3 2 Genel Mudur Company B
4 2 Bekçi Company B
##### Access to data #####
Role based data access->
# Information Data Block #
Building Information Data -> Service Taker
Company Information Data -> Service Giver
# Offical Data Block #
Building Financial Data -> Service Taker
Company Financial Data -> Service Giver
#### Summary ####
Maximum amount of building a employee can be responsiable of? 50
Alg: Duty(Person) ->
Person = User
Access Token
(Service Giver)
Company R-> Department R-> Duty R-> Employee R-> Person
(Service Taker)
Company R-> Building R-> Person
Service Giver:
Company (related to) Job (related to) Employee (related to) Person
This flow indicates a hierarchical relationship where each entity is related to the next.
Company: The organization providing the service.
Duty: Specific roles or tasks within the company that are related to providing the service.
Employee: The individual performing the job-related tasks within the company.
Person: The individual as a person, highlighting the human element of the employee.
Service Taker:
Company (related to) Job (related to) Employee (related to) Building
This flow indicates a hierarchical relationship where each entity is related to the next, but with a different end point.
Company: The organization receiving the service.
Duty: Specific roles or tasks within the company that are related to managing or utilizing the service.
Employee: The individual performing the job-related tasks within the company.
Building: The physical location or facility where the service is utilized or managed.
duty_id = mapped_column(ForeignKey("duty.id"), nullable=False)
owner_id = mapped_column(ForeignKey("company.id"), nullable=False) X
member_id = mapped_column(ForeignKey("company.id"), nullable=False)
parent_id = mapped_column(ForeignKey("company.id"), nullable=False)
relationship_type = mapped_column(String, nullable=False)
child_count = mapped_column(Integer)
X company
duty_id ? Evyos GM -< Ankara GM Ayrancı GM
select query=
Company Sub
#### Filters ####
Add extra query to Crud:
{
"company_id_in": @Redis[Array],
"build_id_in": @Redis[Array],
"employee_id": @Redis[Array],
}
-------------------------------------------------------------------------------
# Query Pos.
o What are the employee branch? T
- Company filtereleyerek X
+ Mongo Db den brach ı cekerek
o What are sub companies under certain company_id? X
- CompanyRelationship Table like
+ Mongo Db den brach ı cekerek
o Who are my employess [Personel Info]?
EmployeeRelationship Table
Department -> Duty -> Employee
o What buildings are in my responsibilty?
BuildingRelationship Table
o What are certain debts of Build Parts?
CompanyRelationship Table ilke
o Iban and financial informations of Buildings?
AccountingRelationship Table ilke
o Salaries of a group of Employees?
X
o Duty information of a group of Employees?
X
o List Decision Book Items of a build part?
Build R-> Decision Book
Responsiable of related Building
Employee Query if Build view yetkisi varsa -> Decision Book
o Living Space info of a certian person?
Responsiable of related Building
Living Space -> Person Detail Infop
o Which build parts I am responsiable of?
Person -> Build Parts
Query employee -> Building
o Address of a person?
Query employee -> Building
o Email, phone personal info of a employee?
Brach Company
-------------------------------------------------------------------------------
User[Person] -> Employee Salaries Table data
User Company[Employee]
[Table]Company2BuildingRelationship
company_id build_id responsiable
1 3 True
2 3 False
Company2BuildingRelationship: Are these users of this company are responsiable from this building.
[Table]Company2EmployeeRelationship:
company_id employee_id
1 2
1 3
[Table]Company2CompanyRelationship:
1EVYOS 2Ankara 3Besat 4Ayrancı 5Dikmen 6Çayyolu 7Beysukent 8OsmanMah 9NecatiMah
2Ankara -> 3Besat 4Ayrancı 5Dikmen 6Çayyolu 7Beysukent -> 8OsmanMah 9NecatiMah
Top Hiercacy:
ADD field:
top_hiercacy_companies: id: 1, uuid: 1a1a51bd-67f5-4f85-bd7c-1edb6afdaa7e Evyos
Ask for branch ???
Update a branch ???
Delete a branch ???
Carry branch ???
Get "18aa001a-6878-4d39-bc21-0e63ba33beff" -> carry to "1a1a51bd-67f5-4f85-bd7c-1edb6afdaa7e"
DELETE -> INSERT
Go to mongo collection of top_hiercacy_company
--------------------------------------------------------------------------------
[Table]Company2CompanyRelationship: ??? Branch
owner_company_id member_company_id
1 2
2 3
3 4
1 5
1 6
class CompanyRelationship(CrudCollection):
"""
CompanyRelationship class based on declarative_base and CrudCollection via session
"""
__tablename__ = "company_relationship"
__exclude__fields__ = []
duty_id = mapped_column(ForeignKey("duty.id"), nullable=False)
owner_id = mapped_column(ForeignKey("company.id"), nullable=False)
member_id = mapped_column(ForeignKey("company.id"), nullable=False)
parent_id = mapped_column(ForeignKey("company.id"), nullable=False)
child_count = mapped_column(Integer)
json_text = mapped_column(String)
relationship_type = mapped_column(String, nullable=False)
Mehmet Karatay > Javascript
--------------------------------------------------------------------------------
EmployeeRelationship Table
X and Y Employee
Employee ->
Relationship
# Bindings of Queries #
Buildings [Decision Books, Project Books] 2 Resp.
Companies [Duty, Departments] 2 Resp.
Employees [Salaries, People] 2 Resp.
Accounts [Iban, Debits] 2 Resp.
People [LivingSpace, Users, Addresses] 2 Resp.
Role = Company + Job
Employee = Role + People
Employee R-> Employee
Employee R-> AccessRule ???
# Bindings of Actions #
INSERT -> Res? X
UPDATE -> Res? X
SELECT -> Res? |
DELETE -> Res?
ACTIVATE -> Res?
DESTROY -> Res?
id employee_id restrict_id by_who
1 2 3 2
2 2 4 2
3 2 5 2
1 -7 Genel Mudur
Permissions
A | 1 SuperUser
B | 2 Sub SuperUser
C | 3 Sub Sub SuperUser
A1 -> B2 -> C3
Many to Many
1 2

View File

@ -0,0 +1,168 @@
Employees[TOKEN]
User -> Person -> Employees -> Duty -> Department -> Company
Duty -> Occupant -> Department -> Company
Occupant[TOKEN]
User -> People -> LivingSpace -> Building(n) -> BuildPart(n) -> Company
User
?Occupant @User mail = personal mail google.com.tr OR personal domains included
?Employee @User mail = evyos.com.tr OR company domains included
Evyos Free id1 + Evyos [] id2 + Evyos [] id3
0TL + 100TL + 1000TL
Mail Service +
Occupant Types:
Bina Yönetici : 1 tip kullanıcı
Daire Sakini : 2 tip kullanıcı
Daire Sahibi : 3 tip kullanıcı
Bina Görevlisi : 4 tip kullanıcı
Bina Denetcisi : 5 tip kullanıcı
Bina Muhasebecisi : 6 tip kullanıcı
Bina Teknisyeni : 7 tip kullanıcı
Bina Güvenlik Görevlisi : 8 tip kullanıcı
Bina Temizlik Görevlisi : 9 tip kullanıcı
Bina Bahçıvanı : 10 tip kullanıcı
Plan:
evyos_free 1
evyos_basic 2
evyos_premium 3
evyos_enterprise 4
Service:
occupant_id: 1,
plan: 1,
event_id: 1,
service_id: 1,
Company Occupant
User -> Person
o Employee -> Duty -> Department -> Company -> Building -> Person ->
o Building -> Decision Book -> Person ->
CompanyPerson R-> User
CustomerPerson R-> User
class Person:
+ is_employee_related True Company User
+ is_living_space_related True LivingSpace User
is_employee_related:
Cahce company details
Cahce Menu Reach points
Cahce Employee Endpoint Access Rules
Cahce Responsiable Buildings and connect to WAG Services
is_living_space_related:
Cahce BuildPart Details and connect to HAG Services
No need to cache any company details
building_decision_book_responsaible:
Manager:
Supervisor:
##### Step by step Test Guide #####
----- INIT -----
1. department_name: Manager
2. department_name: IT Department
Duty
Company[Managment] (GROOT)
department_name: Manager 1
duty_name: General Manager User(1)
department_name: IT Department 2
duty_name: Application Manager User(2) + Login
duty_name: Database Manager
duty_name: Network Manager
Rule: 78 can create company / employee / duty / department / person
duty_name: Super User User(3) + Login
----- INIT -----
----- API -----
When User(2) creates any row in database it must be confirmed by User(3)[Notification]
User(2) => Login and confirm below...
User(3) => Login and create below...
### Company ###
[GROOT]
Person X 5
Email X 5
Phone X 5
User X 3
Sub Company X 5 [GROOT] && GROOT connect => Sub Company X 5
Sub Sub Company X 5 [Sub Company] && Each Sub Company connect => Sub SUb Company X 2
Sub Company 2 X 5 = 10 User
Sub Sub Company 2 x 25 = 50 User
60 User
10
Person X 2
Email X 2
Phone X 2
User X 2
1. department_name: Manager
1. duty_name: General Manager
1. employee_name: 1
2. department_name: IT Department
2. duty_name: Super User
2. employee_name: 1
### Company ###
### Build ###
### Build ###
### Book ###
### Book ###
### Account ###
### Account ###
----- API -----
class User(Person):
...
class Company:
...
class LivingSpaces:
tenant_person: True
owner_person: True
...

View File

@ -0,0 +1,91 @@
Company
o1 Evyos LTD - System
2 Evyos Istanbul BD
3 Evyos Ankara BD
Evyos Izmir BD
o Evyos Ankara BD
Çankaya YS
YeniMahalle YS
Sincan YS
o Evyos Istanbul BD
Bakırköy YS
Kadıköy YS
Pendik YS
o Evyos Izmir BD
Karşıyaka YS
duty_id
1 GM Evyos
2 GM Evyos Ankara BD
RelationshipDutyCompany
Berkay duty_id SU = id = 5 -> [TOKEN] -< Company_id = 1 Evyos LTD
Koray duty_id SU = id = 7 -> [TOKEN] -< Company_id = 3 Evyos Ankara BD
owner_id member_id parent_id active type duties_id Auto
1 2 1 False Organization 2 @/create
1 3 1 False Organization 2 @/create
1 4 1 False Organization 2 @/create
1 5 3 False Organization 5
1 6 3 False Organization 5
1 7 3 False Organization 5
1 8 2 False Organization
1 9 2 False Organization
1 10 2 False Organization
1 88 3 False Commercial
1 11 4 False Organization
3 5 3 False Organization 3
3 88 3 False Commercial 3
3 6 3 False Organization 3
3 7 3 False Organization 3
Evyos LTD SuperUser (company_id=1)
Login...
2Evyos Istanbul BD Evyos LTD SuperUser + 1
3Evyos Ankara BD Evyos LTD SuperUser + 1
4Evyos Izmir BD Evyos LTD SuperUser + 1
5VevYos Trabzon
1 Evyos LTD Evyos Verimlilik Sistemleri Evyos LTD SuperUser + 1
2Evyos Istanbul BD Istanbul SuperUser Evyos LTD SuperUser + 1
3Evyos Ankara BD Ankara SuperUser Evyos LTD SuperUser + 1
4Evyos Izmir BD Izmır SuperUser Evyos LTD SuperUser + 1
5VevYos Trabzon
CREATE => 1-> company_id:[2,3,4]
VIEW => 1 company_id:[2,3,4,5,6,7...11]
{
"company_id":
}
5Çankaya YS Çankaya YS Evyos Ankara BD SuperUser +
6YeniMahalle YS YeniMahalle YS Evyos Ankara BD SuperUser +
7Sincan YS Sincan YS Evyos Ankara BD SuperUser +
8Bakırköy YS Bakırköy YS
9Kadıköy YS Kadıköy YS
10Pendik YS Pendik YS
11Karşıyaka YS Karşıyaka YS
select * from build a
inner join buid_re b on a.=b.id
where (id = 5)

View File

@ -0,0 +1,37 @@
+ Application Defaults
o Duty form .init
o Department form .init
o RelationshipDutyCompany -> Evyos Ltd -> 78 Super User .init
O Evyos için duty = bulk duty on every company creation -> 78 Super User can access his companies bulk duties
relationship = company_id filter -> Action filter(company_id) relationship_type = Organization
relationship = company_id filter -> Action filter(company_id) relationship_type = Commercial
For every company creation, the following action: Only Create [Organization]
- Create a (Department) Execution Office & Create a (Duty) General Manager
- Create a (Department) IT Department & Create a (Duty) Super User & Create a Bulk Duty for Super User
EndpointRestrictions:
Duty: R-> Endpoint: /company/create" name: "Create Company" code: "AR001" method: "POST"
Abstract Class:
o Get class to inherit from it and check which fields are available for each duty given in table
o Explain the fields ,their usage, and examples
- PATCH /company/create with [TOKEN] -> BaseModel for this duty and ApiEnumDropdowns [RESPONSE]
- PATCH /company/update with [TOKEN] -> BaseModel for this duty and ApiEnumDropdowns [RESPONSE]
Re arrange TOKEN
Token (Save AS) => User => Employee => Menu
+ User ID
+ People ID
+ User Info
+ Employee ID
+ Request [IP + header]
+ List of reachable Endpoint Codes [Array]
+ CompanyId + CompanyUUID
+ DutyId + DutyUUID [duty_id]
+ Priority ID, Priority Code [priority_id ,priority_code]

View File

@ -0,0 +1,53 @@
Event:
mail_gönderme: 1
mail_alma: 2
mail_analiz: 3
xl_import_export: 4
xl_takibi: 5
OccType:
Daire Sakini 1,
EmpType:
Muhasebeci 1,
Plan:
evyos_free 1,
evyos_basic 2,
evyos_premium 3,
evyos_enterprise 4
ApplicationServices:
id: 1
occupant_id: 1,
plan: 1,
id: 2
occupant_id: 1,
plan: 2,
id: 3
occupant_id: 1,
plan: 3,
Events2Services:
event_id: 1,
service_id: 1,
event_id: 1,
service_id: 2,
event_id: 2,
service_id: 2,
event_id: 1,
service_id: 3,
event_id: 2,
service_id: 3,
event_id: 3,
service_id: 3,

View File

@ -0,0 +1,54 @@
- Do the endpoints -
RelationshipDutyCompany org*perm
Select -> Inner Join with duty_id
Create -> Redis cache pre-determined value = company_id
Update -> Redis cache pre-determined with duty_id
Select -> Inner Join with duty_id
Create -> Redis cache pre-determined value = company_id
Update -> Redis cache pre-determined with duty_id
Redis Cache material
- duty_id
- duty_uu_id
- duty_code: 96
- company_id
- company_uu_id
- uu_id
- get_available_patch_methods(['confirm', 'delete', 'active'])
Endpoint Acccess List
list endpoint + confirm-delete-active
{
confirm True, delete=True, active=True,
}
POST
update endpoint +
create endpoint +
PATCH endpoint && update endpoint +
duty_code ??? if 96 =>
{
"patch_type": [
"confirm", Application Manager [OK] : Restrict
"delete", SuperUser
"active", SuperUser
]}

View File

@ -0,0 +1,9 @@
Notlar
ApiEnum Dropdown her seferinde load üretiyor onun yerine obje attribute olarak ekle
__enums__ = {
"abc": [],
"abcd": []
}

View File

@ -0,0 +1,107 @@
Department:
Bağımsız bir işi yapan kadrolar tümüne
Staff:
Duty yapacak kadro
Employee:
Staffdaki çalışanlar
İnsan Kaynakları
Department
class ModuleSection:
module_section = ["Department", "OccupantTypes"]
...
Module -> Service -> Event -> 500MB default 0.00TL core, def
Module -> Service -> Event -> 1GB price 10.00TL add-on
Module -> Service -> Event -> 2GB price 20.00TL add-on
İç Hizmetler Müdürlüğü
Module: Satış Departmanı Modülü Base 0.00TL
Cari Servisi (Service)
+ Cari Hesap Okuma Event 0.00TL
+ Cari Hesap Uyarma Event 0.00TL
+ Cari Hesap Analiz Event 0.00TL
Toplam: 0.00TL
Module: Satış Departmanı Modülü Permium 30 TL
Cari Servisi Premium (Service)
+ Cari Hesap Okuma Event 0.00TL
+ Cari Hesap Uyarma Event 0.00TL
+ Cari Hesap Analiz Event 0.00TL
+ Cari Hesap Mail Event 10.00TL
+ Cari Hesap SMS Event 20.00TL
Toplam: 30.00TL
Dış Hiztmetler Müdürlüğü
Module (Department) | Service | -> (n) Duty -> Staff -> Employee -> Event
Module (OccupantTypes) | Service | -> -> (n) Duty -> Staff -> Employee -> LivingSpace -> Event
Service:
OccupantType + Module
OccupantType -> User -> People
Event -> Service
Department -> (n) Module -> Duty -> Staff -> Employee
Mali İşler -> A Muhasabe B Finans ->
user -> people.id + occupant_type.id -> BuildLivingSpace -> Module -> Modules2Occupant -> Event
user -> employee.id -> Duty -> Staff -> Employee -> Event -> Module -> Modules2Employee -> Event
Employee
X Occupant
User:
1. Employee
employee.id () => Module
2. (n) Occupant Types
-> Daire Sakini () => Module
-> Daire Sahibi people.id () => Module
-> Staff () people.id X buildmanagment_staff.id => Module
Duty : Employee
User ->
is_occupant: False
Employee
Staff
is_occupant: True
LivingSpace
Occupant_Type
class LivingSpace:
People people.id false
BuildPart build.id
Occupant_type Daire Sakini
start_date =
stop_date =
agremeent_no =
LivingSpace:
Occupant occupant.id
LivingSpaceType living_space_type

View File

@ -0,0 +1,210 @@
postgres EndpointRestriction(CrudCollection):
"""
Initiliaze Endpoint Restriction on default
"""
__tablename__ = "endpoint_restriction"
__exclude__fields__ = []
endpoint_name = mapped_column(String, server_default="")
endpoint_method = mapped_column(String, server_default="")
endpoint_desc = mapped_column(String, server_default="")
endpoint_code = mapped_column(String, server_default="", unique=True)
endpoint_priority = mapped_column(SmallInteger, server_default="0")
postgres Priority(CrudCollection):
"""
Initiliaze at api roles on default
4ex.
{
"0": "User",
"4": "Owner",
"8": "Tenant",
"12": "Freelancer",
"16": "Tech",
"78": "Super User",
"96": "Database Manager",
"97": "Network Manager",
"98": "Application Manager",
"99": "System Admin",
}
"""
__tablename__ = "priority"
__exclude__fields__ = []
priority_code = mapped_column(SmallInteger, server_default="0")
priority_desc = mapped_column(String, server_default="")
postgres User(CrudCollection):
"""
Application User frame to connect to api with assigned token based HTTP connection
"""
__tablename__ = "user"
__exclude__fields__ = [
"hash_password",
"password_token",
"expiry_begins"
]
user_tag = mapped_column(String(64), server_default="", comment="User Tag")
email = mapped_column(String(128), server_default="")
phone_number = mapped_column(String, server_default="")
avatar = mapped_column(String, server_default="")
hash_password = mapped_column(String(256), server_default="")
password_token = mapped_column(String(256), server_default="")
remember_me = mapped_column(Boolean, server_default="0")
expires_day = mapped_column(Integer, server_default=env.PASSWORD_EXPIRE_DAY, comment="Password Expires in Days") // Password must be changed by user in [expires_day] days
expiry_begins = mapped_column(TIMESTAMP, server_default=func.now())
priority_id = mapped_column(ForeignKey("priority.id"), nullable=False)
person_id = mapped_column(ForeignKey("people.id"), nullable=False)
priority: Mapped["Priority"] = relationship("Priority", back_populates="user", foreign_keys=[priority_id])
@property def expiry_ends():
return expiry_begins + expires_day
@property
def is_super_user():
return bool(self.priority.priority_code == 78)
@property
def is_user():
return bool(self.priority.priority_code == 0)
postgres Person(CrudCollection):
"""
People that are related to users in application
"""
__tablename__ = "person"
__exclude__fields__ = []
firstname = mapped_column(String(24), nullable=False, comment="First Name")
surname = mapped_column(String(24), nullable=False, comment="Surname")
middle_name = mapped_column(String(16), server_default="")
sex_code = mapped_column(String(1), nullable=False, comment="Sex Code")
person_ref = Mapped[str] = mapped_column(String(24), server_default="")
person_tag = mapped_column(String(64), server_default="")
// ENCRYPT DATA
father_name = mapped_column(String(24), server_default="")
mother_name = mapped_column(String(24), server_default="")
country_code = mapped_column(String(4), server_default="TR")
national_identity_id = mapped_column(String(48), server_default="")
birth_place = mapped_column(String(24), server_default="")
birth_date = mapped_column(TIMESTAMP, server_default="1900-01-01")
tax_no = mapped_column(String(48), server_default="")
// ENCRYPT DATA
class Company(CrudCollection):
"""
Company class based on declarative_base and CrudCollection via session
formal_name = Government register name by offical
public_name = Public registered name by User
nick_name = Search by nickname, commercial_type = Tüzel veya birey
"""
__tablename__ = "company"
__exclude__fields__ = ["is_blacklist", "is_commercial"]
formal_name = mapped_column(String(64), nullable=False, comment="Formal Name")
company_type = mapped_column(String(1), nullable=False, comment="Company Type")
commercial_type = mapped_column(
String(5), nullable=False, comment="Commercial Type"
)
tax_no = mapped_column(
String(48), index=True, unique=True, nullable=False, comment="Tax No"
)
public_name = mapped_column(String(64))
nick_name = mapped_column(String(64))
default_lang_type = mapped_column(String(5), server_default="TR")
default_money_type = mapped_column(String(5), server_default="TL")
is_commercial = mapped_column(Boolean, server_default="False")
is_blacklist = mapped_column(Boolean, server_default="False")
official_address_id = mapped_column(ForeignKey("address.id"))
parent_id = mapped_column(ForeignKey("company.id"))
# Rule of Mongo Collection Creation #
// To avoid data load for no-sql storage all collection must be created in a pattern of
// mongo_collection_name = str(Company.uu_id()) + str(storage_reasoning) 4ex. : mongo_collection_name = str(Company.uu_id()) + str('UserPasswordHistory')
// MongoCollectionBase = str(Company.uu_id())
[Company][info] -> [Company][info] -> [Company][info] -> [Company][info]
Mongo MongoCollectionBase + Access:
{
}
Mongo MongoCollectionBase + Domain:
{
"user_id": 1,
"domain_tag": {
...
},
}
!! ADD domain_tag for user to name this domain -> so user can use domain with device that is saved
Mongo MongoCollectionBase + PasswordHistory:
{
"user_id": 1,
"password_history":
[
...{
"password_hashed": "", // String
"tmstp": "" // TMSTP,
}
],
"access_history_detail": device_single_history
}
Mongo MongoCollectionBase + AccessHistory:
// Last 60 History of a user login to application
// ! add function retrieve_last()
{
"access_history":
[
...{
"platform": "", // String
"agent": "", // String
"last_seen": "", // TMSTP
"remote_addr": "", // String
"geo_location": "", // String
"detail": {} // From ip retrieve api data
}
],
}

View File

@ -0,0 +1,71 @@
/event/create
/authentication/select
/authentication/valid
/Duty/list
/Duty/create
/Duty/update/{company_uu_id}
/Duty/patch/{company_uu_id}
/duties/list
/duties/create
/People/list/
/People/create
/People/update/{user_uu_id}
/People/patch/{user_uu_id}
/event/list
/event/register/employee
/event/register/occupant
/User/list
/User/create
/User/update/{user_uu_id}
/User/patch/{user_uu_id}
/Company/list
/Company/create
/Company/update/{company_uu_id}
/Company/patch/{company_uu_id}
/Department/list
/Department/create
/Department/update/{company_uu_id}
/Department/patch/{company_uu_id}
/building/build/list
/building/build/create
/building/build/update/{build_uu_id}
/building/build/patch/{build_uu_id}
/Building/Parts/list
/Building/Parts/create
/Building/Parts/update/{build_uu_id}
/Building/Parts/patch/{build_uu_id}
/Building/Sites/patch/{build_uu_id}
/Building/Area/patch/{build_uu_id}
/Building/LivingSpace/list
/Building/LivingSpace/create
/Building/LivingSpace/update/{build_uu_id}
/Building/LivingSpace/patch/{build_uu_id}
/Build/DecisionBook/list
/Build/DecisionBook/create
/Build/DecisionBook/update/{book_uu_id}
/Build/DecisionBook/patch/{book_uu_id}
/Build/DecisionBook/Person/list
/Build/DecisionBook/Person/create
/Build/DecisionBook/Person/update/{book_uu_id}
/event/list
/Build/DecisionBook/Person/patch/{book_uu_id}
/Build/DecisionBook/Items/list
/Build/DecisionBook/Items/create
/Build/DecisionBook/Items/update/{book_uu_id}
/Build/DecisionBook/Items/patch/{book_uu_id}
/Build/DecisionBook/Items/Debits/list
/Build/DecisionBook/Items/Debits/create
/Build/DecisionBook/Items/Debits/update/{book_uu_id}
/Build/DecisionBook/Items/Debits/patch/{book_uu_id}
/Build/ProjectDecisionBook/list
/Build/ProjectDecisionBook/create
/Build/ProjectDecisionBook/update/{book_uu_id}
/Build/ProjectDecisionBook/patch/{book_uu_id}
/Build/ProjectDecisionBook/Items/list
/Build/ProjectDecisionBook/Items/create
/Build/ProjectDecisionBook/Items/update/{book_uu_id}
/Build/ProjectDecisionBook/Items/patch/{book_uu_id}
/Build/ProjectDecisionBook/Items/Debits/list
/Build/ProjectDecisionBook/Items/Debits/create
/Build/ProjectDecisionBook/Items/Debits/update/{book_uu_id}
/Build/ProjectDecisionBook/Items/Debits/patch/{book_uu_id}

View File

@ -0,0 +1,21 @@
/Duty/list
/Duty/create
/duties/list
/duties/create
/People/list
/People/create
/event/register/employee
/event/register/occupant
/User/list
/User/create
/Company/list
/Company/create
/Department/list
/Department/create
/building/build/list
/Building/Parts/list
/Building/LivingSpace/list
/Build/DecisionBook/list

View File

@ -0,0 +1,138 @@
Company[Evyos]
Create Department[Department]
- Genel Müdürlük GM
- Mali İşler Departmanı MD
- İnsan Kaynakları Departmanı İKD
- Satış Departmanı SD
- Bilgi Teknolojileri Departmanı BTD
Create Duty[Duty]
- Genel Müdür GM 1
- Mali İşler Direktörlüğü MD
- İnsan Kaynakları Direktörlüğü İKD
- Satış Direktörlüğü SD
- Bilgi Teknolojileri Direktörlüğü BTD
- Muhasebe Müdürlüğü MM
- Finans Müdürlüğü FM
- Muhasabe Şefliği MS
- Muhasebe Uzmanı MU
- Muhasebe Elemanı ME
- Finans Şefliği FS
- Finans Uzmanı FU
- Finans Elemanı FE
- İnsan Kaynakları Müdürlüğü İKM
- İnsan Kaynakları Şefliği İKS
- İnsan Kaynakları Uzmanı İKU
- İnsan Kaynakları Elemanı İKE
- Satış Müdürlüğü SM
- Satış Bölge Şefliği SS
- Satış Temsilcisi ST
- Veri Tabanı Yöneticisi VTY
- Aplikasyon Sorumlusu AS
- Ağ Yöneticisi AY
Create Staff[Staff]
- Genel Müdür GM 1 | Duty: Genel Müdür
- Mali İşler Direktörü MD 1 | Duty: Mali İşler Direktörlüğü
- İnsan Kaynakları Direktörü İKD 2 | Duty: İnsan Kaynakları Direktörlüğü
- Satış Direktörü SD 3 | Duty: Satış Direktörlüğü
- Bilgi Teknolojileri Direktörü BTD 6 | Duty: Bilgi Teknolojileri Direktörlüğü
- Muhasabe Müdürü MM | Duty: Muhasebe Müdürlüğü
- Finans Müdürü FM | Duty: Finans Müdürlüğü
- Muhasabe Şefi MS | Duty: Muhasabe Şefliği
- Muhasabe Uzmanı MU | Duty: Muhasebe Uzmanı
- Digital Muhasabe Elemanı | Duty: Muhasebe Elemanı
- Muhasabe Elemanı | Duty: Muhasebe Elemanı
- Finans Şefi FS | Duty: Finans Şefliği
- Finans Uzmanı FU | Duty: Finans Uzmanı
- Finans Elemanı FE | Duty: Finans Elemanı
- İnsan Kaynakları Müdürü İKM | Duty: İnsan Kaynakları Müdürlüğü
- İnsan Kaynakları Şefi İKS | Duty: İnsan Kaynakları Şefliği
- İnsan Kaynakları Uzmanı İKU | Duty: İnsan Kaynakları Uzmanı
- İnsan Kaynakları Elemanı İKE | Duty: İnsan Kaynakları Elemanı
- Satış Müdürü SM | Duty: Satış Müdürlüğü
- Satış Ankara Bölge Şefi SS | Duty: Satış Bölge Şefliği
- Satış İstanbul Bölge Şefi SS | Duty: Satış Bölge Şefliği
- Satış İzmir Bölge Şefi SS | Duty: Satış Bölge Şefliği
- Satış Ankara Çankaya Temsilcisi ST | Duty: Satış Temsilcisi
- Satış Ankara Keçiören Temsilcisi ST | Duty: Satış Temsilcisi
- Satış Ankara Yenimahalle Temsilcisi ST | Duty: Satış Temsilcisi
- Satış İstanbul Beylikdüzü Temsilcisi ST | Duty: Satış Temsilcisi
- Satış İstanbul Kadıköy Temsilcisi ST | Duty: Satış Temsilcisi
- Satış İstanbul Üsküdar Temsilcisi ST | Duty: Satış Temsilcisi
- Satış İzmir Bornova Temsilcisi ST | Duty: Satış Temsilcisi
- Veri Tabanı Yöneticisi VTY | Duty: Veri Tabanı Yöneticisi
- Aplikasyon Sorumlusu AS | Duty: Aplikasyon Sorumlusu
- Super User AS | Duty: Aplikasyon Sorumlusu
- Ağ Yöneticisi AY | Duty: Ağ Yöneticisi
o Department - İcra Kurulu İCK
Duty[İCK]
- [Duty]Genel Müdür GM 1 --> Staff[GM] - Genel Müdür GM 1
- [Duty]Mali İşler Direktörlüğü MD --> Staff[MD] - Mali İşler Direktörü MD 1
- [Duty]İnsan Kaynakları Direktörlüğü İKD --> Staff[İKD] - İnsan Kaynakları Direktörü İKD 2
- [Duty]Satış Direktörlüğü SD --> Staff[SD] - Satış Direktörü SD 3
- [Duty]Bilgi Teknolojileri Direktörlüğü BTD --> Staff[BTD] - Bilgi Teknolojileri Direktörü BTD 6
- [Duty]Pazarlama Direktörlüğü PD --> Staff[PD] - Pazarlama Direktörü PD 4
- [Duty]Operasyon Direktörlüğü OD --> Staff[OD] - Operasyon Direktörü OD 5
o Department - Mali İşler Departmanı MD
Duty[Mİ]
- [Duty]Muhasebe Müdürlüğü MM --> Staff[MD] Muhasabe Müdürü MM
- [Duty]Finans Müdürlüğü FM --> Staff[MD] Finans Müdürü FM
- [Duty]Muhasabe Şefliği MS 4 --> Staff[MM] Muhasabe Şefi MS
- [Duty]Muhasebe Uzmanı MU 5 --> Staff[MM] Muhasabe Uzmanı MU
- [Duty]Muhasebe Elemanı ME 6 --> Staff[MM] Digital Muhasabe Elemanı
--> Staff[MM] Muhasabe Elemanı
- [Duty]Finans Şefliği FS 7 --> Staff[FM] Finans Şefi FS
- [Duty]Finans Uzmanı FU 8 --> Staff[FM] Finans Uzmanı FU
- [Duty]Finans Elemanı FE 9 --> Staff[FM] Finans Elemanı FE
o Department - İnsan Kaynakları Departmanı İKD
Duty[İKD]
- [Duty]İnsan Kaynakları Müdürlüğü İKM --> Staff[İKD] İnsan Kaynakları Müdürü İKM
- [Duty]İnsan Kaynakları Şefliği İKS --> Staff[İKM] İnsan Kaynakları Şefi İKS
- [Duty]İnsan Kaynakları Uzmanı İKU --> Staff[İKS] İnsan Kaynakları Uzmanı İKU
- [Duty]İnsan Kaynakları Elemanı İKE --> Staff[İKS] İnsan Kaynakları Elemanı İKE
o Department - Satış Departmanı SD
- [Duty]Satış Müdürlüğü SM --> Staff[SD] Satış Müdürü SM
- [Duty]Satış Bölge Şefliği SS --> Staff[SM] Satış Ankara Bölge Şefi SS
--> Staff[SM] Satış İstanbul Bölge Şefi SS
--> Staff[SM] Satış İzmir Bölge Şefi SS
- [Duty]Satış Temsilcisi ST --> Staff[SS] Satış Ankara Çankaya Temsilcisi ST
--> Staff[SS] Satış Ankara Keçiören Temsilcisi ST
--> Staff[SS] Satış Ankara Yenimahalle Temsilcisi ST
--> Staff[SS] Satış İstanbul Beylikdüzü Temsilcisi ST
--> Staff[SS] Satış İstanbul Kadıköy Temsilcisi ST
--> Staff[SS] Satış İstanbul Üsküdar Temsilcisi ST
--> Staff[SS] Satış İzmir Bornova Temsilcisi ST
--> Staff[SS] Satış İzmir Karşıyaka Temsilcisi ST
--> Staff[SS] Satış İzmir Konak Temsilcisi ST
o Department - Bilgi Teknolojileri Departmanı BTD
- [Duty]Veri Tabanı Yöneticisi VTY --> Staff[BTD] Veri Tabanı Yöneticisi VTY
- [Duty]Aplikasyon Sorumlusu AS --> Staff[BTD] Aplikasyon Sorumlusu AS
--> Staff[BTD] Super User AS
- [Duty]Ağ Yöneticisi AY --> Staff[BTD] Ağ Yöneticisi AY

View File

@ -0,0 +1,68 @@
--- Event Architecture ---
Module:
Şirkete yada kavramsal gruba devrideleden süreçler bütünü. Farklı departmanlara verilen eylemler bütünü.
Servis:
Bir modülün içerisindeki eylemler bütünü. Farklı görevleri yerine getirmek için kullanılan hizmetler.
Eylem:
Bir servisin işini farklı parametrelerle yapmasını sağlayan işlemler.
Olay:
Bir görevi yerine getirken oluşan temel fonksiyonlar. Bir eylemin gerçekleşmesi için gerekli olan temel işlemler.
example event endpoint: "https://app.evyos.com.tr/events/[module]/[service]/[action]/[event-uu-id]"
example event endpoint: "https://[IP]:port/[event-uu-id]"
Which events I can reach?
TOKEN
Module -> Service -> Action -> Events
https://[IP]:port/8oYt-lkashdıayusd-qjkywuıyh
Module: Sales Module
Service: Company
Action: Create
Event: 1
{
"event_entity_id": 1,
"name": "Create Company",
"description": "Create a new company",
"property_description": "Create a new company with all the necessary information",
"marketing_layer": 3,
"cost": 0.00,
"unit_price": 0.00,
"endpoint_id": 1
}
SuperUser:
Module: Core
Service: It Department
Action: Company Create
Event: 1
employee_id: 1
Module: Sales
Service: Company
Action: Create
Event: 1
Service: Company
Action: Update
Event: 2
Module: Marketing
Service: Company
Action: Create
Event-uu-id: 9uyt-8u7y-8u7y-8u7y
Event-uu-id: 10yt-9u7y-8u7y-8u7y
request: POST /events/sales/company/

View File

@ -0,0 +1,29 @@
App initialisation
------------------
1. Run app to deploy init data via app.py/create_app/create_application_defaults function
2. Login with super user which is defined in app.py/create_app/create_application_defaults function
3. Create a sub company @evyos.com/company/add
4. Connect Main Company[Evyos] 2-> Sub Company[New Company] evyos.com/company/available/organization
5. Add new people @evyos.com/people/add
6. Add new user @evyos.com/user/add [LATER]
7. Make new added people available for a certain duty or create new super user for new company @evyos.com/people/available/employee
Super User Actions with no event declared on system
---------------------------------------------------
@evyos.com/departments/add => Add new department
@evyos.com/duty/add => Attach new duty to new department
@evyos.com/staff/add => Add new staff to new department
Connect people to staff @evyos.com/employee/match
-> Logout with super user
-> Login with Sales Employee
----------------------------------------------------
1. Create a new building @evyos.com/building/build/add
2. Create a new build area @evyos.com/building/area/add
3. Create a new build part @evyos.com/building/part/add
4.

View File

@ -0,0 +1,43 @@
Modules:
[Super User Module]
Services -> Action:
[Account]
-> Create Account
-> Update Account
-> Delete Account
-> List Account
[Address]
-> Create Address
-> Update Address
-> Delete Address
-> List Address
[Api]
[Application]
[Authentication]
[Build]
[Buildparts]
[Buildsection]
[Livingspaces]
[Company]
[Department]
[Duties]
[Duty]
[Employee]
[Staff]
[DecisionBook]
[DecisionBookItems]
[DecisionBookItemsDebits]
[DecisionBookPerson]
[Events]
[People]
[ProjectDecisionBook]
[Rules]
[Users]

View File

@ -0,0 +1,49 @@
User Types
1. Employee
2. Occupant
[Login Action]
------Occupant------
Person -> User:
Company -> Department -> Duty -> Staff -> Employee -> Person | (n) Occupant -> Person
People[people_id] -> User[Login Intersect] -> BuildLivingSpace -> BuildPart -> Build -> Responsible Employee -> Company
Person [people_id]
- Occupant Type [occupant_id] + Build Part [build_parts_id]
------Employee------
Person -> User:
Company -> Department -> Duty -> Employee -> Person | (n) Employee
People[people_id] -> User[Login Intersect] -> Employee[staff_id] -> Staff -> Duty -> Department -> Company
1. Person [people_id]
2. Staff [staff_id]
Employee login TOKEN requires:
Company : evyos.com
Department : Satış Dep.
Duty : Temsilci
Employee: Berkay Karatay[Person]
(n) Occupant
Occupant: Melih[Person]
Occupant: Songül[Person]
Occupant: Günay[Person]
::Add middleware endpoint control

View File

@ -0,0 +1,10 @@
1- Geçen yıla ait toplantıda 2nolu gündemde bahsedilen kanalizasyon için her bir kanalizasyon çıkışı için fiyat alınarak proje açılacaktır. Arka alana yağmur suyu drenajın yaptırılması.
2- Aidat gündemi içim 1-2-3nolu daireler için 1.400 TL. diğer daireler için 1.500 TL. olarak apartman hesabına ödeme yapılmasına.
3- Hali hazırda yöneticilik görevini ifa eden Mehmet Karatayın görevine devam etmesine.
4- Kirişin içinden geçen kalorifer borusunun çıkarılmadan kesilmesine ve gerekli tadilatın yapılıp problemin çözülmesine ve bu arada ayrıca her dairenin kalorifer borularında su olmadığı için gerekli her radyatörlerinin temizliğini kendisinin yaptırmasına.
5- Doğalgaz tadilatından çıkan hurda boruların hurdacı tarafından gelip alınarak satışının yapılmasına.
6- Apartman içinin tadilatının yapılmasın, ışıkların ve elektrik sisteminin elden geçirilmesi ve elektrik sayaçlarının panolara konulmasına ve yeni yapılan doğalgaz boruların pasa karşı astar boya ile ve sarı renkle boyanmasına.
7- İç kapı teklifi alınarak gerekli tadilatın gerçekleştirilmesi için çalışma yapılması, ek kapı veya tek kapı seçenekleri değerlendirilerek fiyat alınmasına,
8- Binanın su depo temizliğinin yapılmasına.
9- Çatı havalandırma camlarından çatlamış olanların değiştirilmesine.
10- Arka zemin dairenin yoğun yağışlarda evini su basmasından korunmak amacı ile saçak yapılmasına karar verilmiştir.

View File

@ -0,0 +1,140 @@
{
"_id": {
"$oid": "662a85f05b8acaaa3b37238c"
},
"user_id": 7,
"menu": {
"only_menu_item": false,
"item_order": 0,
"layer": 0,
"app_name": "Tanımlama Menüsü",
"app_description": "Tanımlama Menüsü",
"app_path": "",
"uu_id": "166d9a3f-495e-4261-baab-dd456e9d294b",
"app_parent_items_id": null,
"after_separator": false,
"row_limit": 100,
"read": true,
"write": false,
"delete": false,
"report_print": false,
"report_export": false,
"program_name": "APP166d9a3f495e4261baabdd456e9d294b",
"children": [
{
"only_menu_item": false,
"item_order": 10,
"layer": 1,
"app_name": "Firma İşlemleri",
"app_description": "Firma İşlemleri",
"app_path": "",
"uu_id": "d1aa4365-b1ef-4c91-ac8e-e3289f7eb075",
"app_parent_items_id": "166d9a3f-495e-4261-baab-dd456e9d294b",
"after_separator": false,
"row_limit": 100,
"read": true,
"write": false,
"delete": false,
"report_print": false,
"report_export": false,
"program_name": "APPd1aa4365b1ef4c91ac8ee3289f7eb075",
"children": [
{
"only_menu_item": true,
"item_order": 20,
"layer": 2,
"app_name": "Firma Tanımlama",
"app_description": "Firma Tanımlama",
"app_path": "create_company",
"uu_id": "a3c60a25-ff46-4872-b209-9e501dde7b73",
"app_parent_items_id": "d1aa4365-b1ef-4c91-ac8e-e3289f7eb075",
"after_separator": false,
"row_limit": 100,
"read": true,
"write": false,
"delete": false,
"report_print": false,
"report_export": false,
"program_name": "APPa3c60a25ff464872b2099e501dde7b73"
}
]
},
{
"only_menu_item": false,
"item_order": 30,
"layer": 1,
"app_name": "Personel İşlemleri",
"app_description": "Personel İşlemleri",
"app_path": "",
"uu_id": "eebb591d-842b-4495-8721-e09552665a06",
"app_parent_items_id": "166d9a3f-495e-4261-baab-dd456e9d294b",
"after_separator": false,
"row_limit": 100,
"read": true,
"write": false,
"delete": false,
"report_print": false,
"report_export": false,
"program_name": "APPeebb591d842b44958721e09552665a06",
"children": [
{
"only_menu_item": true,
"item_order": 40,
"layer": 2,
"app_name": "Kişi Tanımlama",
"app_description": "Kişi Tanımlama",
"app_path": "create_person",
"uu_id": "0c6c8cd2-f6b7-471f-9671-5cc1ac9f502e",
"app_parent_items_id": "eebb591d-842b-4495-8721-e09552665a06",
"after_separator": false,
"row_limit": 100,
"read": true,
"write": false,
"delete": false,
"report_print": false,
"report_export": false,
"program_name": "APP0c6c8cd2f6b7471f96715cc1ac9f502e"
}
]
},
{
"only_menu_item": false,
"item_order": 50,
"layer": 1,
"app_name": "Bina İşlemleri",
"app_description": "Bina İşlemleri",
"app_path": "",
"uu_id": "66627ebb-0425-425f-bc0f-8a943eb0a3ca",
"app_parent_items_id": "166d9a3f-495e-4261-baab-dd456e9d294b",
"after_separator": false,
"row_limit": 100,
"read": true,
"write": false,
"delete": false,
"report_print": false,
"report_export": false,
"program_name": "APP66627ebb0425425fbc0f8a943eb0a3ca",
"children": [
{
"only_menu_item": true,
"item_order": 60,
"layer": 2,
"app_name": "Bina ve bölüm tanımlama",
"app_description": "Bina ve bölüm tanımlama",
"app_path": "create_build",
"uu_id": "173c4d8e-5577-4d4d-8712-f6fa2fbc8019",
"app_parent_items_id": "66627ebb-0425-425f-bc0f-8a943eb0a3ca",
"after_separator": false,
"row_limit": 100,
"read": true,
"write": false,
"delete": false,
"report_print": false,
"report_export": false,
"program_name": "APP173c4d8e55774d4d8712f6fa2fbc8019"
}
]
}
]
}
}

View File

@ -0,0 +1,229 @@
import json
data = '{"menu":[{"only_menu_item":false,"item_order":0,"layer":0,"app_name":"Tanımlama Menüsü","app_description":"Tanımlama Menüsü","app_path":"","uu_id":"166d9a3f-495e-4261-baab-dd456e9d294b","app_parent_items_id":null,"after_separator":false,"row_limit":100,"read":true,"write":false,"delete":false,"report_print":false,"report_export":false,"program_name":"APP166d9a3f495e4261baabdd456e9d294b"},{"only_menu_item":false,"item_order":10,"layer":1,"app_name":"Firma İşlemleri","app_description":"Firma İşlemleri","app_path":"","uu_id":"d1aa4365-b1ef-4c91-ac8e-e3289f7eb075","app_parent_items_id":"166d9a3f-495e-4261-baab-dd456e9d294b","after_separator":false,"row_limit":100,"read":true,"write":false,"delete":false,"report_print":false,"report_export":false,"program_name":"APPd1aa4365b1ef4c91ac8ee3289f7eb075"},{"only_menu_item":true,"item_order":20,"layer":2,"app_name":"Firma Tanımlama","app_description":"Firma Tanımlama","app_path":"create_company","uu_id":"a3c60a25-ff46-4872-b209-9e501dde7b73","app_parent_items_id":"d1aa4365-b1ef-4c91-ac8e-e3289f7eb075","after_separator":false,"row_limit":100,"read":true,"write":false,"delete":false,"report_print":false,"report_export":false,"program_name":"APPa3c60a25ff464872b2099e501dde7b73"},{"only_menu_item":false,"item_order":30,"layer":1,"app_name":"Personel İşlemleri","app_description":"Personel İşlemleri","app_path":"","uu_id":"eebb591d-842b-4495-8721-e09552665a06","app_parent_items_id":"166d9a3f-495e-4261-baab-dd456e9d294b","after_separator":false,"row_limit":100,"read":true,"write":false,"delete":false,"report_print":false,"report_export":false,"program_name":"APPeebb591d842b44958721e09552665a06"},{"only_menu_item":true,"item_order":40,"layer":2,"app_name":"Kişi Tanımlama","app_description":"Kişi Tanımlama","app_path":"create_person","uu_id":"0c6c8cd2-f6b7-471f-9671-5cc1ac9f502e","app_parent_items_id":"eebb591d-842b-4495-8721-e09552665a06","after_separator":false,"row_limit":100,"read":true,"write":false,"delete":false,"report_print":false,"report_export":false,"program_name":"APP0c6c8cd2f6b7471f96715cc1ac9f502e"},{"only_menu_item":false,"item_order":50,"layer":1,"app_name":"Bina İşlemleri","app_description":"Bina İşlemleri","app_path":"","uu_id":"66627ebb-0425-425f-bc0f-8a943eb0a3ca","app_parent_items_id":"166d9a3f-495e-4261-baab-dd456e9d294b","after_separator":false,"row_limit":100,"read":true,"write":false,"delete":false,"report_print":false,"report_export":false,"program_name":"APP66627ebb0425425fbc0f8a943eb0a3ca"},{"only_menu_item":true,"item_order":60,"layer":2,"app_name":"Bina ve bölüm tanımlama","app_description":"Bina ve bölüm tanımlama","app_path":"create_build","uu_id":"173c4d8e-5577-4d4d-8712-f6fa2fbc8019","app_parent_items_id":"66627ebb-0425-425f-bc0f-8a943eb0a3ca","after_separator":false,"row_limit":100,"read":true,"write":false,"delete":false,"report_print":false,"report_export":false,"program_name":"APP173c4d8e55774d4d8712f6fa2fbc8019"}]}'
class Menu:
def __init__(self, json_data):
self.data = {}
self.json = json_data
self.app_name = None
self.app_description = None
self.app_path = None
self.uu_id = None
self.app_parent_items_id = None
self.children = {}
self.only_menu_item = None
self.item_order = None
self.layer = None
self.before_separator = None
self.row_limit = None
self.read = None
self.write = None
self.delete = None
self.report_print = None
self.report_export = None
self.program_name = None
self.dct = {}
self.import_data()
def add_item(
self,
only_menu_item,
item_order,
layer,
app_name,
app_description,
app_path,
uu_id,
app_parent_items_id,
before_separator,
row_limit,
read,
write,
delete,
report_print,
report_export,
program_name,
):
self.app_name = app_name
self.app_description = app_description
self.app_path = app_path
self.uu_id = uu_id
self.app_parent_items_id = app_parent_items_id
self.children = {}
self.only_menu_item = only_menu_item
self.item_order = item_order
self.layer = layer
self.before_separator = before_separator
self.row_limit = row_limit
self.read = read
self.write = write
self.delete = delete
self.report_print = report_print
self.report_export = report_export
self.program_name = program_name
self.dct = dict(
app_parent_items_id=app_parent_items_id,
uu_id=uu_id,
app_name=app_name,
children={},
app_path=app_path,
app_description=app_description,
only_menu_item=self.only_menu_item,
item_order=self.item_order,
layer=self.layer,
before_separator=self.before_separator,
row_limit=self.row_limit,
read=self.read,
write=self.write,
delete=self.delete,
report_print=self.report_print,
report_export=self.report_export,
program_name=self.program_name,
)
xx = self.find_data(self.data, str(app_parent_items_id))
if not xx:
self.data[self.uu_id] = self.dct
else:
xx["children"][self.uu_id] = self.dct
# xx.self.children[self.uu_id] = self.dct
# self.add_data(self.data, None)
def find_data(self, search_data, find_text):
if find_text is None:
return None
for x, y in search_data.items():
if x == find_text:
print(find_text, " bulundu")
# y["children"].append(self.dct)
return y
if "children" in y and len(y["children"]) > 0:
ret = self.find_data(y["children"], find_text)
if ret is not None:
return ret
return None
@staticmethod
def show_col(i, y):
print(
"layer :",
i,
" app_parent_items_id",
y["app_parent_items_id"],
"uu_id",
y["uu_id"],
"app_name",
y["app_name"],
"app_path",
y["app_path"],
"app_description",
y["app_description"],
"only_menu_item",
y["only_menu_item"],
"item_order",
y["item_order"],
"layer",
y["layer"],
"before_separator",
y["before_separator"],
"row_limit",
y["row_limit"],
"read",
y["read"],
"write",
y["write"],
"delete",
y["delete"],
"report_print",
y["report_print"],
"report_export",
y["report_export"],
"program_name",
y["program_name"],
)
def show_data(self):
# print(self.data)
for x, y in self.data.items():
self.show_col(0, y)
if type(y) is dict:
for a, b in y["children"].items():
self.show_col(1, b)
if type(y) is dict:
for c, d in b["children"].items():
self.show_col(2, d)
if type(y) is dict:
for e, f in d["children"].items():
self.show_col(3, f)
# print("show Dat :", x, y)
return self.data
def import_data(self):
if type(self.json) is str:
print("string miş")
self.json = json.loads(self.json)
for item, value in self.json.items():
if type(value) is list:
for x in range(len(value)):
print(f"t:{type(value[x])} : {value[x]}")
if type(value[x]) is list:
print("list", x)
if type(value[x]) is dict:
print(
value[x]["app_name"],
value[x]["app_description"],
value[x]["app_path"],
value[x]["uu_id"],
value[x]["app_parent_items_id"],
[],
value[x]["only_menu_item"],
value[x]["item_order"],
value[x]["layer"],
value[x]["after_separator"],
value[x]["row_limit"],
value[x]["read"],
value[x]["write"],
value[x]["delete"],
value[x]["report_print"],
value[x]["report_export"],
value[x]["program_name"],
)
self.add_item(
value[x]["only_menu_item"],
value[x]["item_order"],
value[x]["layer"],
value[x]["app_name"],
value[x]["app_description"],
value[x]["app_path"],
value[x]["uu_id"],
value[x]["app_parent_items_id"],
value[x]["after_separator"],
value[x]["row_limit"],
value[x]["read"],
value[x]["write"],
value[x]["delete"],
value[x]["report_print"],
value[x]["report_export"],
value[x]["program_name"],
)
# self.add_item(value[x]["app_name"], app_description, app_path, uu_id, app_parent_items_id):
# self.app_name = app_name
# for child in item.children:
# print(f" - {child.app_name}")
(0, [1, 3, 5])
(1, [2])
(3, [4])
(5, [6])
(4, [7])
menu = Menu(json.loads(data))
print("*" * 100)
menu.show_data()

View File

@ -0,0 +1,93 @@
import glob
import os
import shutil
import time
import pandas
import datetime
from services.email.service import send_email
from logging import getLogger, basicConfig, INFO
# from company_budget_records import insert_budget_record
logger = getLogger(__name__)
basicConfig(filename=__name__, level=INFO)
def parse_xl_files_and_copy_to_database():
completed = "bank_excels/completed"
incoming = "bank_excels/incoming"
pandas.set_option("display.max_columns", None)
pandas.set_option("display.width", 1200)
current_directory = os.getcwd()
# current_directory = "/home/berkay/git-evyos/wag-management-api"
absolute_path = os.path.join(current_directory, incoming)
excel_files = glob.glob(os.path.join(absolute_path, "*.xls*"))
for file_path in excel_files:
xl_file = pandas.read_excel(file_path)
xl_frame = pandas.DataFrame(xl_file)
iban = ""
for row in xl_frame.itertuples():
if "IBAN" in str(row[3]).upper():
iban = str(row[5]).replace(" ", "")
if not str(row[1]) == "nan" and not str(row[2]) == "nan":
if len(str(row[1]).split("/")) > 2:
insert_dict = dict(
iban=str(iban),
bank_date=datetime.datetime.strptime(
str(row[1]), "%d/%m/%Y-%H:%M:%S"
).__str__(),
channel_branch=str(row[3]),
currency_value=(
float(str(row[4]).replace(",", "")) if row[4] else 0
),
balance=float(str(row[5]).replace(",", "")) if row[5] else 0,
additional_balance=(
float(str(row[6]).replace(",", "")) if row[6] else 0
),
process_name=str(row[7]),
process_type=str(row[8]),
process_comment=str(row[9]),
bank_reference_code=str(row[15]),
)
logger.info(f"Insert Dict: {insert_dict}")
print(f"Insert Dict: {insert_dict}")
# find_or_create, found = EdmBudgetRecords.find_or_create(**insert_dict)
# find_or_create, found = insert_budget_record(insert_dict)
find_or_create, found = None, None
if found:
send_html = f"""
<br/>
<h1>Bank Excel File</h1>
<p>Bank Excel File is processed</p>
<br/>
<h3>{str(find_or_create.bank_date)}</h3>
<h3>{str(find_or_create.process_comment)}</h3>
<h3>{str(find_or_create.currency_value)}</h3>
<p>Thank you</p>
<p>Wag Management</p>
<p>Sincere Regards</p>
"""
try:
send_email(
subject="Bank Excel File",
receivers=["mehmet.karatay@hotmail.com"],
html=send_html,
)
except Exception as e:
print(f"Error: {e}")
finally:
print("Email is sent")
shutil.move(
file_path,
os.path.join(current_directory, completed, os.path.basename(file_path)),
)
if __name__ == "__main__":
while True:
parse_xl_files_and_copy_to_database()
time.sleep(int(os.getenv("PARSER_SEQUENCE", 60)))

View File

@ -0,0 +1,27 @@
Add via[Field] to @ login_via_credentials
Check is_occupant is True or False @ login_via_credentials
Add middleware @endpoint-controller to @ Event.Controller
If Events2Occupants and Events2Employees are not found for user request, response 401 Unauthorized
Also check user priority before Events2Occupants and Events2Employees
/home/berkay/evyos-apis/wag_api_service/shared_functions
Add default http errors status and message over Config Class
Change login and token object with occupant and employee
Add middleware to check user priority
Event rendering function must check with
Module -> Event
For each event add step and required previous step
Redis Cache TOKEN(encrypted) + UUID(encrypted) = Object (encrypted)
Occupant {
people_id,
occupant_id
}
Employee {
priority_id (Nullable | User),
*duty_id
}

View File

@ -0,0 +1,23 @@
{
"login_sup":
{
"domain": "evyos.com.tr",
"access_key": "karatay.berkay.sup@evyos.com.tr",
"password": "string",
"remember_me": false
},
"login_occupant":
{
"domain": "evyos.com.tr",
"access_key": "gdemirel@example.com",
"password": "string",
"remember_me": false
},
"select_sup": {
"company_uu_id": "0c8b808c-0f3b-4030-a2e7-681ed4478b97"
},
"select_occupant": {
"occupant_uu_id": "16dc4457-4c71-4a87-bd7a-53e87f6657d5",
"build_part_uu_id": "295de6a4-e5ba-4f3a-b5c0-02dff0578dc2"
}
}

View File

@ -0,0 +1,34 @@
{
"build":
{
"gov_address_code": "123456",
"build_name": "Beaver Build",
"build_no": "56",
"build_types": "A",
"max_floor": 12,
"underground_floor": 1,
"build_date": "01.01.2021",
"tax_no": "1234567890",
"lift_count": 0,
"heating_system": true,
"cooling_system": false,
"hot_water_system": false,
"block_service_man_count": 0,
"security_service_man_count": 0,
"garage_count": 2
},
"build_part":
{
"build_uu_id": "19d53a0c-1fa8-4011-8c91-75c05d357838",
"address_gov_code": "132456789101112",
"part_no": 1,
"part_level": 0,
"build_part_type_uu_id": "8eeeedd2-82b2-46d2-8611-4ea3d31dc122",
"part_code": 1,
"part_gross_size": 90,
"part_net_size": 90,
"human_livable": true,
"part_direction": "9fcbc4fa-245e-42a4-b4e2-6e2eb3222d3d",
"current_owner_person_uu_id": "bd96727c-2732-4432-98f3-516c403b0f6d"
}
}

View File

@ -0,0 +1,31 @@
{
"create_companies" :[
{
"formal_name": "Evyos Ankara Bölge Müdürlüğü",
"company_type": "Commercial",
"commercial_type": "Branch",
"public_name": "Evyos Ankara Bölge Müdürlüğü",
"company_tag": "Ankara Bölge Müdürlüğü",
"default_lang_type": "TR",
"default_money_type": "TL"
},
{
"formal_name": "Evyos İzmir Bölge Müdürlüğü",
"company_type": "Commercial",
"commercial_type": "Branch",
"public_name": "Evyos İzmir Bölge Müdürlüğü",
"company_tag": "İzmir Bölge Müdürlüğü",
"default_lang_type": "TR",
"default_money_type": "TL"
},
{
"formal_name": "Evyos İstanbul Bölge Müdürlüğü",
"company_type": "Commercial",
"commercial_type": "Branch",
"public_name": "Evyos İstanbul Bölge Müdürlüğü",
"company_tag": "İstanbul Bölge Müdürlüğü",
"default_lang_type": "TR",
"default_money_type": "TL"
}
]
}

View File

@ -0,0 +1,63 @@
{
"decision_book":
{
"build_uu_id": "19d53a0c-1fa8-4011-8c91-75c05d357838",
"period_start_date": "2024-07-01",
"period_stop_date": "2025-06-30",
"decision_type": "DMB",
"meeting_date": "2024-06-26 21:44:20.749 +0300",
"is_out_sourced": false
},
"decision_book_item":[
{
"item_order": 1,
"item_comment": "Geçen yıla ait toplantıda 2nolu gündemde bahsedilen kanalizasyon için her bir kanalizasyon çıkışı için fiyat alınarak proje açılacaktır. Arka alana yağmur suyu drenajın yaptırılması.",
"build_decision_book_uu_id": "6a8e5ac9-97ea-43c8-8f7a-d6dffde551e6"
},
{
"item_order": 2,
"item_comment": "Aidat gündemi içim 1-2-3nolu daireler için 1.400 TL. diğer daireler için 1.500 TL. olarak apartman hesabına ödeme yapılmasına.",
"build_decision_book_uu_id": "6a8e5ac9-97ea-43c8-8f7a-d6dffde551e6"
},
{
"item_order": 3,
"item_comment": "Hali hazırda yöneticilik görevini ifa eden Mehmet Karatayın görevine devam etmesine.",
"build_decision_book_uu_id": "6a8e5ac9-97ea-43c8-8f7a-d6dffde551e6"
},
{
"item_order": 4,
"item_comment": "Kirişin içinden geçen kalorifer borusunun çıkarılmadan kesilmesine ve gerekli tadilatın yapılıp problemin çözülmesine ve bu arada ayrıca her dairenin kalorifer borularında su olmadığı için gerekli her radyatörlerinin temizliğini kendisinin yaptırmasına.",
"build_decision_book_uu_id": "6a8e5ac9-97ea-43c8-8f7a-d6dffde551e6"
},
{
"item_order": 5,
"item_comment": "Doğalgaz tadilatından çıkan hurda boruların hurdacı tarafından gelip alınarak satışının yapılmasına.",
"build_decision_book_uu_id": "6a8e5ac9-97ea-43c8-8f7a-d6dffde551e6"
},
{
"item_order": 6,
"item_comment": "Apartman içinin tadilatının yapılmasın, ışıkların ve elektrik sisteminin elden geçirilmesi ve elektrik sayaçlarının panolara konulmasına ve yeni yapılan doğalgaz boruların pasa karşı astar boya ile ve sarı renkle boyanmasına.",
"build_decision_book_uu_id": "6a8e5ac9-97ea-43c8-8f7a-d6dffde551e6"
},
{
"item_order": 7,
"item_comment": "İç kapı teklifi alınarak gerekli tadilatın gerçekleştirilmesi için çalışma yapılması, ek kapı veya tek kapı seçenekleri değerlendirilerek fiyat alınmasına,",
"build_decision_book_uu_id": "6a8e5ac9-97ea-43c8-8f7a-d6dffde551e6"
},
{
"item_order": 8,
"item_comment": "Binanın su depo temizliğinin yapılmasına.",
"build_decision_book_uu_id": "6a8e5ac9-97ea-43c8-8f7a-d6dffde551e6"
},
{
"item_order": 9,
"item_comment": "Çatı havalandırma camlarından çatlamış olanların değiştirilmesine.",
"build_decision_book_uu_id": "6a8e5ac9-97ea-43c8-8f7a-d6dffde551e6"
},
{
"item_order": 10,
"item_comment": "Arka zemin dairenin yoğun yağışlarda evini su basmasından korunmak amacı ile saçak yapılmasına karar verilmiştir.",
"build_decision_book_uu_id": "6a8e5ac9-97ea-43c8-8f7a-d6dffde551e6"
}
]
}

View File

@ -0,0 +1,7 @@
{
"decision_book_item_debit":
{
"build_decision_book_item_uu_id": "855c1b77-f00e-4bc2-b3d1-42fc28ea2cb8",
"dues_values": {"NET_80": 1400, "NET_88": 1500}
}
}

View File

@ -0,0 +1,29 @@
{
"decision_books_project":
{
"build_decision_book_item_uu_id": "11b9dafa-8d7f-4b8f-8dad-3f8dbecaab98",
"project_response_person_uu_id": "7be73c91-ec57-46e0-99fa-95fa038c5f8d",
"project_name": "Depo Temizliği",
"project_start_date": "2024-06-01",
"project_stop_date": "2024-08-01",
"project_type": "TDL",
"is_out_sourced": false,
"project_note": "Sertifika alınacak",
"meeting_date": "2024-06-10"
},
"decision_book_item":
{
"item_order": 1,
"item_comment": "2,5 saat sürecek iş için 1000 TL fiyat istendi. 2 taksit ile ödenecek",
"build_decision_book_project_uu_id": "4a6bfdac-57d0-4876-8344-ae3f56c3b6d6"
},
"decision_book_item_debit" :
{
"build_decision_book_project_item_uu_id": "b862122a-2ef7-4a0d-b2e9-e2242b228b1f",
"payment_date": "2024-06-04",
"dues_values": {"NET_80": 1400, "NET_88": 1500}
}
}

View File

@ -0,0 +1,111 @@
@classmethod
def select_action(cls, duty_id, filter_expr: list = None):
from application.base import AlchemyResponse
keys_list = list(cls.__table__.columns) + list(
RelationshipDutyUser.__table__.columns
)
keys = [str(_.table) + "*" + str(_.name) for _ in keys_list]
data_list = []
if filter_expr is not None:
filter_expr = (RelationshipDutyUser.duty_id == duty_id, *filter_expr)
data = (
cls.session.query(
*cls.__table__.columns, *RelationshipDutyUser.__table__.columns
)
.select_from(cls)
.join(RelationshipDutyUser, RelationshipDutyUser.member_id == cls.id)
.filter(*filter_expr)
)
return AlchemyResponse(
query=data, data=data_list if data_list else data.all(), count=data.count()
)
data = (
cls.session.query(
*cls.__table__.columns, *RelationshipDutyUser.__table__.columns
)
.select_from(cls)
.join(RelationshipDutyUser, RelationshipDutyUser.member_id == cls.id)
.filter(RelationshipDutyUser.duty_id == duty_id)
)
for _ in data.all():
temp_dict = {}
for ix, item in enumerate(_):
table, key = str(keys[ix]).split("*")[0], str(keys[ix]).split("*")[1]
if table in temp_dict:
temp_dict[table][key] = item
else:
temp_dict[table] = {}
temp_dict[table][key] = item
data_list.append(temp_dict)
return AlchemyResponse(
query=data, data=data_list if data_list else data.all(), count=data.count()
)
def create_filter_with_options(model, options: ListOptions, duty_id):
from application.base import AlchemyResponse
if options.query:
model.query_filter = options.query
model.filter_attr = options
if hasattr(model, "select_action"):
list_of_model_records = model.select_action(duty_id=duty_id)
else:
list_of_model_records = model.filter_by_non_deleted()
if hasattr(list_of_model_records.data, "get_dict"):
if not list_of_model_records.count:
return AlchemyResponse(
query=list_of_model_records.query,
count=list_of_model_records.count,
data=[],
)
return AlchemyResponse(
query=list_of_model_records.query,
count=list_of_model_records.count,
data=[_.get_dict() for _ in list_of_model_records.data],
)
if not list_of_model_records.count:
return AlchemyResponse(
query=list_of_model_records.query,
count=list_of_model_records.count,
data=[],
)
return AlchemyResponse(
query=list_of_model_records.query,
count=list_of_model_records.count,
data=model.joined_to_dict(list_of_model_records.data),
)
@classmethod
def joined_to_dict(cls, joined_list: list):
exclude = list(cls.__exclude__fields__) + [
"is_confirmed",
"deleted",
"replication_id",
"id",
]
serialized_list = []
new_dict = {}
for joined_dict_list in joined_list:
for joined_dict in joined_dict_list:
return_dict = {}
for key, val in joined_dict_list[joined_dict].items():
if key not in exclude and "_id" not in key:
if val is None:
return_dict[key] = None
elif key == "active":
return_dict[key] = bool(val)
elif isinstance(val, int) or isinstance(val, float):
return_dict[key] = float(val)
elif isinstance(val, bool):
return_dict[key] = bool(val)
else:
return_dict[key] = str(val)
if key == "uu_id":
return_dict["uu_id"] = str(val)
new_dict[joined_dict] = return_dict
serialized_list.append(new_dict)
return serialized_list

27
api_configs/__init__.py Normal file
View File

@ -0,0 +1,27 @@
from api_configs.configs import (
Config,
ApiStatic,
Auth,
WagDatabase,
WagRedis,
TestRedis,
HagRedis,
MongoConfig,
TestMongo,
RelationAccess,
EmailConfig,
)
__all__ = [
"Config",
"ApiStatic",
"Auth",
"WagDatabase",
"WagRedis",
"TestRedis",
"HagRedis",
"MongoConfig",
"TestMongo",
"RelationAccess",
"EmailConfig",
]

154
api_configs/configs.py Normal file
View File

@ -0,0 +1,154 @@
import datetime
class Config:
INSECURE_PATHS = [
"/",
"/metrics",
"/openapi.json",
"/openapi.json_files",
"/docs",
"/redoc",
"/auth/login",
"/favicon.ico",
"/internal/isbank/retreive",
"/docs/oauth2-redirect",
"/hardware/auth/receive/hardware/token",
"/hardware/auth/hardware/greetings",
"/test/create/test/staff",
"/test/create/test/gateway",
"/test/create/test/company",
"/infos/current_date",
"/authentication/login",
"/authentication/logout",
"/authentication/refresher",
"/authentication/refresh",
"/authentication/disconnect",
"/authentication/create_password",
"/authentication/change_password",
"/authentication/forgot",
"/authentication/avatar",
"/api/Contact/Us/current_date",
]
APP_NAME = "evyos-web-api-gateway"
TITLE = "WAG API Web Api Gateway"
DESCRIPTION = "This api is serves as web api gateway only to evyos web services."
APP_URL = "https://www.wag.eys.gen.tr"
class ApiStatic:
PLACEHOLDER = "https://s.tmimgcdn.com/scr/800x500/276800/building-home-nature-logo-vector-template-3_276851-original.jpg"
FORGOT_LINK = "https://www.evyos.com.tr/auth/create-password/"
BLACKLIST_LINK = "https://www.evyos.com.tr/support/unknown-login-notice/"
APP_DIR = "/home/berkay/git-evyos/api-managment-backend/"
@classmethod
def forgot_link(cls, forgot_key):
return cls.FORGOT_LINK + forgot_key
@classmethod
def blacklist_login(cls, record_id):
return cls.BLACKLIST_LINK + record_id
class Auth:
ACCESS_EMAIL_EXT = "evyos.com.tr"
ACCESS_TOKEN_TAG = "evyos-session-key"
REFRESHER_TOKEN_TAG = "eys_token_refresher"
SECRET_KEY_72 = (
"t3sUAmjTGeTgDc6dAUrB41u2SNg0ZHzj4HTjem95y3fRH1nZXOHIBj163kib6iLybT0gLaxq"
)
SECRET_KEY_96 = "7ct8VpiwaP1hR2bVSet4dEEAgepuTZUOnO1QxOgKyDqBR2PkqNhcubSrbUUigQKoQA1PBoeeQn5ZCo24pESmVtKs76nA4EKq"
SECRET_KEY_144 = (
"R2p5Rq6KCr6PCfjFYUeH1keF2VWHFEuqINVjBGGnvRA2m10pYUKqfOtIGBcaj2v5wZmElDndzSHGOS7roQsoTelPSok0"
+ "qqMucurMWE0FGexGpFuJkfPEm9tH2OjMOqegvEetpSVywH0W4Kh4"
)
ALGORITHM = "HS256"
ACCESS_TOKEN_LENGTH: int = 90
REFRESHER_TOKEN_LENGTH: int = 144
PASSWORD_EXPIRE_DAY = datetime.timedelta(days=30)
TOKEN_EXPIRE_MINUTES_1 = datetime.timedelta(minutes=1)
TOKEN_EXPIRE_MINUTES_15 = datetime.timedelta(minutes=15)
TOKEN_EXPIRE_MINUTES_30 = datetime.timedelta(minutes=30)
TOKEN_EXPIRE_DAY_1 = datetime.timedelta(days=1)
TOKEN_EXPIRE_DAY_5 = datetime.timedelta(days=5)
TOKEN_EXPIRE_DAY_15 = datetime.timedelta(days=15)
TOKEN_EXPIRE_DAY_30 = datetime.timedelta(days=30)
class WagDatabase:
SQL: str = "postgresql+psycopg2"
USERNAME: str = "berkay_wag_user"
PASSWORD: str = "berkay_wag_user_password"
HOST: str = "postgres_commercial"
PORT = "5432"
# HOST: str = "127.0.0.1"
# PORT: str = "5434"
DATABASE_NAME: str = "wag_database"
DATABASE_URL = f"{SQL}://{USERNAME}:{PASSWORD}@{HOST}:{PORT}/{DATABASE_NAME}"
class HagRedis:
REDIS_HOST: str = "hardware_token_service"
REDIS_PASSWORD: str = "hardware_redis_password"
REDIS_PORT: int = 6379
REDIS_DB: int = 0
class WagRedis:
# REDIS_HOST: str = "10.10.2.44"
# REDIS_PORT: int = 11112
REDIS_HOST = "commercial_memory_service"
REDIS_PASSWORD: str = "commercial_redis_password"
REDIS_PORT: int = 6379
REDIS_DB: int = 0
class TestRedis:
REDIS_HOST: str = "localhost"
REDIS_PASSWORD: str = "commercial_redis_password"
REDIS_PORT: int = 11112
REDIS_DB: int = 0
class TestDatabase:
SQL: str = "postgresql+psycopg2"
USERNAME: str = "berkay_wag_user"
PASSWORD: str = "berkay_wag_user_password"
HOST: str = "10.10.2.44"
PORT: str = "5434"
DATABASE_NAME: str = "wag_database"
DATABASE_URL = f"{SQL}://{USERNAME}:{PASSWORD}@{HOST}:{PORT}/{DATABASE_NAME}"
class MongoConfig:
password = "mongo_password"
username = "mongo_user"
database_name = "mongo_database"
# host = "10.10.2.44"
# port = 11122
host = "commercial_mongo_service"
port = 27017
url = f"mongodb://{username}:{password}@{host}:{port}/{database_name}?retryWrites=true&w=majority"
class TestMongo:
password = "mongo_password"
username = "mongo_user"
database_name = "mongo_database"
host = "localhost"
port = 11110
url = f"mongodb://{username}:{password}@{host}:{port}/{database_name}?retryWrites=true&w=majority"
class EmailConfig:
EMAIL_HOST: str = "10.10.2.34"
EMAIL_USERNAME: str = "karatay@mehmetkaratay.com.tr"
EMAIL_PASSWORD: str = "system"
class RelationAccess:
# 77 Evyos superuser of Superuser - 78 all company superuser - 98 Manager of 77 & 78
SuperAccessList = ["77", "78", "98"]

0
api_events/__init__.py Normal file
View File

View File

@ -0,0 +1,218 @@
from api_events.events.identity.people import (
PeopleListEventMethod,
PeopleCreateEventMethod,
PeopleDeleteEventMethod,
PeopleUpdateEventMethod,
PeoplePatchEventMethod,
)
from api_events.events.address.address import (
AddressListEventMethod,
AddressCreateEventMethod,
AddressUpdateEventMethod,
AddressPatchEventMethod,
AddressSearchEventMethod,
AddressPostCodeCreateEventMethod,
AddressPostCodeUpdateEventMethod,
AddressPostCodeListEventMethod,
)
from api_events.events.authentication import (
AuthenticationLoginEventMethod,
AuthenticationSelectEventMethod,
AuthenticationCheckTokenEventMethod,
AuthenticationRefreshEventMethod,
AuthenticationChangePasswordEventMethod,
AuthenticationCreatePasswordEventMethod,
AuthenticationDisconnectUserEventMethod,
AuthenticationLogoutEventMethod,
AuthenticationRefreshTokenEventMethod,
AuthenticationForgotPasswordEventMethod,
AuthenticationDownloadAvatarEventMethod,
)
from api_events.events.identity.users import (
UserListEventMethod,
UserCreateEventMethod,
UserUpdateEventMethod,
UserPatchEventMethod,
)
from api_events.events.building.building_build import (
BuildListEventMethod,
BuildCreateEventMethod,
BuildUpdateEventMethod,
BuildPatchEventMethod,
)
from api_events.events.building.building_build_parts import (
BuildingBuildPartsListEventMethod,
BuildingBuildPartsCreateEventMethod,
BuildingBuildPartsUpdateEventMethod,
BuildingBuildPartsPatchEventMethod,
)
from api_events.events.company.company_company import (
CompanyListEventMethod,
CompanyCreateEventMethod,
CompanyUpdateEventMethod,
CompanyPatchEventMethod,
)
from api_events.events.company.company_department import (
DepartmentListEventMethod,
DepartmentCreateEventMethod,
DepartmentUpdateEventMethod,
DepartmentPatchEventMethod,
)
from api_events.events.company.company_duties import (
DutiesListEventMethod,
DutiesGetByUUIDEventMethod,
DutiesCreateEventMethod,
DutiesUpdateEventMethod,
DutiesPatchEventMethod,
)
from api_events.events.company.company_duty import (
DutyListEventMethod,
DutyCreateEventMethod,
DutyUpdateEventMethod,
DutyPatchEventMethod,
)
from api_events.events.company.company_employee import (
EmployeeListEventMethod,
EmployeeCreateEventMethod,
EmployeeUpdateEventMethod,
EmployeePatchEventMethod,
Employee2PeopleEmployEventMethod,
Employee2PeopleFireEventMethod,
)
from api_events.events.company.company_staff import (
StaffListEventMethod,
StaffCreateEventMethod,
StaffGetByUUIDEventMethod,
StaffUpdateEventMethod,
StaffPatchEventMethod,
)
from api_events.events.building.building_living_spaces import (
BuildingLivingSpacesPartsListEventMethod,
BuildingLivingSpacesPartsCreateEventMethod,
BuildingLivingSpacesPartsUpdateEventMethod,
)
from api_events.events.decision_book.decision_book_decision_book import (
DecisionBookListEventMethod,
DecisionBookCreateEventMethod,
DecisionBookUpdateEventMethod,
DecisionBookPatchEventMethod,
DecisionBookApprovalEventMethod,
)
from api_events.events.decision_book.decision_book_decision_book_items import (
DecisionBookDecisionBookItemsListEventMethod,
DecisionBookDecisionBookItemsCreateEventMethod,
DecisionBookDecisionBookItemsUpdateEventMethod,
DecisionBookDecisionBookItemsPatchEventMethod,
)
from api_events.events.events.events_bind_events import (
EventBindOccupantEventMethod,
EventBindEmployeeEventMethod,
)
from api_events.events.events.events_bind_services import (
ServiceBindOccupantEventMethod,
ServiceBindEmployeeEventMethod,
)
from api_events.events.decision_book.decision_book_decision_book_person import (
DecisionBookPersonListEventMethod,
DecisionBookPersonAddEventMethod,
DecisionBookPersonRemoveEventMethod,
DecisionBookPersonAttendEventMethod,
DecisionBookPersonAssignOccupantEventMethod,
)
from api_events.events.decision_book.decision_book_invitations import (
BuildDecisionBookInvitationsListEventMethod,
BuildDecisionBookInvitationsCreateEventMethod,
BuildDecisionBookInvitationsUpdateEventMethod,
)
__all__ = [
"AddressListEventMethod",
"AddressCreateEventMethod",
"AddressUpdateEventMethod",
"AddressPatchEventMethod",
"AddressSearchEventMethod",
"AddressPostCodeCreateEventMethod",
"AddressPostCodeUpdateEventMethod",
"AddressPostCodeListEventMethod",
"PeopleListEventMethod",
"PeopleDeleteEventMethod",
"PeopleUpdateEventMethod",
"PeoplePatchEventMethod",
"PeopleCreateEventMethod",
"AuthenticationLoginEventMethod",
"AuthenticationSelectEventMethod",
"AuthenticationCheckTokenEventMethod",
"AuthenticationRefreshEventMethod",
"AuthenticationChangePasswordEventMethod",
"AuthenticationCreatePasswordEventMethod",
"AuthenticationDisconnectUserEventMethod",
"AuthenticationLogoutEventMethod",
"AuthenticationRefreshTokenEventMethod",
"AuthenticationForgotPasswordEventMethod",
"AuthenticationDownloadAvatarEventMethod",
"UserListEventMethod",
"UserCreateEventMethod",
"UserUpdateEventMethod",
"UserPatchEventMethod",
"BuildListEventMethod",
"BuildCreateEventMethod",
"BuildUpdateEventMethod",
"BuildPatchEventMethod",
"BuildingBuildPartsListEventMethod",
"BuildingBuildPartsCreateEventMethod",
"BuildingBuildPartsUpdateEventMethod",
"BuildingBuildPartsPatchEventMethod",
"BuildingLivingSpacesPartsListEventMethod",
"BuildingLivingSpacesPartsCreateEventMethod",
"BuildingLivingSpacesPartsUpdateEventMethod",
"DecisionBookListEventMethod",
"DecisionBookCreateEventMethod",
"DecisionBookUpdateEventMethod",
"DecisionBookPatchEventMethod",
"DecisionBookApprovalEventMethod",
"DecisionBookPersonListEventMethod",
"DecisionBookPersonAddEventMethod",
"DecisionBookPersonRemoveEventMethod",
"DecisionBookDecisionBookItemsListEventMethod",
"DecisionBookDecisionBookItemsCreateEventMethod",
"DecisionBookDecisionBookItemsUpdateEventMethod",
"DecisionBookDecisionBookItemsPatchEventMethod",
"CompanyPatchEventMethod",
"CompanyCreateEventMethod",
"CompanyUpdateEventMethod",
"CompanyListEventMethod",
"DepartmentListEventMethod",
"DepartmentCreateEventMethod",
"DepartmentUpdateEventMethod",
"DepartmentPatchEventMethod",
"DutiesListEventMethod",
"DutiesGetByUUIDEventMethod",
"DutiesCreateEventMethod",
"DutiesUpdateEventMethod",
"DutiesPatchEventMethod",
"DutyListEventMethod",
"DutyCreateEventMethod",
"DutyUpdateEventMethod",
"DutyPatchEventMethod",
"EmployeeListEventMethod",
"EmployeeCreateEventMethod",
"EmployeeUpdateEventMethod",
"EmployeePatchEventMethod",
"Employee2PeopleEmployEventMethod",
"Employee2PeopleFireEventMethod",
"StaffListEventMethod",
"StaffCreateEventMethod",
"StaffGetByUUIDEventMethod",
"StaffUpdateEventMethod",
"StaffPatchEventMethod",
"EventBindOccupantEventMethod",
"EventBindEmployeeEventMethod",
"ServiceBindOccupantEventMethod",
"ServiceBindEmployeeEventMethod",
"BuildDecisionBookInvitationsListEventMethod",
"BuildDecisionBookInvitationsCreateEventMethod",
"BuildDecisionBookInvitationsUpdateEventMethod",
"DecisionBookPersonAttendEventMethod",
"DecisionBookPersonAssignOccupantEventMethod",
]

View File

@ -0,0 +1,70 @@
import typing
from abc import ABC
from fastapi.exceptions import HTTPException
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
class ActionsSchema(ABC):
def __init__(self, endpoint: str = None):
self.endpoint = endpoint
def retrieve_action_from_endpoint(self):
from databases import EndpointRestriction
endpoint_restriction = EndpointRestriction.filter_all(
EndpointRestriction.endpoint_name.ilike(f"%{self.endpoint}%")
).get(1)
if not endpoint_restriction:
raise HTTPException(
status_code=404,
detail=f"Endpoint {self.endpoint} not found in the database",
)
return endpoint_restriction
class ActionsSchemaFactory:
def __init__(self, action: ActionsSchema):
self.action = action
try:
self.action_match = self.action.retrieve_action_from_endpoint()
except Exception as e:
err = e
self.action_match = None
class MethodToEvent(ABC, ActionsSchemaFactory):
event_type: str = None
event_description: str = ""
event_category: str = ""
__event_keys__: dict = {}
@classmethod
def call_event_method(cls, method_uu_id: str, *args, **kwargs):
function_name = cls.__event_keys__.get(method_uu_id)
return getattr(cls, function_name)(*args, **kwargs)
@classmethod
def ban_token_objects(
cls,
token: typing.Union[EmployeeTokenObject, OccupantTokenObject],
ban_list: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
from fastapi import status
from fastapi.exceptions import HTTPException
if token.user_type == ban_list.user_type:
if isinstance(token, EmployeeTokenObject):
raise HTTPException(
status_code=status.HTTP_406_NOT_ACCEPTABLE,
detail="No employee can reach this event. An notification is send to admin about event registration",
)
if isinstance(token, OccupantTokenObject):
raise HTTPException(
status_code=status.HTTP_406_NOT_ACCEPTABLE,
detail="No occupant can reach this event. An notification is send to admin about event registration",
)

View File

View File

@ -0,0 +1,4 @@
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
class ApiEvents(MethodToEvent): ...

View File

View File

@ -0,0 +1,372 @@
from fastapi.exceptions import HTTPException
from fastapi.responses import JSONResponse
from databases import (
AddressPostcode,
Addresses,
RelationshipEmployee2PostCode,
AddressStreet,
)
from api_validations.validations_request import (
ListOptions,
InsertAddress,
InsertPostCode,
SearchAddress
)
from api_validations.core_response import return_json_response_from_alchemy
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
class AddressListEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"9c251d7d-da70-4d63-a72c-e69c26270442": "address_list_super_user", # 1
"52afe375-dd95-4f4b-aaa2-4ec61bc6de52": "address_list_employee",
}
@classmethod
def address_list_super_user(cls, list_options: ListOptions, token_dict):
from sqlalchemy import select
post_code_list = RelationshipEmployee2PostCode.filter_active(
RelationshipEmployee2PostCode.company_id
== token_dict.selected_company.company_id,
).data
post_code_id_list = [post_code.member_id for post_code in post_code_list]
if not post_code_id_list:
raise HTTPException(
status_code=404,
detail="User has no post code registered. User can not list addresses.",
)
get_street_ids = AddressPostcode.session.execute(
select(AddressPostcode.street_id).where(
AddressPostcode.id.in_(post_code_id_list)
)
).all()
Addresses.pre_query = Addresses.filter_active(
Addresses.street_id.in_(*get_street_ids) if get_street_ids else None
).query
Addresses.filter_attr = list_options
records = Addresses.filter_active(
*Addresses.get_smart_query(list_options.query)
)
return return_json_response_from_alchemy(
response=records, pagination=list_options
)
@classmethod
def address_list_employee(cls, list_options: ListOptions, token_dict):
Addresses.filter_attr = list_options
records = Addresses.list_via_employee(
token_dict=token_dict,
filter_expr=Addresses.get_smart_query(list_options.query),
)
return return_json_response_from_alchemy(
response=records, pagination=list_options
)
class AddressCreateEventMethods(MethodToEvent):
event_type = "CREATE"
__event_keys__ = {
"ffdc445f-da10-4ce4-9531-d2bdb9a198ae": "create_address",
}
@classmethod
def create_address(cls, data: InsertAddress, token_dict):
post_code = AddressPostcode.find_one(uu_id=data.post_code_uu_id)
if not post_code:
raise HTTPException(
status_code=404,
detail="Post code not found. User can not create address without post code.",
)
data_dict = data.excluded_dump()
data_dict["street_id"] = post_code.street_id
del data_dict["post_code_uu_id"]
address = Addresses.find_or_create(**data_dict)
if not address.is_found:
RelationshipEmployee2PostCode.find_or_create(
employee_id=token_dict.selected_company.employee_id,
member_id=post_code.id,
company_id=token_dict.selected_company.company_id,
is_confirmed=True,
)
return JSONResponse(
content={
"completed": True,
"message": "Create Address record",
"data": address.get_dict(),
},
status_code=200,
)
class AddressSearchEventMethods(MethodToEvent):
event_type = "SEARCH"
__event_keys__ = {
"e0ac1269-e9a7-4806-9962-219ac224b0d0": "search_address",
}
@classmethod
def search_address(cls, data: SearchAddress, token_dict):
import database_sql_models
from time import perf_counter
st = perf_counter()
pre_query_first = AddressStreet.search_address_text(search_text=data.search)
query, schemas, new_data_list = (
pre_query_first.get("query"),
pre_query_first.get("schema"),
[],
)
filter_list = data.list_options.dump()
filter_table = AddressStreet
if filter_list.get("order_field") not in schemas:
filter_list["order_field"] = "uu_id"
else:
filter_table = getattr(
database_sql_models, str(filter_list.get("order_field")).split(".")[0]
)
filter_list["order_field"] = str(filter_list.get("order_field")).split(".")[
1
]
order = (
getattr(filter_table, filter_list.get("order_field")).desc()
if str(filter_list.get("order_type"))[0] == "d"
else getattr(filter_table, filter_list.get("order_field")).asc()
)
query = (
query.order_by(order)
.limit(int(filter_list.get("size")))
.offset(int((filter_list.get("page")) - 1) * int(filter_list.get("size")))
.populate_existing()
)
records = list(query.all())
print(perf_counter() - st)
for item in records:
new_data_dict = {}
for index, schema in enumerate(schemas):
new_data_dict[schema] = str(item[index])
if "uu_id" in str(item[index]):
new_data_dict[schema] = str(new_data_dict.get(schema))
new_data_list.append(new_data_dict)
return JSONResponse(
content={
"completed": True,
"pagination": filter_list,
"count": len(new_data_list),
"data": new_data_list,
"message": "Search Address records",
},
status_code=200,
)
class AddressUpdateEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"1f9c3a9c-e5bd-4dcd-9b9a-3742d7e03a27": "update_address",
}
@classmethod
def update_address(cls, address_uu_id: str, data: InsertAddress, token_dict):
address = Addresses.find_one_or_abort(uu_id=address_uu_id)
post_code = RelationshipEmployee2PostCode.postcode.find_one(
member_id=address.post_code_id
)
if not post_code:
raise HTTPException(
status_code=404,
detail="Post code not found. User can not update address without post code.",
)
data_dict = data.excluded_dump()
data_dict["post_code_id"] = post_code.id
del data_dict["post_code_uu_id"]
updated_address = address.update(**data_dict)
return JSONResponse(
content={
"completed": True,
"message": "Update Address record",
"data": updated_address.get_dict(),
},
status_code=200,
)
class AddressPatchEventMethods(MethodToEvent):
event_type = "PATCH"
__event_keys__ = {
"b0e55a7e-af81-468c-b46c-a6b3a6b68d5d": "patch_address",
}
@classmethod
def patch_address(cls, address_uu_id: str, data: InsertAddress, token_dict):
address = Addresses.find_one_or_abort(uu_id=address_uu_id)
post_code = RelationshipEmployee2PostCode.postcode.find_one(
member_id=address.post_code_id
)
if not post_code:
raise HTTPException(
status_code=404,
detail="Post code not found. User can not patch address without post code.",
)
data_dict = data.excluded_dump()
data_dict["post_code_id"] = post_code.id
del data_dict["post_code_uu_id"]
patched_address = address.patch(**data_dict)
return JSONResponse(
content={
"completed": True,
"message": "Patch Address record",
"data": patched_address.get_dict(),
},
status_code=200,
)
class AddressPostCodeCreateEventMethods(MethodToEvent):
event_type = "CREATE"
__event_keys__ = {
"6f1406ac-577d-4f2c-8077-71fff2252c5f": "create_post_code_address",
}
@classmethod
def create_post_code_address(cls, data: InsertPostCode, token_dict):
data_dump = data.excluded_dump()
street = AddressStreet.find_one(uu_id=data.street_uu_id)
if not street:
raise HTTPException(
status_code=404,
detail="Street not found. User can not create post code without street.",
)
data_dump["street_id"] = street.id
data_dump["postcode"] = data.post_code
del data_dump["street_uu_id"], data_dump["post_code"]
post_code = AddressPostcode.find_or_create(**data_dump)
if not post_code.is_found:
AddressPostcode.__many__table__.find_or_create(
member_id=post_code.id,
employee_id=token_dict.selected_company.employee_id,
company_id=token_dict.selected_company.company_id,
is_confirmed=True,
)
return JSONResponse(
content={
"completed": True,
"message": "Create Post Code record",
"data": post_code.get_dict(),
},
status_code=200,
)
class AddressPostCodeUpdateEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"df18e489-a63c-477f-984c-aa52d30640ad": "update_post_code_address",
}
@classmethod
def update_post_code_address(
cls, post_code_uu_id: str, data: InsertPostCode, token_dict
):
post_code = AddressPostcode.find_one_or_abort(uu_id=post_code_uu_id)
street = AddressStreet.find_one(uu_id=data.street_uu_id)
if not street:
raise HTTPException(
status_code=404,
detail="Street not found. User can not update post code without street.",
)
updated_post_code = post_code.update(**data.excluded_dump())
return JSONResponse(
content={
"completed": True,
"message": "Update Post Code record",
"data": updated_post_code.get_dict(),
},
status_code=200,
)
class AddressPostCodeListEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"88d37b78-1ac4-4513-9d25-090ac3a24f31": "list_post_code_address",
}
@classmethod
def list_post_code_address(cls, list_options: ListOptions, token_dict):
post_code_list = AddressPostcode.__many__table__.filter_active(
AddressPostcode.__many__table__.company_id
== token_dict.selected_company.company_id
).data
if not post_code_list:
raise HTTPException(
status_code=404,
detail="User has no post code registered or not yet any post code created.",
)
AddressPostcode.pre_query = AddressPostcode.filter_active(
AddressPostcode.id.in_(
[post_code.member_id for post_code in post_code_list]
)
).query
AddressPostcode.filter_attr = list_options
records = AddressPostcode.filter_active(
*Addresses.get_smart_query(list_options.query)
)
return return_json_response_from_alchemy(
response=records, pagination=list_options
)
AddressListEventMethod = AddressListEventMethods(
action=ActionsSchema(endpoint="/address/list")
)
AddressCreateEventMethod = AddressCreateEventMethods(
action=ActionsSchema(endpoint="/address/create")
)
AddressUpdateEventMethod = AddressUpdateEventMethods(
action=ActionsSchema(endpoint="/address/update")
)
AddressPatchEventMethod = AddressPatchEventMethods(
action=ActionsSchema(endpoint="/address/patch")
)
AddressPostCodeCreateEventMethod = AddressPostCodeCreateEventMethods(
action=ActionsSchema(endpoint="/postcode/create")
)
AddressPostCodeUpdateEventMethod = AddressPostCodeUpdateEventMethods(
action=ActionsSchema(endpoint="/postcode/update")
)
AddressPostCodeListEventMethod = AddressPostCodeListEventMethods(
action=ActionsSchema(endpoint="/postcode/list")
)
AddressSearchEventMethod = AddressSearchEventMethods(
action=ActionsSchema(endpoint="/address/search")
)

View File

@ -0,0 +1,5 @@
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
class DecisionBookEvents(MethodToEvent): ...

View File

@ -0,0 +1,5 @@
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
class ApplicationEvents(MethodToEvent): ...

View File

@ -0,0 +1,682 @@
import json
import typing
from fastapi import status
from fastapi.requests import Request
from fastapi.exceptions import HTTPException
from fastapi.responses import JSONResponse
from databases import (
Companies,
Staff,
Duties,
Departments,
Employees,
BuildLivingSpace,
BuildParts,
Build,
RelationshipEmployee2PostCode,
Duty,
Event2Occupant,
Event2Employee,
Users,
UsersTokens,
OccupantTypes,
)
from api_services import (
redis_cli,
send_email,
get_object_via_access_key,
get_object_via_user_uu_id,
save_access_token_to_redis,
update_selected_to_redis,
password_is_changed_template,
change_your_password_template,
)
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from api_library.date_time_actions.date_functions import DateTimeLocal
from api_configs import ApiStatic, Auth
from databases.no_sql_models.login_handlers import load_user_with_erp_details
from api_validations.validations_request import (
Login,
Logout,
ChangePassword,
Remember,
Forgot,
CreatePassword,
OccupantSelection,
EmployeeSelection,
)
class AuthenticationLoginEventMethods(MethodToEvent):
event_type = "LOGIN"
__event_keys__ = {
"e672846d-cc45-4d97-85d5-6f96747fac67": "authentication_login_with_domain_and_creds",
}
@classmethod
def authentication_login_with_domain_and_creds(
cls,
data: Login,
request,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
access_dict = Users.login_user_with_credentials(data=data, request=request)
found_user = access_dict.get("user", None)
if not found_user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid credentials"
)
return JSONResponse(
content={
"completed": True,
"message": "User is logged in successfully",
"access_token": access_dict.get("access_token"),
"refresh_token": access_dict.get("refresher_token"),
"access_object": access_dict.get("access_object"),
"user": found_user.get_dict(),
},
status_code=status.HTTP_200_OK,
)
class AuthenticationSelectEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"cee96b9b-8487-4e9f-aaed-2e8c79687bf9": "authentication_select_company_or_occupant_type",
}
@classmethod
def authentication_select_company_or_occupant_type(
cls,
request: Request,
data: typing.Union[EmployeeSelection, OccupantSelection],
token_dict: dict = None,
):
from api_objects import OccupantToken, CompanyToken
token_user = get_object_via_access_key(request=request)
if token_user.user_type == 1:
if data.company_uu_id not in token_user.companies_uu_id_list:
return JSONResponse(
content={
"completed": False,
"message": "Company is not found in users company list",
},
status_code=status.HTTP_401_UNAUTHORIZED,
)
if selected_company := Companies.find_one(uu_id=data.company_uu_id):
department_ids = [
department.id
for department in Departments.filter_by_active(
company_id=selected_company.id
).data
]
duties_ids = [
duties.id
for duties in Duties.filter_active(
Duties.company_id == selected_company.id,
Duties.department_id.in_(department_ids),
).data
]
staff_ids = [
staff.id
for staff in Staff.filter_active(
Staff.duties_id.in_(duties_ids)
).data
]
employee = Employees.filter_active(
Employees.people_id == token_user.person_id,
Employees.staff_id.in_(staff_ids),
).data[0]
reachable_event_list_id, reachable_event_list_uu_id = (
Event2Employee.get_event_id_by_employee_id(employee_id=employee.id)
)
staff = Staff.find_one(id=employee.staff_id)
duties = Duties.find_one(id=staff.duties_id)
department = Departments.find_one(id=duties.department_id)
bulk_id = Duty.find_one(duty_code="BULK")
bulk_duty_id = Duties.find_one(
company_id=selected_company.id, duties_id=bulk_id.id
)
update_selected_to_redis(
request=request,
add_payload=CompanyToken(
company_uu_id=selected_company.uu_id.__str__(),
company_id=selected_company.id,
department_id=department.id,
department_uu_id=department.uu_id.__str__(),
duty_id=duties.id,
duty_uu_id=duties.uu_id.__str__(),
bulk_duties_id=bulk_duty_id.id,
staff_id=staff.id,
staff_uu_id=staff.uu_id.__str__(),
employee_id=employee.id,
employee_uu_id=employee.uu_id.__str__(),
reachable_event_list_id=reachable_event_list_id,
reachable_event_list_uu_id=reachable_event_list_uu_id,
),
)
return JSONResponse(
content={
"completed": True,
"message": "Company is selected successfully",
},
status_code=status.HTTP_200_OK,
)
elif token_user.user_type == 2:
occupant_type = OccupantTypes.find_one(uu_id=data.occupant_uu_id)
if not occupant_type:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Occupant Type is not found",
)
build_part = BuildParts.find_one(uu_id=data.build_part_uu_id)
if not build_part:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Build Part is not found",
)
build = Build.find_one(id=build_part.build_id)
related_company = RelationshipEmployee2Build.find_one(member_id=build.id)
company_related = Companies.find_one(id=related_company.company_id)
responsible_employee = Employees.find_one(id=related_company.employee_id)
if selected_occupant_type := BuildLivingSpace.find_one(
occupant_type=occupant_type.id,
person_id=token_user.person_id,
build_parts_id=build_part.id,
):
reachable_event_list_id, reachable_event_list_uu_id = (
Event2Occupant.get_event_id_by_build_living_space_id(
build_living_space_id=selected_occupant_type.id
)
)
update_selected_to_redis(
request=request,
add_payload=OccupantToken(
living_space_id=selected_occupant_type.id,
living_space_uu_id=selected_occupant_type.uu_id.__str__(),
occupant_type_id=occupant_type.id,
occupant_type_uu_id=occupant_type.uu_id.__str__(),
occupant_type=occupant_type.occupant_type,
build_id=build.id,
build_uuid=build.uu_id.__str__(),
build_part_id=build_part.id,
build_part_uuid=build_part.uu_id.__str__(),
responsible_employee_id=responsible_employee.id,
responsible_employee_uuid=responsible_employee.uu_id.__str__(),
responsible_company_id=company_related.id,
responsible_company_uuid=company_related.uu_id.__str__(),
reachable_event_list_id=reachable_event_list_id,
reachable_event_list_uu_id=reachable_event_list_uu_id,
),
)
return JSONResponse(
content={
"completed": True,
"message": "Occupant is selected successfully",
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={"completed": False, "message": "Invalid data provided"},
status_code=status.HTTP_418_IM_A_TEAPOT,
)
class AuthenticationCheckTokenEventMethods(MethodToEvent):
event_type = "CHECK"
__event_keys__ = {
"73d77e45-a33f-4f12-909e-3b56f00d8a12": "authentication_check_token_is_valid",
}
@classmethod
def authentication_login_with_domain_and_creds(
cls, request, token_dict: dict = None
):
if get_object_via_access_key(request=request):
return JSONResponse(
content={"completed": True, "message": "Access Token is valid"},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={"completed": False, "message": "Access Token is NOT valid"},
status_code=status.HTTP_401_UNAUTHORIZED,
)
class AuthenticationRefreshEventMethods(MethodToEvent):
event_type = "REFRESH"
__event_keys__ = {
"48379bb2-ba81-4d8e-a9dd-58837cfcbf67": "authentication_refresh_user_info",
}
@classmethod
def authentication_refresh_user_info(cls, request, token_dict: dict = None):
access_token = str(request.headers.get(Auth.ACCESS_TOKEN_TAG))
if token_user := get_object_via_access_key(request=request):
if found_user := Users.find_one(uu_id=token_user.get("uu_id")):
user_token = UsersTokens.find_one(
domain=found_user.domain_name,
user_id=found_user.id,
token_type="RememberMe",
)
access_dict = {
"access_token": access_token,
"refresh_token": getattr(user_token, "token", None),
}
return JSONResponse(
content={
"completed": True,
"message": "User is logged in successfully via refresh token",
"data": load_user_with_erp_details(found_user, access_dict),
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={"completed": False, "message": "Invalid data", "data": {}},
status_code=status.HTTP_401_UNAUTHORIZED,
)
class AuthenticationChangePasswordEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"f09f7c1a-bee6-4e32-8444-962ec8f39091": "authentication_change_password",
}
@classmethod
def authentication_change_password(
cls, request, data: ChangePassword, token_dict: dict = None
):
token_user = get_object_via_access_key(request=request)
if token_user.user_type == 1:
if found_user := Users.find_one(uu_id=token_user.uu_id):
if found_user.check_password(data.old_password):
found_user.set_password(data.new_password)
return JSONResponse(
content={
"completed": True,
"message": "Password is changed successfully",
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={
"completed": False,
"message": "Old password is not correct",
},
status_code=status.HTTP_401_UNAUTHORIZED,
)
return JSONResponse(
content={"completed": False, "message": "Invalid data"},
status_code=status.HTTP_401_UNAUTHORIZED,
)
class AuthenticationCreatePasswordEventMethods(MethodToEvent):
event_type = "CREATE"
__event_keys__ = {
"c519f9af-92e1-47b2-abf7-5a3316d075f7": "authentication_create_password",
}
@classmethod
def authentication_create_password(
cls, request, data: CreatePassword, token_dict: dict = None
):
if not data.re_password == data.password:
raise HTTPException(
status_code=status.HTTP_406_NOT_ACCEPTABLE, detail="Password must match"
)
if found_user := Users.find_one(password_token=data.password_token):
found_user.create_password(password=data.password)
found_user.password_token = None
found_user.save()
send_email_completed = send_email(
subject=f"Dear {found_user.user_tag}, your password has been changed.",
receivers=[str(found_user.email)],
html=password_is_changed_template(user_name=found_user.user_tag),
)
if not send_email_completed:
raise HTTPException(
status_code=400, detail="Email can not be sent. Try again later"
)
return JSONResponse(
content={
"completed": True,
"message": "Password is created successfully",
"data": found_user.get_dict(),
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={
"completed": False,
"message": "Record not found",
"data": {},
},
status_code=status.HTTP_202_ACCEPTED,
)
class AuthenticationDisconnectUserEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"8b586848-2fb3-4161-abbe-642157eec7ce": "authentication_disconnect_user",
}
@classmethod
def authentication_disconnect_user(
cls, request: Request, data: Logout, token_dict: dict = None
):
if token_user := get_object_via_access_key(request=request):
found_user = Users.find_one(uu_id=token_user.get("uu_id"))
if not found_user:
return JSONResponse(
content={
"completed": False,
"message": "Invalid data",
"data": None,
},
status_code=status.HTTP_202_ACCEPTED,
)
if already_tokens := get_object_via_user_uu_id(user_id=found_user.uu_id):
for key in already_tokens:
token_user = json.loads(redis_cli.get(key) or {})
redis_cli.delete(key)
selected_user = Users.find_one(uu_id=token_user.get("uu_id"))
selected_user.remove_refresher_token(
domain=data.domain, disconnect=True
)
# UserLogger.log_error(
# str(
# dict(
# user_id=found_user.id,
# domain=data.domain,
# access_key=token_user.get("access_input"),
# agent=request.headers.get("User-Agent", None),
# ip=getattr(request, "remote_addr", None)
# or request.headers.get("X-Forwarded-For", None),
# platform=request.headers.get("Origin", None),
# login_date=datetime.datetime.utcnow().__str__(),
# is_login=False,
# )
# )
# )
return JSONResponse(
content={
"completed": True,
"message": "All sessions are disconnected",
"data": token_user,
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={"completed": False, "message": "Invalid data", "data": None},
status_code=status.HTTP_202_ACCEPTED,
)
class AuthenticationLogoutEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"5cc22e4e-a0f7-4077-be41-1871feb3dfd1": "authentication_logout_user",
}
@classmethod
def authentication_logout_user(
cls, request: Request, data: Logout, token_dict: dict = None
):
token_user = None
if already_tokens := get_object_via_access_key(request=request):
for key in already_tokens:
token_user = json.loads(redis_cli.get(key) or {})
if token_user.get("domain") == data.domain:
redis_cli.delete(key)
selected_user = Users.find_one(uu_id=token_user.get("uu_id"))
selected_user.remove_refresher_token(domain=data.domain)
# UserLogger.log_error(
# str(
# dict(
# user_id=selected_user.id,
# domain=data.domain,
# access_key=token_user.get("access_input"),
# agent=request.headers.get("User-Agent", None),
# ip=getattr(request, "remote_addr", None)
# or request.headers.get("X-Forwarded-For", None),
# platform=request.headers.get("Origin", None),
# login_date=datetime.datetime.utcnow().__str__(),
# is_login=False,
# )
# )
# )
return JSONResponse(
content={
"completed": True,
"message": "Session is logged out",
"data": token_user,
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={
"completed": False,
"message": "Logout is not successfully completed",
"data": None,
},
status_code=status.HTTP_202_ACCEPTED,
)
class AuthenticationRefreshTokenEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"c90f3334-10c9-4181-b5ff-90d98a0287b2": "authentication_refresher_token",
}
@classmethod
def authentication_refresher_token(
cls, request: Request, data: Remember, token_dict: dict = None
):
token_refresher = UsersTokens.find_one(
token=data.refresh_token, domain=data.domain
)
if not token_refresher:
return JSONResponse(
content={"completed": False, "message": "Invalid data", "data": {}},
status_code=status.HTTP_202_ACCEPTED,
)
if found_user := Users.find_one(id=token_refresher.user_id):
found_user: Users = found_user
access_key = save_access_token_to_redis(
request=request, found_user=found_user, domain=data.domain
)
found_user.last_agent = request.headers.get("User-Agent", None)
found_user.last_platform = request.headers.get("Origin", None)
found_user.last_remote_addr = getattr(
request, "remote_addr", None
) or request.headers.get("X-Forwarded-For", None)
found_user.last_seen = str(DateTimeLocal.now())
# UserLogger.log_error(
# str(
# dict(
# user_id=found_user.id,
# domain=data.domain,
# access_key="via_refresher",
# agent=request.headers.get("User-Agent", None),
# ip=getattr(request, "remote_addr", None)
# or request.headers.get("X-Forwarded-For", None),
# platform=request.headers.get("Origin", None),
# login_date=datetime.datetime.utcnow().__str__(),
# is_login=False,
# )
# )
# )
return JSONResponse(
content={
"completed": True,
"message": "User is logged in successfully via refresher token",
"data": load_user_with_erp_details(
found_user,
{
"access_token": access_key,
"refresh_token": data.refresh_token,
},
),
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={"completed": False, "message": "Invalid data", "data": {}},
status_code=status.HTTP_202_ACCEPTED,
)
class AuthenticationForgotPasswordEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"e3ca6e24-b9f8-4127-949c-3bfa364e3513": "authentication_forgot_password",
}
@classmethod
def authentication_forgot_password(
cls, request: Request, data: Forgot, token_dict: dict = None
):
found_user: Users = Users.check_user_exits(
access_key=data.access_key, domain=data.domain
)
forgot_key = save_access_token_to_redis(
request=request, found_user=found_user, domain=data.domain
)
# UserLogger.log_error(
# str(
# dict(
# user_id=found_user.id,
# domain=data.domain,
# access_key=data.access_key,
# agent=request.headers.get("User-Agent", None),
# ip=getattr(request, "remote_addr", None)
# or request.headers.get("X-Forwarded-For", None),
# platform=request.headers.get("Origin", None),
# login_date=str(DateTimeLocal.now()),
# is_login=False,
# )
# )
# )
forgot_link = ApiStatic.forgot_link(forgot_key=forgot_key)
send_email_completed = send_email(
subject=f"Dear {found_user.user_tag}, your forgot password link has been sent.",
receivers=[str(found_user.email)],
html=change_your_password_template(
user_name=found_user.user_tag, forgot_link=forgot_link
),
)
if not send_email_completed:
raise HTTPException(
status_code=400, detail="Email can not be sent. Try again later"
)
found_user.password_token = forgot_key
found_user.password_token_is_valid = str(DateTimeLocal.shift(days=1))
found_user.save()
return JSONResponse(
content={
"completed": True,
"message": "Password is change link is sent to your email or phone",
"data": {},
},
status_code=status.HTTP_200_OK,
)
class AuthenticationDownloadAvatarEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"c140cd5f-307f-4046-a93e-3ade032a57a7": "authentication_download_avatar",
}
@classmethod
def authentication_download_avatar(
cls, request: Request, data: Forgot, token_dict: dict = None
):
found_user = Users.check_user_exits(
access_key=data.access_key, domain=data.domain
)
return JSONResponse(
content={
"completed": True,
"message": "Avatar and profile is shared via user credentials",
"data": {
"last_seen": str(found_user.last_seen),
"avatar": found_user.avatar,
"remember_me": found_user.remember_me,
"expiry_ends": str(found_user.expiry_ends),
"expired_str": str(
DateTimeLocal.now()
- DateTimeLocal.get(str(found_user.expiry_ends))
),
"expired_int": int(
(
DateTimeLocal.now()
- DateTimeLocal.get(str(found_user.expiry_ends))
).days
),
},
},
status_code=status.HTTP_200_OK,
)
AuthenticationLoginEventMethod = AuthenticationLoginEventMethods(
action=ActionsSchema(endpoint="/authentication/login")
)
AuthenticationSelectEventMethod = AuthenticationSelectEventMethods(
action=ActionsSchema(endpoint="/authentication/select")
)
AuthenticationCheckTokenEventMethod = AuthenticationCheckTokenEventMethods(
action=ActionsSchema(endpoint="/authentication/valid")
)
AuthenticationRefreshEventMethod = AuthenticationRefreshEventMethods(
action=ActionsSchema(endpoint="/authentication/refresh")
)
AuthenticationChangePasswordEventMethod = AuthenticationChangePasswordEventMethods(
action=ActionsSchema(endpoint="/authentication/change_password")
)
AuthenticationCreatePasswordEventMethod = AuthenticationCreatePasswordEventMethods(
action=ActionsSchema(endpoint="/authentication/create_password")
)
AuthenticationDisconnectUserEventMethod = AuthenticationDisconnectUserEventMethods(
action=ActionsSchema(endpoint="/authentication/disconnect")
)
AuthenticationLogoutEventMethod = AuthenticationLogoutEventMethods(
action=ActionsSchema(endpoint="/authentication/logout")
)
AuthenticationRefreshTokenEventMethod = AuthenticationRefreshTokenEventMethods(
action=ActionsSchema(endpoint="/authentication/refresher")
)
AuthenticationForgotPasswordEventMethod = AuthenticationForgotPasswordEventMethods(
action=ActionsSchema(endpoint="/authentication/forgot")
)
AuthenticationDownloadAvatarEventMethod = AuthenticationDownloadAvatarEventMethods(
action=ActionsSchema(endpoint="/authentication/avatar")
)

View File

@ -0,0 +1,5 @@
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
class RulesEvents(MethodToEvent): ...

View File

@ -0,0 +1,680 @@
import json
import typing
from fastapi import status
from fastapi.requests import Request
from fastapi.exceptions import HTTPException
from fastapi.responses import JSONResponse
from databases import (
Companies,
Staff,
Duties,
Departments,
Employees,
BuildLivingSpace,
BuildParts,
Build,
RelationshipEmployee2Build,
Event2Occupant,
Event2Employee,
Users,
UsersTokens,
OccupantTypes,
Duty,
)
from databases.no_sql_models.login_handlers import load_user_with_erp_details
from api_validations.validations_request import (
Login,
Logout,
ChangePassword,
Remember,
Forgot,
CreatePassword,
OccupantSelection,
EmployeeSelection,
)
from api_services import (
password_is_changed_template,
change_your_password_template,
save_access_token_to_redis,
update_selected_to_redis,
get_object_via_access_key,
get_object_via_user_uu_id,
redis_cli,
send_email,
)
from api_validations.core_response import return_json_response_from_alchemy
from api_configs import ApiStatic, Auth
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from api_library.date_time_actions.date_functions import DateTimeLocal
class AuthenticationLoginEventMethods(MethodToEvent):
event_type = "LOGIN"
__event_keys__ = {
"e672846d-cc45-4d97-85d5-6f96747fac67": "authentication_login_with_domain_and_creds",
}
@classmethod
def authentication_login_with_domain_and_creds(
cls,
data: Login,
request,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
access_dict = Users.login_user_with_credentials(data=data, request=request)
found_user = access_dict.get("user", None)
if not found_user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid credentials"
)
return JSONResponse(
content={
"completed": True,
"message": "User is logged in successfully",
"access_token": access_dict.get("access_token"),
"refresh_token": access_dict.get("refresher_token"),
"access_object": access_dict.get("access_object"),
"user": found_user.get_dict(),
},
status_code=status.HTTP_200_OK,
)
class AuthenticationSelectEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"cee96b9b-8487-4e9f-aaed-2e8c79687bf9": "authentication_select_company_or_occupant_type",
}
@classmethod
def authentication_select_company_or_occupant_type(
cls,
request: Request,
data: typing.Union[EmployeeSelection, OccupantSelection],
token_dict: dict = None,
):
from api_objects.auth.token_objects import OccupantToken, CompanyToken
token_user = get_object_via_access_key(request=request)
if token_user.user_type == 1:
if data.company_uu_id not in token_user.companies_uu_id_list:
return JSONResponse(
content={
"completed": False,
"message": "Company is not found in users company list",
},
status_code=status.HTTP_401_UNAUTHORIZED,
)
if selected_company := Companies.find_one(uu_id=data.company_uu_id):
department_ids = [
department.id
for department in Departments.filter_by_active(
company_id=selected_company.id
).data
]
duties_ids = [
duties.id
for duties in Duties.filter_active(
Duties.company_id == selected_company.id,
Duties.department_id.in_(department_ids),
).data
]
staff_ids = [
staff.id
for staff in Staff.filter_active(
Staff.duties_id.in_(duties_ids)
).data
]
employee = Employees.filter_active(
Employees.people_id == token_user.person_id,
Employees.staff_id.in_(staff_ids),
).data[0]
reachable_event_list_id, reachable_event_list_uu_id = (
Event2Employee.get_event_id_by_employee_id(employee_id=employee.id)
)
staff = Staff.find_one(id=employee.staff_id)
duties = Duties.find_one(id=staff.duties_id)
department = Departments.find_one(id=duties.department_id)
bulk_id = Duty.find_one(duty_code="BULK")
bulk_duty_id = Duties.find_one(
company_id=selected_company.id, duties_id=bulk_id.id
)
update_selected_to_redis(
request=request,
add_payload=CompanyToken(
company_uu_id=selected_company.uu_id.__str__(),
company_id=selected_company.id,
department_id=department.id,
department_uu_id=department.uu_id.__str__(),
duty_id=duties.id,
duty_uu_id=duties.uu_id.__str__(),
bulk_duties_id=bulk_duty_id.id,
staff_id=staff.id,
staff_uu_id=staff.uu_id.__str__(),
employee_id=employee.id,
employee_uu_id=employee.uu_id.__str__(),
reachable_event_list_id=reachable_event_list_id,
reachable_event_list_uu_id=reachable_event_list_uu_id,
),
)
return JSONResponse(
content={
"completed": True,
"message": "Company is selected successfully",
},
status_code=status.HTTP_200_OK,
)
elif token_user.user_type == 2:
occupant_type = OccupantTypes.find_one(uu_id=data.occupant_uu_id)
if not occupant_type:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Occupant Type is not found",
)
build_part = BuildParts.find_one(uu_id=data.build_part_uu_id)
if not build_part:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Build Part is not found",
)
build = Build.find_one(id=build_part.build_id)
related_company = RelationshipEmployee2Build.find_one(member_id=build.id)
company_related = Companies.find_one(id=related_company.company_id)
responsible_employee = Employees.find_one(id=related_company.employee_id)
if selected_occupant_type := BuildLivingSpace.find_one(
occupant_type=occupant_type.id,
person_id=token_user.person_id,
build_parts_id=build_part.id,
):
reachable_event_list_id, reachable_event_list_uu_id = (
Event2Occupant.get_event_id_by_build_living_space_id(
build_living_space_id=selected_occupant_type.id
)
)
update_selected_to_redis(
request=request,
add_payload=OccupantToken(
living_space_id=selected_occupant_type.id,
living_space_uu_id=selected_occupant_type.uu_id.__str__(),
occupant_type_id=occupant_type.id,
occupant_type_uu_id=occupant_type.uu_id.__str__(),
occupant_type=occupant_type.occupant_type,
build_id=build.id,
build_uuid=build.uu_id.__str__(),
build_part_id=build_part.id,
build_part_uuid=build_part.uu_id.__str__(),
responsible_employee_id=responsible_employee.id,
responsible_employee_uuid=responsible_employee.uu_id.__str__(),
responsible_company_id=company_related.id,
responsible_company_uuid=company_related.uu_id.__str__(),
reachable_event_list_id=reachable_event_list_id,
reachable_event_list_uu_id=reachable_event_list_uu_id,
),
)
return JSONResponse(
content={
"completed": True,
"message": "Occupant is selected successfully",
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={"completed": False, "message": "Invalid data provided"},
status_code=status.HTTP_418_IM_A_TEAPOT,
)
class AuthenticationCheckTokenEventMethods(MethodToEvent):
event_type = "CHECK"
__event_keys__ = {
"73d77e45-a33f-4f12-909e-3b56f00d8a12": "authentication_check_token_is_valid",
}
@classmethod
def authentication_login_with_domain_and_creds(
cls, request, token_dict: dict = None
):
if get_object_via_access_key(request=request):
return JSONResponse(
content={"completed": True, "message": "Access Token is valid"},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={"completed": False, "message": "Access Token is NOT valid"},
status_code=status.HTTP_401_UNAUTHORIZED,
)
class AuthenticationRefreshEventMethods(MethodToEvent):
event_type = "REFRESH"
__event_keys__ = {
"48379bb2-ba81-4d8e-a9dd-58837cfcbf67": "authentication_refresh_user_info",
}
@classmethod
def authentication_refresh_user_info(cls, request, token_dict: dict = None):
access_token = str(request.headers.get(Auth.ACCESS_TOKEN_TAG))
if token_user := get_object_via_access_key(request=request):
if found_user := Users.find_one(uu_id=token_user.get("uu_id")):
user_token = UsersTokens.find_one(
domain=found_user.domain_name,
user_id=found_user.id,
token_type="RememberMe",
)
access_dict = {
"access_token": access_token,
"refresh_token": getattr(user_token, "token", None),
}
return JSONResponse(
content={
"completed": True,
"message": "User is logged in successfully via refresh token",
"data": load_user_with_erp_details(found_user, access_dict),
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={"completed": False, "message": "Invalid data", "data": {}},
status_code=status.HTTP_401_UNAUTHORIZED,
)
class AuthenticationChangePasswordEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"f09f7c1a-bee6-4e32-8444-962ec8f39091": "authentication_change_password",
}
@classmethod
def authentication_change_password(
cls, request, data: ChangePassword, token_dict: dict = None
):
token_user = get_object_via_access_key(request=request)
if token_user.user_type == 1:
if found_user := Users.find_one(uu_id=token_user.uu_id):
if found_user.check_password(data.old_password):
found_user.set_password(data.new_password)
return JSONResponse(
content={
"completed": True,
"message": "Password is changed successfully",
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={
"completed": False,
"message": "Old password is not correct",
},
status_code=status.HTTP_401_UNAUTHORIZED,
)
return JSONResponse(
content={"completed": False, "message": "Invalid data"},
status_code=status.HTTP_401_UNAUTHORIZED,
)
class AuthenticationCreatePasswordEventMethods(MethodToEvent):
event_type = "CREATE"
__event_keys__ = {
"c519f9af-92e1-47b2-abf7-5a3316d075f7": "authentication_create_password",
}
@classmethod
def authentication_create_password(
cls, request, data: CreatePassword, token_dict: dict = None
):
if not data.re_password == data.password:
raise HTTPException(
status_code=status.HTTP_406_NOT_ACCEPTABLE, detail="Password must match"
)
if found_user := Users.find_one(password_token=data.password_token):
found_user.create_password(password=data.password)
found_user.password_token = None
found_user.save()
send_email_completed = send_email(
subject=f"Dear {found_user.user_tag}, your password has been changed.",
receivers=[str(found_user.email)],
html=password_is_changed_template(user_name=found_user.user_tag),
)
if not send_email_completed:
raise HTTPException(
status_code=400, detail="Email can not be sent. Try again later"
)
return JSONResponse(
content={
"completed": True,
"message": "Password is created successfully",
"data": found_user.get_dict(),
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={
"completed": False,
"message": "Record not found",
"data": {},
},
status_code=status.HTTP_202_ACCEPTED,
)
class AuthenticationDisconnectUserEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"8b586848-2fb3-4161-abbe-642157eec7ce": "authentication_disconnect_user",
}
@classmethod
def authentication_disconnect_user(
cls, request: Request, data: Logout, token_dict: dict = None
):
if token_user := get_object_via_access_key(request=request):
found_user = Users.find_one(uu_id=token_user.get("uu_id"))
if not found_user:
return JSONResponse(
content={
"completed": False,
"message": "Invalid data",
"data": None,
},
status_code=status.HTTP_202_ACCEPTED,
)
if already_tokens := get_object_via_user_uu_id(user_id=found_user.uu_id):
for key in already_tokens:
token_user = json.loads(redis_cli.get(key) or {})
redis_cli.delete(key)
selected_user = Users.find_one(uu_id=token_user.get("uu_id"))
selected_user.remove_refresher_token(
domain=data.domain, disconnect=True
)
# UserLogger.log_error(
# str(
# dict(
# user_id=found_user.id,
# domain=data.domain,
# access_key=token_user.get("access_input"),
# agent=request.headers.get("User-Agent", None),
# ip=getattr(request, "remote_addr", None)
# or request.headers.get("X-Forwarded-For", None),
# platform=request.headers.get("Origin", None),
# login_date=datetime.datetime.utcnow().__str__(),
# is_login=False,
# )
# )
# )
return JSONResponse(
content={
"completed": True,
"message": "All sessions are disconnected",
"data": token_user,
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={"completed": False, "message": "Invalid data", "data": None},
status_code=status.HTTP_202_ACCEPTED,
)
class AuthenticationLogoutEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"5cc22e4e-a0f7-4077-be41-1871feb3dfd1": "authentication_logout_user",
}
@classmethod
def authentication_logout_user(
cls, request: Request, data: Logout, token_dict: dict = None
):
token_user = None
if already_tokens := get_object_via_access_key(request=request):
for key in already_tokens:
token_user = json.loads(redis_cli.get(key) or {})
if token_user.get("domain") == data.domain:
redis_cli.delete(key)
selected_user = Users.find_one(uu_id=token_user.get("uu_id"))
selected_user.remove_refresher_token(domain=data.domain)
# UserLogger.log_error(
# str(
# dict(
# user_id=selected_user.id,
# domain=data.domain,
# access_key=token_user.get("access_input"),
# agent=request.headers.get("User-Agent", None),
# ip=getattr(request, "remote_addr", None)
# or request.headers.get("X-Forwarded-For", None),
# platform=request.headers.get("Origin", None),
# login_date=datetime.datetime.utcnow().__str__(),
# is_login=False,
# )
# )
# )
return JSONResponse(
content={
"completed": True,
"message": "Session is logged out",
"data": token_user,
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={
"completed": False,
"message": "Logout is not successfully completed",
"data": None,
},
status_code=status.HTTP_202_ACCEPTED,
)
class AuthenticationRefreshTokenEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"c90f3334-10c9-4181-b5ff-90d98a0287b2": "authentication_refresher_token",
}
@classmethod
def authentication_refresher_token(
cls, request: Request, data: Remember, token_dict: dict = None
):
token_refresher = UsersTokens.find_one(
token=data.refresh_token, domain=data.domain
)
if not token_refresher:
return JSONResponse(
content={"completed": False, "message": "Invalid data", "data": {}},
status_code=status.HTTP_202_ACCEPTED,
)
if found_user := Users.find_one(id=token_refresher.user_id):
found_user: Users = found_user
access_key = save_access_token_to_redis(
request=request, found_user=found_user, domain=data.domain
)
found_user.last_agent = request.headers.get("User-Agent", None)
found_user.last_platform = request.headers.get("Origin", None)
found_user.last_remote_addr = getattr(
request, "remote_addr", None
) or request.headers.get("X-Forwarded-For", None)
found_user.last_seen = str(DateTimeLocal.now())
# UserLogger.log_error(
# str(
# dict(
# user_id=found_user.id,
# domain=data.domain,
# access_key="via_refresher",
# agent=request.headers.get("User-Agent", None),
# ip=getattr(request, "remote_addr", None)
# or request.headers.get("X-Forwarded-For", None),
# platform=request.headers.get("Origin", None),
# login_date=datetime.datetime.utcnow().__str__(),
# is_login=False,
# )
# )
# )
return JSONResponse(
content={
"completed": True,
"message": "User is logged in successfully via refresher token",
"data": load_user_with_erp_details(
found_user,
{
"access_token": access_key,
"refresh_token": data.refresh_token,
},
),
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={"completed": False, "message": "Invalid data", "data": {}},
status_code=status.HTTP_202_ACCEPTED,
)
class AuthenticationForgotPasswordEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"e3ca6e24-b9f8-4127-949c-3bfa364e3513": "authentication_forgot_password",
}
@classmethod
def authentication_forgot_password(
cls, request: Request, data: Forgot, token_dict: dict = None
):
found_user: Users = Users.check_user_exits(
access_key=data.access_key, domain=data.domain
)
forgot_key = save_access_token_to_redis(
request=request, found_user=found_user, domain=data.domain
)
# UserLogger.log_error(
# str(
# dict(
# user_id=found_user.id,
# domain=data.domain,
# access_key=data.access_key,
# agent=request.headers.get("User-Agent", None),
# ip=getattr(request, "remote_addr", None)
# or request.headers.get("X-Forwarded-For", None),
# platform=request.headers.get("Origin", None),
# login_date=str(DateTimeLocal.now()),
# is_login=False,
# )
# )
# )
forgot_link = ApiStatic.forgot_link(forgot_key=forgot_key)
send_email_completed = send_email(
subject=f"Dear {found_user.user_tag}, your forgot password link has been sent.",
receivers=[str(found_user.email)],
html=change_your_password_template(
user_name=found_user.user_tag, forgot_link=forgot_link
),
)
if not send_email_completed:
raise HTTPException(
status_code=400, detail="Email can not be sent. Try again later"
)
found_user.password_token = forgot_key
found_user.password_token_is_valid = str(DateTimeLocal.shift(days=1))
found_user.save()
return JSONResponse(
content={
"completed": True,
"message": "Password is change link is sent to your email or phone",
"data": {},
},
status_code=status.HTTP_200_OK,
)
class AuthenticationDownloadAvatarEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"c140cd5f-307f-4046-a93e-3ade032a57a7": "authentication_download_avatar",
}
@classmethod
def authentication_download_avatar(
cls, request: Request, data: Forgot, token_dict: dict = None
):
found_user = Users.check_user_exits(
access_key=data.access_key, domain=data.domain
)
return JSONResponse(
content={
"completed": True,
"message": "Avatar and profile is shared via user credentials",
"data": {
"last_seen": str(found_user.last_seen),
"avatar": found_user.avatar,
"remember_me": found_user.remember_me,
"expiry_ends": str(found_user.expiry_ends),
"expired_str": str(
DateTimeLocal.now()
- DateTimeLocal.get(str(found_user.expiry_ends))
),
"expired_int": int(
(
DateTimeLocal.now()
- DateTimeLocal.get(str(found_user.expiry_ends))
).days
),
},
},
status_code=status.HTTP_200_OK,
)
AuthenticationLoginEventMethod = AuthenticationLoginEventMethods(
action=ActionsSchema(endpoint="/authentication/login")
)
AuthenticationSelectEventMethod = AuthenticationSelectEventMethods(
action=ActionsSchema(endpoint="/authentication/select")
)
AuthenticationCheckTokenEventMethod = AuthenticationCheckTokenEventMethods(
action=ActionsSchema(endpoint="/authentication/valid")
)
AuthenticationRefreshEventMethod = AuthenticationRefreshEventMethods(
action=ActionsSchema(endpoint="/authentication/refresh")
)
AuthenticationChangePasswordEventMethod = AuthenticationChangePasswordEventMethods(
action=ActionsSchema(endpoint="/authentication/change_password")
)
AuthenticationCreatePasswordEventMethod = AuthenticationCreatePasswordEventMethods(
action=ActionsSchema(endpoint="/authentication/create_password")
)
AuthenticationDisconnectUserEventMethod = AuthenticationDisconnectUserEventMethods(
action=ActionsSchema(endpoint="/authentication/disconnect")
)
AuthenticationLogoutEventMethod = AuthenticationLogoutEventMethods(
action=ActionsSchema(endpoint="/authentication/logout")
)
AuthenticationRefreshTokenEventMethod = AuthenticationRefreshTokenEventMethods(
action=ActionsSchema(endpoint="/authentication/refresher")
)
AuthenticationForgotPasswordEventMethod = AuthenticationForgotPasswordEventMethods(
action=ActionsSchema(endpoint="/authentication/forgot")
)
AuthenticationDownloadAvatarEventMethod = AuthenticationDownloadAvatarEventMethods(
action=ActionsSchema(endpoint="/authentication/avatar")
)

View File

View File

@ -0,0 +1,252 @@
import typing
from fastapi import status, HTTPException
from fastapi.responses import JSONResponse
from databases import (
Build,
# RelationshipEmployee2Build,
Addresses,
BuildParts,
BuildTypes,
ApiEnumDropdown,
)
from api_validations import (
InsertBuild,
UpdateBuild,
PatchRecord,
ListOptions,
)
from api_validations.core_response import return_json_response_from_alchemy
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
class BuildListEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"68b3b5ed-b74c-4a27-820f-3959214e94e9": "build_list",
}
@classmethod
def build_list(
cls,
list_options: ListOptions,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
if isinstance(token_dict, OccupantTokenObject):
Build.pre_query = Build.filter_active(
Build.id == token_dict.selected_occupant.build_id
).query
elif isinstance(token_dict, EmployeeTokenObject):
Build.pre_query = Build.select_action(
employee_id=token_dict.selected_company.employee_id
)
Build.filter_attr = list_options
records = Build.filter_active(
*Build.get_smart_query(smart_query=list_options.query)
)
return return_json_response_from_alchemy(
response=records, pagination=list_options
)
class BuildCreateEventMethods(MethodToEvent):
event_type = "CREATE"
__event_keys__ = {
"a2271854-6b90-43da-a440-a62b70d90528": "build_create",
"b67ee709-0992-4604-9f90-fb1da10d5cf9": "create_building_employee",
}
@classmethod
def build_create(cls, data: InsertBuild, token_dict: EmployeeTokenObject):
if not token_dict.selected_company.employee_id:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=f"Employee id is not found for {token_dict.selected_company.employee_uu_id}",
)
if not token_dict.selected_company.company_id:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=f"Company id is not found for {token_dict.selected_company.company_uu_id}",
)
created_build = Build.create_action(data=data, token=token_dict)
if not created_build.is_found:
build_type = BuildTypes.find_one(type_code="APT_YNT")
if not build_type:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Build type APT_YNT is not found. Please contact with your system administrator.",
)
api_enum = ApiEnumDropdown.find_one(enum_class="Directions", key="NN")
if not api_enum:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Api Enum NN is not found. Please contact with your system administrator.",
)
build_parts = dict(
address_gov_code=f"{data.gov_address_code}-M",
build_id=int(created_build.id),
build_uu_id=str(created_build.uu_id),
part_no="0",
part_type_id=int(build_type.id),
part_type_uu_id=str(build_type.uu_id),
part_direction_id=int(api_enum.id),
part_direction_uu_id=str(api_enum.uu_id),
part_code="MAN-ROOM",
human_livable=False,
is_confirmed=True,
)
man_build_part = BuildParts.find_or_create(**build_parts)
if not man_build_part.is_found:
created_build.update(management_room_id=man_build_part.id)
return JSONResponse(
content={
"completed": True,
"message": "Create Build record completed. This build is assigned to you.",
"data": created_build.get_dict(),
},
status_code=status.HTTP_200_OK,
)
raise HTTPException(
status_code=status.HTTP_406_NOT_ACCEPTABLE,
detail=f"Build record create not successful for Employee UUID : {token_dict.selected_company.employee_uu_id}",
)
@classmethod
def create_building_employee(
cls, data: InsertBuild, token_dict: EmployeeTokenObject
):
records = Addresses.list_via_employee(
token_dict=token_dict, filter_expr=[Addresses.uu_id == data.address_uu_id]
)
if not records.data:
raise HTTPException(
status_code=404,
detail=f"This address {data.address_uu_id} is not found in the user's address list.",
)
if not token_dict.selected_company.employee_id:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=f"Employee id is not found for {token_dict.selected_company.employee_uu_id}",
)
if not token_dict.selected_company.company_id:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=f"Company id is not found for {token_dict.selected_company.company_uu_id}",
)
created_build = Build.create_action(data=data, token=token_dict)
if not created_build.is_found:
RelationshipEmployee2Build.find_or_create(
company_id=token_dict.selected_company.company_id,
member_id=created_build.id,
employee_id=token_dict.selected_company.employee_id,
is_confirmed=True,
)
return JSONResponse(
content={
"completed": True,
"message": "Create Build record completed. This build is assigned to you.",
"data": created_build.get_dict(),
},
status_code=status.HTTP_200_OK,
)
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=f"Build record create not successful for {token_dict.selected_company.employee_uu_id}",
)
class BuildUpdateEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"5ad38a66-1189-451e-babb-77de2d63d757": "build_update",
}
@classmethod
def build_update(cls, build_uu_id: str, data: UpdateBuild, token_dict):
Build.pre_query = Build.select_action(
employee_id=token_dict.selected_company.employee_id
)
if Build.filter_active(Build.person_id == token_dict.person_id):
if updated_build := Build.update_action(
data=data, token=token_dict, build_uu_id=build_uu_id
):
return JSONResponse(
content={
"completed": True,
"message": "Update Build record",
"data": updated_build,
},
status_code=status.HTTP_200_OK,
)
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=f"This user can not modify {build_uu_id} - building.",
)
class BuildPatchEventMethods(MethodToEvent):
event_type = "PATCH"
__event_keys__ = {
"e3876bfe-8847-4dea-ae36-e709f7431930": "build_patch",
}
@classmethod
def build_patch(cls, build_uu_id: str, data: PatchRecord, token_dict):
find_one_build = Build.find_one_or_abort(uu_id=build_uu_id)
access_authorized_build = Build.select_action(
employee_id=token_dict.selected_company.employee_id,
filter_expr=[Build.id == find_one_build.id],
)
if access_authorized_build.count:
action = data.excluded_dump()
find_one_build.active = bool(action.get("active", find_one_build.active))
find_one_build.is_confirmed = bool(
action.get("confirm", find_one_build.is_confirmed)
)
find_one_build.deleted = bool(action.get("delete", find_one_build.deleted))
find_one_build.save()
return JSONResponse(
content={
"completed": True,
"message": "Patch Build record completed",
"data": find_one_build.get_dict(),
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={
"completed": False,
"message": "Patch Build record failed",
"data": {},
},
status_code=status.HTTP_200_OK,
)
BuildListEventMethod = BuildListEventMethods(
action=ActionsSchema(endpoint="/building/build/list")
)
BuildCreateEventMethod = BuildCreateEventMethods(
action=ActionsSchema(endpoint="/building/build/create")
)
BuildUpdateEventMethod = BuildUpdateEventMethods(
action=ActionsSchema(endpoint="/building/build/update")
)
BuildPatchEventMethod = BuildPatchEventMethods(
action=ActionsSchema(endpoint="/building/build/patch")
)

View File

@ -0,0 +1,5 @@
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
class BuildingBuildAreaEvents(MethodToEvent): ...

View File

@ -0,0 +1,150 @@
from fastapi.responses import JSONResponse
from fastapi import status
from databases import (
Build,
BuildParts,
)
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from api_validations.core_response import return_json_response_from_alchemy
from api_validations import (
InsertBuildParts,
ListOptions,
)
class BuildingBuildPartsListEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"b860e37a-e19b-4c45-9543-461241f7587c": "building_build_parts_list"
}
@classmethod
def building_build_parts_list(cls, list_options: ListOptions, token_dict):
build_list_query = Build.select_action(
employee_id=token_dict.selected_company.employee_id,
)
build_list_ids = [build.id for build in build_list_query.all()]
BuildParts.pre_query = BuildParts.query.filter(
BuildParts.build_id.in_(build_list_ids)
)
records = BuildParts.filter_active(
*BuildParts.get_smart_query(list_options.query)
)
return return_json_response_from_alchemy(
response=records, pagination=list_options
)
class BuildingBuildPartsCreateEventMethods(MethodToEvent):
event_type = "CREATE"
__event_keys__ = {
"fb403f69-11ed-4f4f-ad71-5e6fb4a793d2": "building_build_parts_create"
}
@classmethod
def building_build_parts_create(cls, data: InsertBuildParts, token_dict: dict):
created_build = BuildParts.create_action(data=data, token=token_dict)
if not created_build:
return JSONResponse(
content={
"completed": False,
"message": "Create Build Parts is not completed",
"data": {},
},
status_code=status.HTTP_406_NOT_ACCEPTABLE,
)
return JSONResponse(
content={
"completed": True,
"message": "Create Build Parts record",
"data": created_build.get_dict(),
},
status_code=status.HTTP_200_OK,
)
class BuildingBuildPartsUpdateEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"58fdf95e-2110-4ed6-9c26-95f4be87eaee": "building_build_parts_update"
}
@classmethod
def building_build_parts_update(cls, data: InsertBuildParts, token_dict: dict):
if updated_build := BuildParts.update_action(data=data, token=token_dict):
return JSONResponse(
content={
"completed": True,
"message": "Update Build Parts record",
"data": updated_build,
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={
"completed": True,
"message": "Update Build Parts record",
"data": {},
},
status_code=status.HTTP_200_OK,
)
class BuildingBuildPartsPatchEventMethods(MethodToEvent):
event_type = "PATCH"
__event_keys__ = {
"87a15ade-3474-4206-b574-bbf8580cbb14": "building_build_parts_patch"
}
@classmethod
def building_build_parts_patch(cls, data, token_dict):
find_one_build = BuildParts.find_one(uu_id=data.uu_id)
access_authorized_build = BuildParts.select_action(
duty_id=token_dict.selected_company.duty_id,
filter_expr=[BuildParts.id == find_one_build.id],
)
if access_authorized_build.count:
action = data.excluded_dump()
find_one_build.active = bool(action.get("active", find_one_build.active))
find_one_build.is_confirmed = bool(
action.get("confirm", find_one_build.is_confirmed)
)
find_one_build.deleted = bool(action.get("delete", find_one_build.deleted))
find_one_build.save()
return JSONResponse(
content={
"completed": True,
"message": "Update Build Parts record",
"data": find_one_build.get_dict(),
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={
"completed": False,
"message": "Update Build Parts record",
"data": {},
},
status_code=status.HTTP_200_OK,
)
BuildingBuildPartsListEventMethod = BuildingBuildPartsListEventMethods(
action=ActionsSchema(endpoint="/building/parts/list")
)
BuildingBuildPartsCreateEventMethod = BuildingBuildPartsCreateEventMethods(
action=ActionsSchema(endpoint="/building/parts/create")
)
BuildingBuildPartsUpdateEventMethod = BuildingBuildPartsUpdateEventMethods(
action=ActionsSchema(endpoint="/building/parts/update")
)
BuildingBuildPartsPatchEventMethod = BuildingBuildPartsPatchEventMethods(
action=ActionsSchema(endpoint="/building/parts/patch")
)

View File

@ -0,0 +1,5 @@
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
class BuildingBuildSitesEvents(MethodToEvent): ...

View File

@ -0,0 +1,5 @@
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
class BuildingBuildTypesEvents(MethodToEvent): ...

View File

@ -0,0 +1,240 @@
import typing
from fastapi import status, HTTPException
from databases import (
BuildParts,
Build,
BuildLivingSpace,
OccupantTypes,
)
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from api_validations.core_response import return_json_response_from_alchemy
from api_validations import (
InsertBuildLivingSpace,
ListOptions,
)
class BuildingLivingSpacesPartsListEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"8fd04d94-68fb-4a07-9549-8b47aee3a870": "building_build_parts_list",
"2f3041a9-6184-44c2-ac38-8ea934297ed1": "building_build_parts_list_with_expired",
}
@classmethod
def building_build_parts_list(cls, list_options: ListOptions, token_dict):
build_id_list_query = Build.select_action(
employee_id=token_dict.selected_company.employee_id
)
Build.filter_attr = list_options
build_part_id_list_query = BuildParts.filter_active(
BuildParts.build_id.in_([build.id for build in build_id_list_query.all()]),
)
list_options.query.pop("expiry_starts", None)
list_options.query.pop("expiry_ends", None)
records = BuildLivingSpace.filter_active(
BuildLivingSpace.build_parts_id.in_(
[build_part.id for build_part in build_part_id_list_query.data]
),
*BuildLivingSpace.get_smart_query(smart_query=list_options.query),
)
return return_json_response_from_alchemy(
response=records, pagination=list_options
)
@classmethod
def building_build_parts_list_with_expired(
cls, list_options: ListOptions, token_dict
):
build_id_list_query = Build.select_action(
employee_id=token_dict.selected_company.employee_id
)
Build.filter_attr = list_options
build_part_id_list_query = BuildParts.filter_active(
BuildParts.build_id.in_([build.id for build in build_id_list_query.all()]),
)
records = BuildLivingSpace.filter_active(
BuildLivingSpace.build_parts_id.in_(
[build_part.id for build_part in build_part_id_list_query.data]
),
*BuildLivingSpace.get_smart_query(smart_query=list_options.query),
expired=False,
)
return return_json_response_from_alchemy(
response=records, pagination=list_options
)
class BuildingLivingSpacesPartsCreateEventMethods(MethodToEvent):
event_type = "CREATE"
__event_keys__ = {
"b78ca45c-b9f4-41f6-9ddb-2c6f2faa2570": "building_live_space_create"
}
@classmethod
def building_live_space_create(
cls,
data: InsertBuildLivingSpace,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
from service_app.application import DateTimeLocal
from database_sql_models import People
from sqlalchemy.sql import select
data_dict = data.dump()
build_id_list_query = Build.select_action(
employee_id=token_dict.selected_company.employee_id
)
build_part = BuildParts.filter_active(
BuildParts.uu_id == data.build_parts_uu_id,
BuildParts.build_id.in_([build.id for build in build_id_list_query.all()]),
)
if not build_part.get(1):
raise HTTPException(
status_code=status.HTTP_418_IM_A_TEAPOT,
detail=f"{data.build_parts_uu_id} - Build Part is not found in database. Check build part uu_id",
)
build_part = build_part.get(1)
life_person = People.find_one(uu_id=data.person_uu_id or "")
if not life_person:
raise HTTPException(
status_code=status.HTTP_418_IM_A_TEAPOT,
detail=f"{data.life_person_uu_id} - Living Person is not found in database. "
f"Check build live person uu_id",
)
occupant_type = OccupantTypes.find_one(uu_id=data.occupant_type_uu_id)
if not occupant_type:
raise HTTPException(
status_code=status.HTTP_418_IM_A_TEAPOT,
detail=f"{data.occupant_type_uu_id} - Occupant Type is not found in database. "
f"Check occupant type uu_id",
)
data_dict["occupant_type"] = occupant_type.id
data_dict["occupant_type_uu_id"] = str(occupant_type.uu_id)
data_dict["build_parts_id"] = build_part.id
data_dict["build_parts_uu_id"] = str(build_part.uu_id)
data_dict["person_id"] = life_person.id
data_dict["person_uu_id"] = str(life_person.uu_id)
living_space_id = BuildLivingSpace.session.execute(
select(BuildLivingSpace.id)
.where(
*[
BuildLivingSpace.build_parts_id == build_part.id,
BuildLivingSpace.person_id == life_person.id,
BuildLivingSpace.occupant_type == occupant_type.id,
BuildLivingSpace.active == True,
BuildLivingSpace.is_confirmed == True,
str(DateTimeLocal.now()) < BuildLivingSpace.expiry_ends,
str(DateTimeLocal.now()) >= BuildLivingSpace.expiry_starts,
]
)
.order_by(BuildLivingSpace.expiry_starts.desc())
).first()
last_living_space = BuildLivingSpace.find_one(
id=living_space_id[0] if living_space_id else None
)
data_dict["expiry_starts"] = str(DateTimeLocal.now())
created_living_space = BuildLivingSpace.create_action(
data=data_dict, token_dict=token_dict
)
if last_living_space:
if last_living_space.expiry_ends > DateTimeLocal.now():
last_living_space.expiry_ends = str(DateTimeLocal.shift(minutes=-10))
last_living_space.save()
return created_living_space
class BuildingLivingSpacesPartsUpdateEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"70b4666f-4ceb-46ec-b89e-24be8712f0e7": "building_build_parts_update"
}
@classmethod
def building_build_parts_update(cls, build_uu_id: str, data, token_dict):
from service_app.application import DateTimeLocal
from database_sql_models import People
from sqlalchemy.sql import select
data_dict = data.dump()
build_id_list_query = Build.select_action(
employee_id=token_dict.selected_company.employee_id
)
build_part = BuildParts.filter_active(
BuildParts.uu_id == data.build_parts_uu_id,
BuildParts.build_id.in_([build.id for build in build_id_list_query.all()]),
)
if not build_part.get(1):
raise HTTPException(
status_code=status.HTTP_418_IM_A_TEAPOT,
detail=f"{data.build_parts_uu_id} - Build Part is not found in database. Check build part uu_id",
)
build_part = build_part.get(1)
life_person = People.find_one(uu_id=data.life_person_uu_id or "")
if not life_person:
raise HTTPException(
status_code=status.HTTP_418_IM_A_TEAPOT,
detail=f"{data.life_person_uu_id} - Living Person is not found in database. "
f"Check build live person uu_id",
)
living_spaces = select(BuildLivingSpace.id).order_by(
BuildLivingSpace.expiry_starts.desc()
)
living_space_id = BuildLivingSpace.session.execute(living_spaces).first()
last_living_space = BuildLivingSpace.find_one(
id=getattr(living_space_id[0], "id", None) if living_space_id else None
)
data_dict["expiry_starts"] = DateTimeLocal.now()
data_dict["is_tenant_live"] = bool(data.is_tenant_live)
data_dict["build_parts_id"] = build_part.id
if data_dict["is_tenant_live"]:
owner_person = getattr(last_living_space, "owner_person_id", None)
if not owner_person:
raise HTTPException(
status_code=status.HTTP_418_IM_A_TEAPOT,
detail=dict(
message="Owner person of build part is not defined. Please register owner of part first.",
data=build_part.get_dict(),
),
)
data_dict["life_person_id"] = life_person.id
data_dict["owner_person_id"] = owner_person
else:
data_dict["life_person_id"] = life_person.id
data_dict["owner_person_id"] = life_person.id
del data_dict["build_parts_uu_id"], data_dict["life_person_uu_id"]
BuildingLivingSpacesPartsListEventMethod = BuildingLivingSpacesPartsListEventMethods(
action=ActionsSchema(endpoint="/building/living_space/list")
)
BuildingLivingSpacesPartsCreateEventMethod = (
BuildingLivingSpacesPartsCreateEventMethods(
action=ActionsSchema(endpoint="/building/living_space/create")
)
)
BuildingLivingSpacesPartsUpdateEventMethod = (
BuildingLivingSpacesPartsUpdateEventMethods(
action=ActionsSchema(endpoint="/building/living_space/update")
)
)

View File

View File

@ -0,0 +1,171 @@
import typing
from fastapi import status
from fastapi.responses import JSONResponse
from databases import Companies
from api_validations import (
InsertCompany,
UpdateCompany,
ListOptions,
PatchRecord,
)
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from api_validations.core_response import return_json_response_from_alchemy
class CompanyListEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"f6900cb5-ac5b-478e-8e7c-fa87e65cd2e5": "company_list",
}
@classmethod
def company_list(
cls,
list_options: ListOptions,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
if isinstance(token_dict, EmployeeTokenObject):
Companies.pre_query = Companies.select_action(
duty_id_list=[
token_dict.selected_company.duty_id,
token_dict.selected_company.bulk_duties_id,
]
)
elif isinstance(token_dict, OccupantTokenObject):
Companies.pre_query = Companies.filter_active(
Companies.id == token_dict.selected_occupant.responsible_company_id
).query
Companies.filter_attr = list_options
records = Companies.filter_active(
*Companies.get_smart_query(list_options.query)
)
return return_json_response_from_alchemy(
response=records, pagination=list_options
)
class CompanyCreateEventMethods(MethodToEvent):
event_type = "CREATE"
__event_keys__ = {
"76f11a08-5f4a-4e1f-961f-aaef21699acd": "company_create",
}
@classmethod
def company_create(cls, data: InsertCompany, token_dict):
created_company = Companies.create_action(
data=data, token=token_dict.companies_list
)
created_company.related_company = token_dict.get("company_uu_id")
return JSONResponse(
content={
"completed": True,
"message": "Create Company record",
"data": created_company.get_dict(),
"password_token": {
"password_token": created_company.password_token,
"password_expires_day": str(created_company.password_expires_day),
"password_expiry_begins": str(
created_company.password_expiry_begins
),
"hash_password": created_company.hash_password,
"related_company": created_company.related_company,
},
},
status_code=status.HTTP_200_OK,
)
class CompanyUpdateEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"41ea7f29-006a-4310-b5c4-b2a0e1a504bd": "company_update",
}
@classmethod
def company_update(cls, company_uu_id: str, data: UpdateCompany, token_dict):
find_one_company = Companies.find_one_or_abort(uu_id=company_uu_id)
access_authorized_company = Companies.select_action(
duty_id=getattr(token_dict, "duty_id", 5),
filter_expr=[Companies.id == token_dict.get("")],
)
if access_authorized_company.count:
data_dict = data.excluded_dump()
updated_company = find_one_company.update(**data_dict)
return JSONResponse(
content={
"completed": True,
"message": "Update Company record",
"data": updated_company,
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={"completed": True, "message": "Update Company record", "data": {}},
status_code=status.HTTP_200_OK,
)
class CompanyPatchEventMethods(MethodToEvent):
event_type = "PATCH"
__event_keys__ = {
"6320d696-1fd1-49f9-860a-8f22e5b8a68d": "company_patch",
}
@classmethod
def company_patch(cls, company_uu_id: str, data: PatchRecord, token_dict):
find_one_company = Companies.find_one_or_abort(uu_id=company_uu_id)
access_authorized_company = Companies.select_action(
duty_id=getattr(token_dict, "duty_id", 5),
filter_expr=[Companies.id == find_one_company.id],
)
if access_authorized_company.count:
action = data.excluded_dump()
find_one_company.active = bool(
action.get("active", find_one_company.active)
)
find_one_company.is_confirmed = bool(
action.get("confirm", find_one_company.is_confirmed)
)
find_one_company.deleted = bool(
action.get("delete", find_one_company.deleted)
)
find_one_company.save()
return JSONResponse(
content={
"completed": True,
"message": "Patch Company record completed",
"data": find_one_company.get_dict(),
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={
"completed": False,
"message": "Patch Company record failed",
"data": {},
},
status_code=status.HTTP_200_OK,
)
CompanyPatchEventMethod = CompanyListEventMethods(
action=ActionsSchema(endpoint="/company/list")
)
CompanyCreateEventMethod = CompanyCreateEventMethods(
action=ActionsSchema(endpoint="/company/create")
)
CompanyUpdateEventMethod = CompanyUpdateEventMethods(
action=ActionsSchema(endpoint="/company/update")
)
CompanyListEventMethod = CompanyPatchEventMethods(
action=ActionsSchema(endpoint="/company/patch")
)

View File

@ -0,0 +1,167 @@
from typing import Optional
from fastapi import status
from fastapi.responses import JSONResponse
from validations import (
DepartmentsPydantic,
PatchRecord,
ListOptions,
BaseModelRegular,
)
from databases import Departments
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from api_validations.core_response import return_json_response_from_alchemy
class DepartmentListEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"2cb90331-c1b4-4923-8314-8111326b621a": "department_list",
}
@classmethod
def department_list(cls, list_options: ListOptions, token_dict):
Departments.filter_attr = list_options
records = Departments.filter_active(
*Departments.get_smart_query(smart_query=list_options.query),
Departments.company_id == token_dict.selected_company.company_id
)
return return_json_response_from_alchemy(
response=records, pagination=list_options
)
class AdminUserInsertDepartments(BaseModelRegular):
department_code: str
department_name: str
company_uu_id: Optional[str] = None
department_description: str
parent_department_uu_id: Optional[int] = None
class DepartmentCreateEventMethods(MethodToEvent):
event_type = "CREATE"
__event_keys__ = {
"d8bd3985-7f3b-4267-a74e-d5017e4ea9f8": "super_user_department_create",
}
@classmethod
def super_user_department_create(cls, data: DepartmentsPydantic, token_dict):
data_dict = data.excluded_dump()
data_dict["company_id"] = token_dict.selected_company.company_id
data_dict["company_uu_id"] = token_dict.selected_company.company_uu_id
created_department = Departments.find_or_create(**data_dict)
if created_department.is_found:
return JSONResponse(
content={
"completed": False,
"message": "Company record already exits here is the record",
"data": created_department.get_dict(),
},
status_code=status.HTTP_202_ACCEPTED,
)
return JSONResponse(
content={
"completed": True,
"message": "Create Company record",
"data": created_department.get_dict(),
},
status_code=status.HTTP_200_OK,
)
class DepartmentUpdateEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"4172706f-06c9-4c38-9ac8-59085a72f80a": "department_update",
}
@classmethod
def department_update(
cls, company_uu_id: str, data: DepartmentsPydantic, token_dict
):
find_one_company = Departments.find_one_or_abort(uu_id=company_uu_id)
access_authorized_company = Departments.select_action(
duty_id=getattr(token_dict, "duty_id", 5),
filter_expr=[Departments.id == token_dict.get("")],
)
if access_authorized_company.count:
data_dict = data.excluded_dump()
updated_company = find_one_company.update(**data_dict)
return JSONResponse(
content={
"completed": True,
"message": "Update Company record",
"data": updated_company,
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={"completed": True, "message": "Update Company record", "data": {}},
status_code=status.HTTP_200_OK,
)
class DepartmentPatchEventMethods(MethodToEvent):
event_type = "PATCH"
__event_keys__ = {
"1e272e4f-6c1e-418b-91a7-be8b06c875da": "department_patch",
}
@classmethod
def department_patch(cls, company_uu_id: str, data: PatchRecord, token_dict):
find_one_company = Departments.find_one_or_abort(uu_id=company_uu_id)
access_authorized_company = Departments.select_action(
duty_id=getattr(token_dict, "duty_id", 5),
filter_expr=[Departments.id == find_one_company.id],
)
if access_authorized_company.count:
action = data.excluded_dump()
find_one_company.active = bool(
action.get("active", find_one_company.active)
)
find_one_company.is_confirmed = bool(
action.get("confirm", find_one_company.is_confirmed)
)
find_one_company.deleted = bool(
action.get("delete", find_one_company.deleted)
)
find_one_company.save()
return JSONResponse(
content={
"completed": True,
"message": "Patch Company record completed",
"data": find_one_company.get_dict(),
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={
"completed": False,
"message": "Patch Company record failed",
"data": {},
},
status_code=status.HTTP_200_OK,
)
DepartmentListEventMethod = DepartmentListEventMethods(
action=ActionsSchema(endpoint="/department/list")
)
DepartmentCreateEventMethod = DepartmentCreateEventMethods(
action=ActionsSchema(endpoint="/department/create")
)
DepartmentUpdateEventMethod = DepartmentUpdateEventMethods(
action=ActionsSchema(endpoint="/department/update")
)
DepartmentPatchEventMethod = DepartmentPatchEventMethods(
action=ActionsSchema(endpoint="/department/patch")
)

View File

@ -0,0 +1,199 @@
from fastapi import status
from fastapi.responses import JSONResponse
from validations import InsertDuties, UpdateDuties, SelectDuties
from validations.root_validates import PatchRecord, ListOptions
from databases import Departments, Duty, Duties
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
class DutiesListEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"44b72beb-53a8-407b-a12a-76e74b65794d": "duties_list",
}
@classmethod
def duties_list(cls, list_options: ListOptions, token_dict):
Duties.filter_attr = list_options
records = Duties.filter_active(
*Duties.get_smart_query(smart_query=list_options.query),
Duties.company_id == token_dict.selected_company.company_id
)
return {
"completed": True if records.count else False,
"status": "success",
"data": records.get_dict(),
}
class DutiesGetByUUIDEventMethods(MethodToEvent):
event_type = "GET"
__event_keys__ = {
"30c54cce-3303-4d36-959a-b64e383ae177": "duties_get_by_uuid",
}
@classmethod
def duties_get_by_uuid(cls, data: SelectDuties, token_dict):
duty = Duty.find_one(uu_id=data.duty_uu_id)
if not duty:
return JSONResponse(
content={
"completed": False,
"message": "Duty record is not found",
"data": {},
},
status_code=status.HTTP_404_NOT_FOUND,
)
records = Duties.filter_active(
Duties.duties_id == duty.id,
Duties.company_id == token_dict.selected_company.company_id,
)
if not records.data:
return JSONResponse(
content={
"completed": False,
"message": "Duties record is not found",
"data": {},
},
status_code=status.HTTP_404_NOT_FOUND,
)
return {
"completed": True,
"status": "success",
"data": [record.get_dict() for record in records.data],
}
class DutiesCreateEventMethods(MethodToEvent):
event_type = "CREATE"
__event_keys__ = {
"3524ae42-0825-4af7-be85-7c890a4f65d3": "duties_create",
}
@classmethod
def duties_create(cls, data: InsertDuties, token_dict):
duty = Duty.find_one(uu_id=data.duties_uu_id)
department = Departments.find_one(uu_id=data.department_uu_id)
created_duties = Duties.find_or_create(
company_id=token_dict.selected_company.company_id,
company_uu_id=token_dict.selected_company.company_uu_id,
duties_id=duty.id,
duties_uu_id=str(duty.uu_id),
department_id=department.id,
department_uu_id=str(department.uu_id),
is_confirmed=data.is_confirmed,
)
if data.is_default_duty:
created_duties.update(users_default_duty=created_duties.id)
if not created_duties:
return JSONResponse(
content={
"completed": False,
"message": "Failed to create Duties record",
"data": {},
},
status_code=status.HTTP_400_BAD_REQUEST,
)
return {
"completed": created_duties.is_found,
"message": (
"Create Duties record"
if created_duties.is_found
else "This record is already created"
),
"data": created_duties.get_dict(),
}
class DutiesUpdateEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"3fc77829-f1ee-4511-a2ca-582daa03125b": "duties_update",
}
@classmethod
def duties_update(cls, duties_uu_id: str, data: UpdateDuties, token_dict):
find_one_duties = Duties.find_one_or_abort(uu_id=duties_uu_id)
access_authorized_duties = Duties.select_action(
duty_id=getattr(token_dict, "duty_id", 5),
filter_expr=[Duties.id == find_one_duties.id],
)
if access_authorized_duties.count:
data_dict = data.excluded_dump()
updated_duties = find_one_duties.update(**data_dict)
return {
"completed": True,
"message": "Update Duties record",
"data": updated_duties,
}
return {
"completed": False,
"message": "Update Duties record failed",
"data": {},
}
class DutiesPatchEventMethods(MethodToEvent):
event_type = "PATCH"
__event_keys__ = {
"ca81c6d1-975a-4288-a27b-1069aea84afe": "duties_patch",
}
@classmethod
def duties_patch(cls, duties_uu_id: str, data: PatchRecord, token_dict):
find_one_duties = Duties.find_one_or_abort(uu_id=duties_uu_id)
access_authorized_duties = Duties.select_action(
duty_id=getattr(token_dict, "duty_id", 5),
filter_expr=[Duties.id == find_one_duties.id],
)
if access_authorized_duties.count:
action = data.excluded_dump()
find_one_duties.active = bool(action.get("active", find_one_duties.active))
find_one_duties.is_confirmed = bool(
action.get("confirm", find_one_duties.is_confirmed)
)
find_one_duties.deleted = bool(
action.get("delete", find_one_duties.deleted)
)
find_one_duties.save()
return {
"completed": True,
"message": "Patch Duties record completed",
"data": find_one_duties.get_dict(),
}
return {
"completed": False,
"message": "Patch Duties record failed",
"data": {},
}
DutiesListEventMethod = DutiesListEventMethods(
action=ActionsSchema(endpoint="/duties/list")
)
DutiesGetByUUIDEventMethod = DutiesGetByUUIDEventMethods(
action=ActionsSchema(endpoint="/duties/get_by_duty_uuid")
)
DutiesCreateEventMethod = DutiesCreateEventMethods(
action=ActionsSchema(endpoint="/duties/create")
)
DutiesUpdateEventMethod = DutiesUpdateEventMethods(
action=ActionsSchema(endpoint="/duties/update")
)
DutiesPatchEventMethod = DutiesPatchEventMethods(
action=ActionsSchema(endpoint="/duties/patch")
)

View File

@ -0,0 +1,135 @@
from fastapi import status
from fastapi.responses import JSONResponse
from validations import InsertCompanyDuty
from validations.root_validates import PatchRecord, ListOptions
from databases import Duty
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from api_validations.core_response import return_json_response_from_alchemy
class DutyListEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"23231c7d-4ff2-4b39-b71b-ea350d31fadf": "duty_list",
}
@classmethod
def duty_list(cls, list_options: ListOptions, token_dict):
records = Duty.filter_active(
*Duty.get_smart_query(list_options.query),
)
return return_json_response_from_alchemy(
response=records, pagination=list_options
)
class DutyCreateEventMethods(MethodToEvent):
event_type = "CREATE"
__event_keys__ = {
"c6ea200e-fa17-4393-b390-37f5337c9c65": "duty_create",
}
@classmethod
def duty_create(cls, data: InsertCompanyDuty, token_dict):
created_duty = Duty.find_or_create(**data.excluded_dump())
return JSONResponse(
content={
"completed": True,
"message": "Create Company record",
"data": created_duty.get_dict(),
},
status_code=status.HTTP_200_OK,
)
class DutyUpdateEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"ad952647-bcf8-482d-9e05-b2ee8086483f": "duty_update",
}
@classmethod
def duty_update(cls, company_uu_id: str, data, token_dict):
find_one_company = Duty.find_one_or_abort(uu_id=company_uu_id)
access_authorized_company = Duty.select_action(
duty_id=getattr(token_dict, "duty_id", 5), # ?
filter_expr=[Duty.id == token_dict.get("")],
)
if access_authorized_company.count:
data_dict = data.excluded_dump()
updated_company = find_one_company.update(**data_dict)
return JSONResponse(
content={
"completed": True,
"message": "Update Company record",
"data": updated_company,
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={"completed": True, "message": "Update Company record", "data": {}},
status_code=status.HTTP_200_OK,
)
class DutyPatchEventMethods(MethodToEvent):
event_type = "PATCH"
__event_keys__ = {
"d5c7b5c4-7b4e-4d5b-8e3b-2b9c5f5d0c0b": "duty_patch",
}
@classmethod
def duty_patch(cls, company_uu_id: str, data: PatchRecord, token_dict):
find_one_company = Duty.find_one_or_abort(uu_id=company_uu_id)
access_authorized_company = Duty.select_action(
duty_id=getattr(token_dict, "duty_id", 5),
filter_expr=[Duty.id == find_one_company.id],
)
if access_authorized_company.count:
action = data.excluded_dump()
find_one_company.active = bool(
action.get("active", find_one_company.active)
)
find_one_company.is_confirmed = bool(
action.get("confirm", find_one_company.is_confirmed)
)
find_one_company.deleted = bool(
action.get("delete", find_one_company.deleted)
)
find_one_company.save()
return JSONResponse(
content={
"completed": True,
"message": "Patch Company record completed",
"data": find_one_company.get_dict(),
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={
"completed": False,
"message": "Patch Company record failed",
"data": {},
},
status_code=status.HTTP_200_OK,
)
DutyListEventMethod = DutyListEventMethods(action=ActionsSchema(endpoint="/duty/list"))
DutyCreateEventMethod = DutyCreateEventMethods(
action=ActionsSchema(endpoint="/duty/create")
)
DutyUpdateEventMethod = DutyUpdateEventMethods(
action=ActionsSchema(endpoint="/duty/update")
)
DutyPatchEventMethod = DutyPatchEventMethods(
action=ActionsSchema(endpoint="/duty/patch")
)

View File

@ -0,0 +1,291 @@
from datetime import datetime
from fastapi import status, HTTPException
from fastapi.responses import JSONResponse
from validations import (
InsertEmployees,
BindEmployees2People,
PatchRecord,
ListOptions,
)
from databases import Employees, Staff, People, EmployeeHistory
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from api_validations.core_response import return_json_response_from_alchemy
class EmployeeListEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"cb677c92-6b05-4122-af5c-12766fae8095": "employee_list",
}
@classmethod
def employee_list(cls, list_options: ListOptions, token_dict):
Employees.filter_attr = list_options
records = Employees.filter_active(
*Employees.get_smart_query(smart_query=list_options.query),
Employees.company_id == token_dict.selected_company.company_id,
)
return return_json_response_from_alchemy(
response=records, pagination=list_options
)
class EmployeeCreateEventMethods(MethodToEvent):
event_type = "CREATE"
__event_keys__ = {
"1e1632c3-bb0e-46a5-8e45-da3f6d88ac43": "employee_create",
}
@classmethod
def employee_create(cls, data: InsertEmployees, token_dict):
person = People.find_one(uu_id=data.people_uu_id)
staff = Staff.find_one(uu_id=data.staff_uu_id)
if not staff:
return JSONResponse(
content={
"completed": False,
"message": "Staff record not found",
"data": {},
},
status_code=status.HTTP_404_NOT_FOUND,
)
created_employee = Employees.create(
staff_id=staff.id,
staff_uu_id=str(staff.uu_id),
people_id=person.id if person else None,
people_uu_id=str(person.uu_id) if person else None,
)
return JSONResponse(
content={
"completed": True if not created_employee.is_found else False,
"message": "Create Employee record",
"data": created_employee.get_dict(),
},
status_code=status.HTTP_200_OK,
)
class EmployeeUpdateEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"9015a076-d78c-463d-9474-ea343a125fb8": "employee_update",
}
@classmethod
def employee_update(cls, employee_uu_id: str, data: PatchRecord, token_dict):
find_one_employee = Employees.find_one_or_abort(uu_id=employee_uu_id)
access_authorized_employee = Employees.select_action(
employee_id=getattr(token_dict, "employee_id", 5),
filter_expr=[Employees.id == token_dict.get("")],
)
if access_authorized_employee.count:
data_dict = data.excluded_dump()
updated_employee = find_one_employee.update(**data_dict)
return JSONResponse(
content={
"completed": True,
"message": "Update Employee record",
"data": updated_employee,
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={
"completed": False,
"message": "Update Employee record",
"data": {},
},
status_code=status.HTTP_200_OK,
)
class EmployeePatchEventMethods(MethodToEvent):
event_type = "PATCH"
__event_keys__ = {
"8446ce0b-9310-4b9f-93e2-61f56a9dacd1": "employee_patch",
}
@classmethod
def employee_patch(cls, employee_uu_id: str, data: PatchRecord, token_dict):
find_one_employee = Employees.find_one_or_abort(uu_id=employee_uu_id)
access_authorized_employee = Employees.select_action(
employee_id=getattr(token_dict, "employee_id", 5),
filter_expr=[Employees.id == find_one_employee.id],
)
if access_authorized_employee.count:
action = data.excluded_dump()
find_one_employee.active = bool(
action.get("active", find_one_employee.active)
)
find_one_employee.is_confirmed = bool(
action.get("confirm", find_one_employee.is_confirmed)
)
find_one_employee.deleted = bool(
action.get("delete", find_one_employee.deleted)
)
find_one_employee.save()
return JSONResponse(
content={
"completed": True,
"message": "Patch Employee record completed",
"data": find_one_employee.get_dict(),
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={
"completed": False,
"message": "Patch Employee record failed",
"data": {},
},
status_code=status.HTTP_200_OK,
)
class Employee2PeopleEmployEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"5eb04057-7a74-4555-b2c6-14eda32dae89": "company_employee_employ",
}
@classmethod
def company_employee_employ(cls, data: BindEmployees2People, token_dict):
selected_staff = Staff.find_one(uu_id=data.staff_uu_id)
selected_people = People.find_one(uu_id=data.people_uu_id)
if not selected_staff:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Staff record not found",
)
if not selected_people:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="People record not found",
)
find_one_employee = Employees.filter_active(
Employees.staff_id == selected_staff.id,
Employees.people_id == None,
).data
staff_name_upper = str(selected_staff.staff_name).upper()
if not find_one_employee:
return JSONResponse(
content={
"completed": False,
"message": f"There is no space for new Employee for given staff : {staff_name_upper}",
"data": {},
},
status_code=status.HTTP_406_NOT_ACCEPTABLE,
)
if not data.expiry_starts:
data.expiry_starts = datetime.now()
find_one_employee = find_one_employee[0].update(
people_id=selected_people.id,
expiry_starts=data.expiry_starts,
**token_dict.update_creds,
)
return JSONResponse(
content={
"completed": True,
"message": "Get Employee to People record",
"data": find_one_employee.get_dict(),
},
status_code=status.HTTP_200_OK,
)
class Employee2PeopleFireEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"caf914fa-0899-4b0b-a85a-3d40fdaa06a5": "company_employee_fire",
}
@classmethod
def company_employee_fire(cls, data: BindEmployees2People, token_dict):
selected_people = People.find_one(uu_id=data.people_uu_id)
if not selected_people:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="People record not found",
)
find_one_employee: Employees = Employees.find_one(people_id=selected_people.id)
if not find_one_employee:
return JSONResponse(
content={
"completed": False,
"message": "Employee record not found for given People",
"data": {},
},
status_code=status.HTTP_404_NOT_FOUND,
)
find_one_employee = find_one_employee.update(
people_id=None, **token_dict.update_creds
)
if not find_one_employee.people_id:
employee_history = EmployeeHistory.find_or_create(
staff_id=find_one_employee.staff_id,
expiry_ends=data.expiry_ends,
people_id=selected_people.id,
created_by_id=find_one_employee.created_by_id,
updated_by_id=find_one_employee.updated_by_id,
confirmed_by_id=find_one_employee.confirmed_by_id,
replication_id=find_one_employee.replication_id,
created_by=find_one_employee.created_by,
updated_by=find_one_employee.updated_by,
confirmed_by=find_one_employee.confirmed_by,
active=find_one_employee.active,
is_confirmed=find_one_employee.is_confirmed,
deleted=find_one_employee.deleted,
expiry_starts=find_one_employee.expiry_starts,
is_notification_send=find_one_employee.is_notification_send,
cryp_uu_id=find_one_employee.cryp_uu_id,
)
return JSONResponse(
content={
"completed": True,
"message": "Employee is fired from Staff",
"data": find_one_employee.get_dict(),
},
status_code=status.HTTP_200_OK,
)
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Employee record not found for given People",
)
EmployeeListEventMethod = EmployeeListEventMethods(
action=ActionsSchema(endpoint="/employee/list")
)
EmployeeCreateEventMethod = EmployeeCreateEventMethods(
action=ActionsSchema(endpoint="/employee/create")
)
EmployeeUpdateEventMethod = EmployeeUpdateEventMethods(
action=ActionsSchema(endpoint="/employee/update")
)
EmployeePatchEventMethod = EmployeePatchEventMethods(
action=ActionsSchema(endpoint="/employee/patch")
)
Employee2PeopleEmployEventMethod = Employee2PeopleEmployEventMethods(
action=ActionsSchema(endpoint="/employee/employ")
)
Employee2PeopleFireEventMethod = Employee2PeopleFireEventMethods(
action=ActionsSchema(endpoint="/employee/fire")
)

View File

@ -0,0 +1,148 @@
from fastapi import status
from fastapi.responses import JSONResponse
from fastapi.exceptions import HTTPException
from validations import (
InsertStaff,
SelectStaff,
PatchRecord,
ListOptions,
)
from databases import Staff, Duties
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from api_validations.core_response import return_json_response_from_alchemy
class StaffListEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"8984a519-99bf-4f25-8f34-2e1aebba468c": "staff_list",
}
@classmethod
def staff_list(cls, list_options: ListOptions, token_dict):
Staff.filter_attr = list_options
records = Staff.filter_active(
*Staff.get_smart_query(smart_query=list_options.query),
)
return return_json_response_from_alchemy(
response=records, pagination=list_options
)
class StaffCreateEventMethods(MethodToEvent):
event_type = "CREATE"
__event_keys__ = {
"8f619257-19fd-404f-b713-7392c588dc36": "staff_create",
}
@classmethod
def staff_create(cls, data: InsertStaff, token_dict: EmployeeTokenObject):
data_dict = data.excluded_dump()
duties = Duties.find_one(uu_id=data.duties_uu_id)
if not duties:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Duties not found",
)
data_dict["duties_id"] = duties.id
created_duty = Staff.find_or_create(**data_dict)
return JSONResponse(
content={
"completed": True,
"message": "Create Staff record",
"data": created_duty.get_dict(),
},
status_code=status.HTTP_200_OK,
)
class StaffGetByUUIDEventMethods(MethodToEvent):
event_type = "GET"
__event_keys__ = {
"7724cfbb-c0ee-4261-959b-61b84e88a34f": "staff_get_by_uu_id",
}
@classmethod
def staff_get_by_uu_id(cls, data: SelectStaff, token_dict):
if data.duties_uu_id:
duties_id = Duties.find_one(uu_id=data.duties_uu_id)
selected_staffs = Staff.filter_active(
Staff.duties_id == duties_id.id,
)
return JSONResponse(
content={
"completed": True,
"message": "Staff records are listed",
"data": [
selected_staff.get_dict()
for selected_staff in selected_staffs.data
],
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={
"completed": False,
"message": "Get Staff record failed",
"data": {},
},
status_code=status.HTTP_202_ACCEPTED,
)
class StaffUpdateEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"5329f35d-ff9d-4656-a831-ba9c8204e483": "staff_update",
}
@classmethod
def staff_update(cls, staff_uu_id: str, data, token_dict):
return JSONResponse(
content={"completed": True, "message": "Update Staff record", "data": {}},
status_code=status.HTTP_200_OK,
)
class StaffPatchEventMethods(MethodToEvent):
event_type = "PATCH"
__event_keys__ = {
"b1cd7c0a-1458-472b-894f-3adc857c8512": "staff_patch",
}
@classmethod
def staff_patch(cls, staff_uu_id: str, data: PatchRecord, token_dict):
return JSONResponse(
content={
"completed": False,
"message": "Patch Staff record failed",
"data": {},
},
status_code=status.HTTP_200_OK,
)
StaffListEventMethod = StaffListEventMethods(
action=ActionsSchema(endpoint="/staff/list")
)
StaffCreateEventMethod = StaffCreateEventMethods(
action=ActionsSchema(endpoint="/staff/create")
)
StaffGetByUUIDEventMethod = StaffGetByUUIDEventMethods(
action=ActionsSchema(endpoint="/staff/get_by_duties_uu_id")
)
StaffUpdateEventMethod = StaffUpdateEventMethods(
action=ActionsSchema(endpoint="/staff/update")
)
StaffPatchEventMethod = StaffPatchEventMethods(
action=ActionsSchema(endpoint="/staff/patch")
)

View File

@ -0,0 +1,220 @@
import typing
from fastapi import status, HTTPException
from fastapi.responses import JSONResponse
from databases import (
Build,
BuildDecisionBook,
Companies,
OccupantTypes,
)
from validations import (
InsertDecisionBook,
ListOptions,
)
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from api_validations.core_response import return_json_response_from_alchemy
from api_library.date_time_actions.date_functions import DateTimeLocal
class DecisionBookListEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"5c10d6ae-2aee-4243-a7c3-94826d028d13": "building_decision_book_list",
}
@classmethod
def building_decision_book_list(
cls,
list_options: ListOptions,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
records = []
if isinstance(token_dict, EmployeeTokenObject):
build_id_list_query = Build.select_action(
employee_id=token_dict.selected_company.employee_id
)
build_id_list = build_id_list_query.all()
if not build_id_list:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"No building is match with given Employee UUID {token_dict.selected_company.employee_uu_id}",
)
records = BuildDecisionBook.filter_active(
BuildDecisionBook.build_id.in_([build.id for build in build_id_list]),
*BuildDecisionBook.get_smart_query(list_options.query),
)
elif isinstance(token_dict, OccupantTokenObject):
records = BuildDecisionBook.filter_active(
BuildDecisionBook.build_id == token_dict.selected_occupant.build_id,
*BuildDecisionBook.get_smart_query(list_options.query),
)
return return_json_response_from_alchemy(
response=records, pagination=list_options
)
class DecisionBookCreateEventMethods(MethodToEvent):
event_type = "CREATE"
__event_keys__ = {
"0a68cb44-271a-4829-81f6-cd99a5f326b4": "building_decision_book_create",
}
@classmethod
def building_decision_book_create(
cls,
data: InsertDecisionBook,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
data_dict = data.excluded_dump()
if isinstance(token_dict, EmployeeTokenObject):
Build.pre_query = Build.select_action(
employee_id=token_dict.selected_company.employee_id
)
build = Build.filter_active(
Build.uu_id == data.build_uu_id,
)
if not build.data:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Emloyee UUID {token_dict.selected_company.employee_uu_id} has no build with given UUID {data_dict.get('build_uu_id')}",
)
data_dict["build_id"] = build.data[0].id
if data.resp_company_uu_id:
Companies.pre_query = Companies.select_action(
duty_id_list=[
token_dict.selected_company.duty_id,
token_dict.selected_company.bulk_duties_id,
]
)
company = Companies.filter_active(
Companies.uu_id == data.resp_company_uu_id
)
if not company.data:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Duty UUID {token_dict.selected_company.duty_uu_id} has no company with given UUID {data_dict.get('resp_company_uu_id')}",
)
data_dict["resp_company_id"] = company.data[0].id
data_dict["resp_company_uu_id"] = str(company.data[0].uu_id)
build_object = build.data[0]
decision_period_date = DateTimeLocal.get(build_object.decision_period_date)
data_dict["expiry_starts"] = DateTimeLocal.get(
DateTimeLocal.now().date().year,
int(decision_period_date.date().month),
int(decision_period_date.date().day),
)
data_dict["expiry_ends"] = str(
data_dict["expiry_starts"].shift(years=1, days=-1)
)
data_dict["expiry_starts"] = str(data_dict["expiry_starts"])
build_decision_book = BuildDecisionBook.find_or_create(**data_dict)
return JSONResponse(
status_code=status.HTTP_200_OK,
content=dict(
message="Decision Book has created",
completed=True,
data=build_decision_book.get_dict(),
),
)
elif isinstance(token_dict, OccupantTokenObject):
occupant_manager = OccupantTypes.find_one(
occupant_category_type="BU", occupant_code="BU-MNG"
)
if not token_dict.selected_occupant.occupant_type_id == occupant_manager.id:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Only Build Manager can create decision book",
)
occupant_build = Build.find_one(id=token_dict.selected_occupant.build_id)
occupant_company = Companies.find_one(
id=token_dict.selected_occupant.responsible_company_id
)
data_dict["build_id"] = occupant_build.id
data_dict["build_uu_id"] = str(occupant_build.uu_id)
data_dict["resp_company_id"] = occupant_company.id
data_dict["resp_company_uu_id"] = str(occupant_company.uu_id)
decision_period_date = DateTimeLocal.get(
occupant_build.decision_period_date
)
data_dict["expiry_starts"] = DateTimeLocal.get(
DateTimeLocal.now().date().year,
int(decision_period_date.date().month),
int(decision_period_date.date().day),
)
data_dict["expiry_ends"] = str(
data_dict["expiry_starts"].shift(years=1, days=-1)
)
data_dict["expiry_starts"] = str(data_dict["expiry_starts"])
build_decision_book = BuildDecisionBook.find_or_create(**data_dict)
return JSONResponse(
status_code=status.HTTP_200_OK,
content=dict(
message="Decision Book has created",
completed=True,
data=build_decision_book.get_dict(),
),
)
class DecisionBookUpdateEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"6bc7035c-3b53-4c0a-8cc9-1ec9c6af1e29": "building_decision_book_update",
}
@classmethod
def building_decision_book_update(cls, data: InsertDecisionBook, token_dict: dict):
return
class DecisionBookPatchEventMethods(MethodToEvent):
event_type = "PATCH"
__event_keys__ = {
"7b58ed84-9a65-4588-994d-30df8366b050": "building_decision_book_patch",
}
@classmethod
def building_decision_book_patch(cls, data: InsertDecisionBook, token_dict: dict):
return
class DecisionBookApprovalEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"fc745142-3437-4ca2-89fa-c5a3e2b5c6c2": "building_decision_book_approval",
}
@classmethod
def building_decision_book_approval(cls, data, token_dict):
return
DecisionBookListEventMethod = DecisionBookListEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/list")
)
DecisionBookCreateEventMethod = DecisionBookCreateEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/create")
)
DecisionBookUpdateEventMethod = DecisionBookUpdateEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/update")
)
DecisionBookPatchEventMethod = DecisionBookPatchEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/patch")
)
DecisionBookApprovalEventMethod = DecisionBookApprovalEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/approval")
)

View File

@ -0,0 +1,473 @@
import typing
from fastapi import status, HTTPException
from fastapi.responses import JSONResponse
from databases import (
Build,
BuildParts,
BuildDecisionBook,
BuildDecisionBookItems,
BuildDecisionBookPerson,
BuildDecisionBookPayments,
BuildDecisionBookProjects,
BuildDecisionBookProjectPerson,
ApiEnumDropdown,
OccupantTypes,
Companies,
BuildLivingSpace,
)
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from api_validations.core_response import return_json_response_from_alchemy
from api_library.date_time_actions.date_functions import DateTimeLocal
from validations import (
InsertBuildDecisionBookItems,
ListDecisionBook,
)
class DecisionBookDecisionBookItemsListEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"eb36de59-8268-4d96-80b6-5d01c12bf0b1": "building_decision_book_items_list",
}
@classmethod
def building_decision_book_items_list(
cls,
data: ListDecisionBook,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
decision_book = BuildDecisionBook.find_one(uu_id=data.build_decision_book_uu_id)
if not decision_book:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"No Decision Book is match with given UUID {data.build_decision_book_uu_id}",
)
if isinstance(token_dict, EmployeeTokenObject):
Build.pre_query = Build.select_action(
employee_id=token_dict.selected_company.employee_id,
filter_expr=[
Build.uu_id == decision_book.build_decision_book_uu_id,
],
)
reachable_building = Build.filter_active()
if not reachable_building.data:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"No building is match with given Employee UUID {token_dict.selected_company.employee_uu_id}",
)
Companies.pre_query = Companies.select_action(
duty_id_list=[
token_dict.selected_company.duty_id,
token_dict.selected_company.bulk_duties_id,
],
filter_expr=[Companies.id == decision_book.company_id],
)
reachable_companies = Companies.filter_active()
if not reachable_companies.data:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"No company is match with given Employee UUID {token_dict.selected_company.employee_uu_id}",
)
records = BuildDecisionBookItems.filter_active(
BuildDecisionBookItems.build_decision_book_id == decision_book.id
)
return JSONResponse(
status_code=status.HTTP_200_OK,
content=dict(
total_count=records.count,
count=len(records.data),
message=f"Decision Book Items has found from given Decision Book UUID {data.build_decision_book_uu_id}",
completed=True,
data=[record.get_dict() for record in records.data],
),
)
else:
# BuildDecisionBookItems.pre_query = BuildDecisionBookItems.select_action(
# occupant_id=token_dict.occupant_list["occupant_id"]
# )
# records = BuildDecisionBookItems.filter_active(
# *BuildDecisionBookItems.get_smart_query(list_options.query)
# )
# return return_json_response_from_alchemy(response=records, pagination=list_options)
return
class DecisionBookDecisionBookItemsCreateEventMethods(MethodToEvent):
event_type = "CREATE"
__event_keys__ = {
"dce10509-0da5-46fb-af3c-a81d54d5481c": "building_decision_book_items_create",
}
@classmethod
def iterate_over_build_parts(
cls,
build_parts_list,
payment_types,
local_date,
end_date,
unit_price,
unit_type,
book_payment_dict,
unit_price_is_fixed
):
start_date, payment_return_dict = local_date, {}
for build_part_single in build_parts_list:
local_date = start_date
while local_date.is_between(start_date, end_date, "[]"):
local_date = DateTimeLocal.find_last_day_of_month(local_date)
payment_amount = unit_price
if not unit_price_is_fixed:
unit_amount = str(build_part_single.due_part_key).replace(" ", "")
unit_amount = unit_amount.replace(str(unit_type).upper(), "")
payment_amount = abs(unit_price * float(unit_amount)) * -1
payment_amount = -1 * (abs(payment_amount) + (50 - float(abs(payment_amount)) % 50))
BuildDecisionBookPayments.create(
build_parts_id=build_part_single.id,
build_parts_uu_id=str(build_part_single.uu_id),
payment_amount=payment_amount,
payment_types_id=payment_types.id,
payment_types_uu_id=str(payment_types.uu_id),
process_date=str(local_date),
process_date_m=int(local_date.month),
process_date_y=int(local_date.year),
period_time=f"{local_date.year}-{str(local_date.month).zfill(2)}",
**book_payment_dict
)
local_date = local_date.shift(days=2)
part_key = str(build_part_single.due_part_key).upper()
if part_key not in payment_return_dict:
payment_return_dict[part_key] = payment_amount
return payment_return_dict
@classmethod
def create_payment_records_for_each_build_part(
cls,
data_info_type,
build_id,
unit_price,
unit_type,
decision_book,
decision_book_item,
unit_price_is_fixed,
currency,
debit_start_date: str = None,
debit_end_date: str = None,
):
build_parts_list = BuildParts.filter_active(
BuildParts.human_livable == True,
BuildParts.build_id == build_id,
)
book_payment_dict = dict(
payment_plan_time_periods=str(data_info_type.key),
build_decision_book_item_id=decision_book_item.id,
build_decision_book_item_uu_id=str(decision_book_item.uu_id),
is_confirmed=True,
currency=currency,
)
payment_types = ApiEnumDropdown.get_debit_search(search_debit="DT-D")
if data_info_type.key == "BDT-D":
local_date = DateTimeLocal.get(DateTimeLocal.get(decision_book.expiry_starts).date())
end_date = DateTimeLocal.get(DateTimeLocal.get(decision_book.expiry_ends).date())
return cls.iterate_over_build_parts(
build_parts_list=build_parts_list.data,
payment_types=payment_types,
local_date=local_date,
end_date=end_date,
unit_price=unit_price,
unit_type=unit_type,
unit_price_is_fixed=unit_price_is_fixed,
book_payment_dict=book_payment_dict,
)
elif data_info_type.key == "BDT-A":
local_date = DateTimeLocal.get(DateTimeLocal.get(debit_start_date).date())
end_date = DateTimeLocal.get(DateTimeLocal.get(debit_end_date).date())
return cls.iterate_over_build_parts(
build_parts_list=build_parts_list.data,
payment_types=payment_types,
local_date=local_date,
end_date=end_date,
unit_price=unit_price,
unit_type=unit_type,
unit_price_is_fixed=unit_price_is_fixed,
book_payment_dict=book_payment_dict,
)
elif data_info_type.key == "BDT-R" or data_info_type.key == "BDT-L":
local_date = DateTimeLocal.get(DateTimeLocal.get(debit_start_date).date())
end_date = DateTimeLocal.get(DateTimeLocal.get(debit_end_date).date())
decision_date = DateTimeLocal.get(decision_book.expiry_starts).date()
meeting_date = DateTimeLocal.get(decision_book.meeting_date).date()
already_book_projects = BuildDecisionBookProjects.filter_all(
BuildDecisionBookProjects.build_decision_book_id==decision_book.id,
BuildDecisionBookProjects.project_type==f"{decision_book.decision_type}_{data_info_type.key}",
)
management_room = BuildParts.find_one(
build_id=build_id, part_no=0, active=True, is_confirmed=True
)
occupant_man = OccupantTypes.find_one(
occupant_code="MT-VPR", occupant_category_type="MT"
)
manager_living_space = BuildLivingSpace.filter_by_active(
build_parts_id=management_room.id, occupant_type=occupant_man.id,
)
if not manager_living_space.data:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"{occupant_man.occupant_description} Living Space is not found. Check manager living space and try again",
)
already_book_project_count = already_book_projects.count + 1
manager_living_space = manager_living_space.get(1)
book_project_dict = dict(
project_no=f"{data_info_type.key}_{decision_date.year}_{already_book_project_count}",
project_name=f"{str(meeting_date)}_{decision_book.decision_type} Project {already_book_projects.count + 1}",
project_start_date=str(local_date),
project_stop_date=str(end_date),
project_type=f"{decision_book.decision_type}_{data_info_type.key}",
project_note=f"Fill later",
build_decision_book_id=decision_book.id,
build_decision_book_uu_id=str(decision_book.uu_id),
build_decision_book_item_id=decision_book_item.id,
build_decision_book_item_uu_id=str(decision_book_item.uu_id),
project_response_living_space_id=manager_living_space.id,
project_response_living_space_uu_id=str(manager_living_space.uu_id),
)
book_project_created = BuildDecisionBookProjects.find_or_create(**book_project_dict)
if not book_project_created.is_found:
decision_book_item.update(
item_comment=f"{book_project_created.project_no}_{book_project_created.project_name} "
f"is assigned to {occupant_man.occupant_description}"
)
project_lead = ApiEnumDropdown.find_one(
key="PTT-LDR", enum_class="ProjectTeamTypes"
)
project_person = BuildDecisionBookProjectPerson.find_or_create(
build_decision_book_project_id=book_project_created.id,
build_decision_book_project_uu_id=str(book_project_created.uu_id),
living_space_id=manager_living_space.id,
living_space_uu_id=str(manager_living_space.uu_id),
project_team_type_id=project_lead.id,
project_team_type_uu_id=str(project_lead.uu_id),
)
elif data_info_type.key == "BDT-SF":
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="BDT-SF is not implemented yet. Check info type and try again",
)
else:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Payment Info Type is not valid. Check payment type and try again",
)
@classmethod
def building_decision_book_items_create(
cls,
data: InsertBuildDecisionBookItems,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
if isinstance(token_dict, EmployeeTokenObject):
raise HTTPException(
status_code=status.HTTP_406_NOT_ACCEPTABLE,
detail="No employee can reach this event. An notification is send to admin about event registration",
)
elif isinstance(token_dict, OccupantTokenObject):
data_dict = data.dump()
occupant_wrt = OccupantTypes.find_one(
occupant_code="MT-WRT", occupant_category_type="MT"
)
if token_dict.selected_occupant.occupant_type_id != occupant_wrt.id:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Only WRITER can create decision book item. Check your occupant type and try again",
)
decision_book_person = BuildDecisionBookPerson.find_one(token=data.token)
decision_book = BuildDecisionBook.find_one(
id=decision_book_person.build_decision_book_id
)
BuildDecisionBookItems.check_meeting_is_valid_to_start_add_attendance(
decision_book=decision_book,
token_dict=token_dict,
)
book_items = BuildDecisionBookItems.filter_active(
BuildDecisionBookItems.build_decision_book_id == decision_book.id,
)
data_dict["item_order"] = int(book_items.count) + 1
data_dict["build_decision_book_id"] = decision_book.id
data_dict["build_decision_book_uu_id"] = str(decision_book.uu_id)
data_dict["is_confirmed"] = True
data_info_types, data_info_type = ApiEnumDropdown.due_type_search(), None
for info_type in data_info_types:
if str(info_type.uu_id) == data_dict["info_type_uu_id"]:
data_info_type = info_type
break
if not data_info_type:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Info Type is not valid. Check info type and try again",
)
if str(data_info_type.key).upper() in ["BDT-A", "BDT-R", "BDT-L", "BDT-SF"]:
if not data_dict["debit_start_date"] or not data_dict["debit_end_date"]:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Debit Start Date and Debit End Date is required for this payment type. "
"Check debit start date and debit end date and try again",
)
data_dict["info_type_id"] = data_info_type.id
data_dict["info_type_uu_id"] = str(data_info_type.uu_id)
unit_price, unit_type = float(data_dict["unit_price"]), str(data_dict["unit_type"])
debit_start_date, debit_end_date = data_dict["debit_start_date"], data_dict["debit_end_date"]
currency = data_dict["currency"]
del (
data_dict["token"],
data_dict["unit_price"],
data_dict["unit_type"],
data_dict["unit_price_is_fixed"],
data_dict["debit_start_date"],
data_dict["debit_end_date"],
data_dict["currency"]
)
if new_decision_book_item := BuildDecisionBookItems.find_or_create(**data_dict):
if new_decision_book_item.is_found:
return JSONResponse(
status_code=status.HTTP_200_OK,
content=dict(
message=f"Decision Book Item is already exist for given Decision Book UUID {decision_book.uu_id}",
completed=True,
data=new_decision_book_item.get_dict(),
),
)
if created_payment_records_dict := cls.create_payment_records_for_each_build_part(
data_info_type=data_info_type,
build_id=decision_book.build_id,
unit_price=unit_price,
unit_type=unit_type.upper(),
decision_book=decision_book,
decision_book_item=new_decision_book_item,
unit_price_is_fixed=data.unit_price_is_fixed,
debit_start_date=debit_start_date,
debit_end_date=debit_end_date,
currency=currency
):
if data_info_type.key == "BDT-A" or data_info_type.key == "BDT-D":
if data_info_type.key == "BDT-D":
item_comment = "Regular Payment Plan : "
else:
item_comment = "Additional Payment Plan : "
for key, value in dict(sorted(
created_payment_records_dict.items(),
key=lambda x: x[1],
reverse=True
)).items():
item_comment += f" {key} | {abs(float(value))} {currency}, "
item_comment = item_comment[:-2]
new_decision_book_item.update(
item_comment=item_comment
)
new_decision_book_item.update(is_payment_created=True)
return JSONResponse(
status_code=status.HTTP_200_OK,
content=dict(
message=f"Decision Book Item has created for given Decision Book UUID {decision_book.uu_id}",
completed=True,
data=new_decision_book_item.get_dict(),
),
)
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Decision Book Item is not created. Check info type and info no and try again. Unique constraint index is implemented for info type and info no",
)
class DecisionBookDecisionBookItemsUpdateEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"f0fdfe1b-806b-4175-ad50-a1a165c0dfb7": "building_decision_book_items_update",
}
@classmethod
def building_decision_book_items_update(
cls,
data: InsertBuildDecisionBookItems,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
return
class DecisionBookDecisionBookItemsPatchEventMethods(MethodToEvent):
event_type = "PATCH"
__event_keys__ = {
"42328809-b516-477b-82cc-2d6fadf28843": "building_decision_book_items_patch",
}
@classmethod
def building_decision_book_items_patch(
cls,
data: InsertBuildDecisionBookItems,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
return
DecisionBookDecisionBookItemsListEventMethod = (
DecisionBookDecisionBookItemsListEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/items/list")
)
)
DecisionBookDecisionBookItemsCreateEventMethod = (
DecisionBookDecisionBookItemsCreateEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/items/create")
)
)
DecisionBookDecisionBookItemsUpdateEventMethod = (
DecisionBookDecisionBookItemsUpdateEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/items/update")
)
)
DecisionBookDecisionBookItemsPatchEventMethod = (
DecisionBookDecisionBookItemsPatchEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/items/patch")
)
)
# if data.info_no is None:
# data_dict["info_no"] = data_dict["item_order"]
# elif data.occupant_types_uu_id:
# data_dict["info_type"] = None
# if occupant_type := OccupantTypes.find_one(
# uu_id=data.occupant_types_uu_id
# ):
# if (
# str(data.occupant_types_uu_id)
# in OccupantTypes.get_manager_occupant_type()
# ):
# if BuildDecisionBookItems.find_one(
# build_decision_book_id=decision_book.id,
# occupant_type=occupant_type.id,
# ):
# raise HTTPException(
# status_code=status.HTTP_400_BAD_REQUEST,
# detail="This Occupant Type is already exist for given Decision Book UUID. Check occupant type and try again",
# )
# data_dict["occupant_type"] = occupant_type.id
# data_dict["occupant_type_uu_id"] = str(occupant_type.uu_id)

View File

@ -0,0 +1,5 @@
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
class DecisionBookDecisionBookItemsDebitsEvents(MethodToEvent): ...

View File

@ -0,0 +1,443 @@
import typing
from fastapi import status, HTTPException
from fastapi.responses import JSONResponse
from databases import (
BuildDecisionBook,
BuildDecisionBookPerson,
BuildDecisionBookInvitations,
Users,
BuildLivingSpace,
BuildParts,
BuildDecisionBookPersonOccupants,
People,
OccupantTypes,
)
from api_validations import (
ListOptions,
RemoveDecisionBookPerson,
DecisionBookDecisionBookInvitationsAttend,
DecisionBookDecisionBookInvitationsUpdate,
DecisionBookDecisionBookInvitationsAssign,
)
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from api_validations.core_response import return_json_response_from_alchemy
class DecisionBookPersonListEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"ea324dc0-3b08-4896-9040-7fa0401a176f": "building_decision_book_person_list",
}
@classmethod
def building_decision_book_person_list(
cls, data: ListOptions, token_dict: EmployeeTokenObject
):
return
class DecisionBookPersonAddEventMethods(MethodToEvent):
event_type = "CREATE"
__event_keys__ = {
"e346f720-880b-4b07-93d6-9ac76fbbaa33": "building_decision_book_person_add",
}
@classmethod
def building_decision_book_person_add(
cls,
data: DecisionBookDecisionBookInvitationsUpdate,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
if isinstance(token_dict, EmployeeTokenObject):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Employee cannot create decision book invitations",
)
elif isinstance(token_dict, OccupantTokenObject):
decision_book = BuildDecisionBook.find_one(
uu_id=data.build_decision_book_uu_id
)
if not decision_book:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"No Decision Book is match with given UUID {data.build_decision_book_uu_id}",
)
manager_occupant_type = OccupantTypes.find_or_abort(
occupant_code="BU-MNG", occupant_category_type="BU"
)
if (
not manager_occupant_type.uu_id
== token_dict.selected_occupant.occupant_type_uu_id
):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Only Build Manager can update the invitation",
)
assign_occupant_type = OccupantTypes.find_or_abort(
uu_id=data.occupant_type_uu_id,
occupant_category_type="MT",
)
if not assign_occupant_type:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Occupant type must be a Meeting Type {data.occupant_type_uu_id} is not a MT type occupant",
)
manger_book_person = BuildDecisionBookPerson.find_one(
token=data.token,
build_decision_book_uu_id=data.build_decision_book_uu_id,
is_confirmed=True,
active=True,
)
if not manger_book_person:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Manager person not found. Please check token",
)
book_invite = BuildDecisionBookInvitations.find_one(
id=manger_book_person.invite_id,
build_id=token_dict.selected_occupant.build_id,
)
if not book_invite:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Invitation not found. Please check token",
)
selected_book_person = BuildDecisionBookPerson.find_one(
invite_id=book_invite.id,
person_uu_id=data.person_uu_id,
is_confirmed=True,
active=True,
)
if not selected_book_person:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Selected person is not in the invitation list. Please check {data.person_uu_id}",
)
selected_book_person.update(
occupant_type=assign_occupant_type.id,
occupant_type_uu_id=str(assign_occupant_type.uu_id),
)
return JSONResponse(
status_code=status.HTTP_200_OK,
content={
"completed": True,
"message": "Invitation is updated",
"data": selected_book_person.get_dict(),
},
)
class DecisionBookPersonRemoveEventMethods(MethodToEvent):
event_type = "DELETE"
__event_keys__ = {
"30588869-04cd-48ea-ad00-0e4f8dd7f735": "building_decision_book_people_remove",
}
@classmethod
def building_decision_book_people_remove(
cls, data: RemoveDecisionBookPerson, token_dict: EmployeeTokenObject
):
return
class DecisionBookPersonAttendEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"bdcba521-0116-441c-ace1-84c5b68c86c7": "decision_book_invitations_attend",
}
@classmethod
def decision_book_invitations_attend(
cls,
data: DecisionBookDecisionBookInvitationsAttend,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
if isinstance(token_dict, EmployeeTokenObject):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Employee cannot create decision book invitations",
)
token_user = Users.find_one(id=token_dict.user_id)
invitation_person = BuildDecisionBookPerson.find_one(
token=data.token, active=True, is_confirmed=True
)
if not invitation_person:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Invitation for the this specific user is not found. Please check token",
)
# is_token_valid = token_dict.person_id == invitation_person.person_id
# if not invitation_person.vicarious_person_id:
# if not invitation_person or not is_token_valid:
# raise HTTPException(
# status_code=status.HTTP_404_NOT_FOUND,
# detail=f"Invitation for the user {token_user.email} is not valid. Please check token",
# )
# todo check if vicarious person is valid
invitation = BuildDecisionBookInvitations.find_one(
id=invitation_person.invite_id,
build_id=token_dict.selected_occupant.build_id,
)
if not invitation:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Invitation not found. Please check invitation uuid : {invitation.uu_id}",
)
invitation_person.update(
is_attending=bool(data.is_attend), vicarious_person_id=None
)
return JSONResponse(
status_code=status.HTTP_200_OK,
content={
"completed": True,
"message": "Attendance is updated. Thank you for your response",
"data": {
"is_attending": bool(data.is_attend),
"user_uuid": str(token_user.uu_id),
"invitation_uuid": str(invitation.uu_id),
},
},
)
class DecisionBookPersonAssignOccupantEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"c0b65098-9c79-4212-b1d0-c7e7836cf141": "decision_book_invitations_assign_occupant",
}
@classmethod
def decision_book_invitations_assign_occupant(
cls,
data: DecisionBookDecisionBookInvitationsAssign,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
if isinstance(token_dict, EmployeeTokenObject):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Employee cannot create decision book invitations",
)
book_person_manager = BuildDecisionBookPerson.find_one(
token=data.token,
build_living_space_id=token_dict.selected_occupant.living_space_id,
active=True,
is_confirmed=True,
)
manager_occupant_type = OccupantTypes.find_or_abort(
occupant_code="BU-MNG", occupant_category_type="BU"
)
book_person_manager.check_occupant_type(manager_occupant_type)
# supervisor_occupant_type = OccupantTypes.find_or_abort(occupant_code="BU-SPV", occupant_category_type="BU")
# book_person_supervisor.check_occupant_type(supervisor_occupant_type)
invitation = BuildDecisionBookInvitations.find_one(
id=book_person_manager.invite_id,
build_id=token_dict.selected_occupant.build_id,
active=True,
is_confirmed=True,
)
if not invitation:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Invitation not found. Please check token",
)
assign_occupant_type = OccupantTypes.find_or_abort(
uu_id=data.occupant_type_uu_id, is_confirmed=True, active=True
)
if not assign_occupant_type:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Occupant type must be a Meeting Type {data.occupant_type_uu_id} is not a MT type occupant",
)
build_parts_of_token = BuildParts.filter_active(
BuildParts.build_id == token_dict.selected_occupant.build_id,
)
selected_living_space = BuildLivingSpace.filter_active(
BuildLivingSpace.uu_id == data.build_living_space_uu_id,
BuildLivingSpace.build_parts_id.in_(
[build.id for build in build_parts_of_token.data]
),
)
if not selected_living_space.data:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Person not found. Please check person uuid",
)
selected_living_space = selected_living_space.get(1)
book_person_to_assign: BuildDecisionBookPerson = (
BuildDecisionBookPerson.find_one(
build_living_space_id=selected_living_space.id,
invite_id=invitation.id,
active=True,
is_confirmed=True,
)
)
if not book_person_to_assign:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Person not found in the invitation list. Please check person uuid: {data.person_uu_id}",
)
if not book_person_to_assign.is_attending:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Person is declined the invitation. This person is not attending the meeting. "
f"Please check person uuid: {data.person_uu_id}. Invite UUID: {invitation.uu_id}",
)
if assign_occupant_type.occupant_code in ("MT-PRS", "MT-WRT"):
occupant_type_unique = OccupantTypes.find_or_abort(
occupant_code=assign_occupant_type.occupant_code,
occupant_category_type="MT",
)
if assigned_book_person_occupant := BuildDecisionBookPersonOccupants.find_one(
invite_id=invitation.id,
occupant_type_id=occupant_type_unique.id,
active=True,
is_confirmed=True,
):
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Only one person can be assigned to {assign_occupant_type.occupant_code} type"
f" {assigned_book_person_occupant.uu_id} is already assigned",
)
if assign_occupant_type.occupant_code == "BU-MNG":
person_occupant_manager = BuildDecisionBookPersonOccupants.find_one(
invite_id=invitation.id,
occupant_type_id=manager_occupant_type.id,
active=True,
is_confirmed=True,
)
person_occupant_manager.delete(destroy=True)
book_person_to_assign.add_occupant_type(
occupant_type=assign_occupant_type,
build_living_space_id=selected_living_space.id,
)
return JSONResponse(
status_code=status.HTTP_200_OK,
content={
"completed": True,
"message": "Invitation is updated",
"data": book_person_to_assign.get_dict(),
},
)
DecisionBookPersonListEventMethod = DecisionBookPersonListEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/people/list")
)
DecisionBookPersonAddEventMethod = DecisionBookPersonAddEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/people/add")
)
DecisionBookPersonRemoveEventMethod = DecisionBookPersonRemoveEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/people/remove")
)
DecisionBookPersonAttendEventMethod = DecisionBookPersonAttendEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/invitations/attend")
)
DecisionBookPersonAssignOccupantEventMethod = (
DecisionBookPersonAssignOccupantEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/invitations/assign")
)
)
# Build.pre_query = Build.select_action(
# employee_id=token_dict.selected_company.employee_id,
# filter_expr=[
# Build.id == decision_book.build_id,
# ],
# )
# reachable_building = Build.filter_active()
# if not reachable_building.data:
# raise HTTPException(
# status_code=status.HTTP_404_NOT_FOUND,
# detail=f"No building is match with given Employee UUID {token_dict.selected_company.employee_uu_id}",
# )
#
# Companies.pre_query = Companies.select_action(
# duty_id_list=[
# token_dict.selected_company.duty_id,
# token_dict.selected_company.bulk_duties_id,
# ],
# filter_expr=[Companies.id == decision_book.resp_company_id],
# )
# reachable_companies = Companies.filter_active()
# if not reachable_companies.data:
# raise HTTPException(
# status_code=status.HTTP_404_NOT_FOUND,
# detail=f"No company is match with given Employee UUID {token_dict.selected_company.employee_uu_id}",
# )
# person_to_add = People.find_one(uu_id=data.person_uu_id)
# if not person_to_add:
# raise HTTPException(
# status_code=status.HTTP_404_NOT_FOUND,
# detail=f"No person is match with given UUID {data.person_uu_id}",
# )
# management_typecode = ApiEnumDropdown.filter_active(
# ApiEnumDropdown.uu_id == data.management_typecode_uu_id,
# ApiEnumDropdown.enum_class.in_("BuildManagementType", "BuildDuesTypes"),
# )
# if not management_typecode.data:
# raise HTTPException(
# status_code=status.HTTP_404_NOT_FOUND,
# detail=f"No management type is match with given UUID {data.management_typecode_uu_id}",
# )
# condition_to_met = (
# data.management_typecode_uu_id
# in ApiEnumDropdown.get_management_type_codes_list()
# )
# any_type_already = BuildDecisionBookPerson.find_one(
# build_decision_book_id=decision_book.id,
# management_typecode=data.management_typecode_uu_id,
# )
# if condition_to_met and any_type_already:
# raise HTTPException(
# status_code=status.HTTP_400_BAD_REQUEST,
# detail=f"Management type is already exist in given Decision Book UUID {data.build_decision_book_uu_id}.",
# )
#
# data_dict.pop("build_decision_book_uu_id", None)
# data_dict.pop("person_uu_id", None)
# data_dict["management_typecode"] = data_dict.pop(
# "management_typecode_uu_id", None
# )
# data_dict["build_decision_book_id"] = decision_book.id
# data_dict["person_id"] = person_to_add.id
#
# created = BuildDecisionBookPerson.find_or_create(**data_dict)
# if created.is_found:
# raise HTTPException(
# status_code=status.HTTP_400_BAD_REQUEST,
# detail=f"Decision Book Person is already exist in given Decision Book UUID {data.build_decision_book_uu_id}.",
# )
# return JSONResponse(
# status_code=status.HTTP_200_OK,
# content=dict(
# message=f"Decision Book Person has added for given Decision Book UUID {data.build_decision_book_uu_id}",
# completed=True,
# data=created.get_dict(),
# ),
# )

View File

@ -0,0 +1,286 @@
import typing
from fastapi import status, HTTPException
from fastapi.responses import JSONResponse
from databases import (
Build,
BuildLivingSpace,
BuildParts,
BuildDecisionBookInvitations,
BuildDecisionBookPerson,
BuildDecisionBook,
BuildDecisionBookPersonOccupants,
OccupantTypes,
Users,
ApiEnumDropdown,
)
from api_validations import (
DecisionBookDecisionBookInvitationsUpdate,
DecisionBookDecisionBookInvitations,
)
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from api_validations.core_response import return_json_response_from_alchemy
from api_library.date_time_actions.date_functions import DateTimeLocal
class BuildDecisionBookInvitationsListEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"e2277528-8c9c-4c0c-ae64-3ce80cae664b": "decision_book_invitations_list",
}
@classmethod
def decision_book_invitations_list(
cls,
data,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
return
class BuildDecisionBookInvitationsCreateEventMethods(MethodToEvent):
event_type = "CREATE"
__event_keys__ = {
"d0bfa20c-841d-421c-98e6-d308f938d16a": "decision_book_invitations_create",
}
@classmethod
def decision_book_invitations_create(
cls,
data: DecisionBookDecisionBookInvitations,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
if isinstance(token_dict, EmployeeTokenObject):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Employee cannot create decision book invitations",
)
# Check token posses the occupant type of Build Manager
occupant_manager = OccupantTypes.find_one(
occupant_category_type="BU", occupant_code="BU-MNG"
)
if not token_dict.selected_occupant.occupant_type_id == occupant_manager.id:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Only Build Manager can create decision book",
)
# Check decision book is valid for this token and building
decision_book = BuildDecisionBook.find_one(
uu_id=data.build_decision_book_uu_id,
build_id=token_dict.selected_occupant.build_id,
)
if not decision_book:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Decision book not found. Please create decision book first",
)
occupant_building = Build.find_one(id=token_dict.selected_occupant.build_id)
# Check meeting type is valid
meeting_type = ApiEnumDropdown.find_one(
enum_class="MeetingTypes",
)
if not meeting_type:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Meeting type not found",
)
# Check planned decision book date is valid
if (
not DateTimeLocal.get(data.planned_date).date()
>= DateTimeLocal.shift(days=1).date()
):
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Planned date must be greater than today",
)
# Create an invitation for specific invitation type to start invite sending process
book_invitation = BuildDecisionBookInvitations.find_or_create(
build_id=token_dict.selected_occupant.build_id,
build_uu_id=token_dict.selected_occupant.build_uuid,
decision_book_id=decision_book.id,
decision_book_uu_id=str(decision_book.uu_id),
invitation_type=meeting_type.key,
living_part_count=occupant_building.livable_part_count,
living_part_percentage=0.51,
message=data.message,
planned_date=data.planned_date,
planned_date_expires=str(
DateTimeLocal.get(data.planned_date).shift(days=15).date()
),
expiry_ends=str(DateTimeLocal.get(data.planned_date).shift(days=15).date()),
is_confirmed=True,
)
if book_invitation.is_found:
detail_message = (
f"Invitation with: {str(book_invitation.planned_date)} already exists"
f" for {book_invitation.invitation_type}"
)
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=detail_message,
)
# Get all the parts of the building that is occupant in token
build_parts = BuildParts.filter_active(
BuildParts.build_id == occupant_building.id
)
# Get all build living spaces that is found in building with distinct person id
occupants = OccupantTypes.filter_all()
build_living_spaces_people = (
BuildLivingSpace.filter_active(
BuildLivingSpace.build_parts_id.in_(
[build_part.id for build_part in build_parts.data]
),
BuildLivingSpace.occupant_type.in_(
[occupant.id for occupant in occupants.data]
),
filter_records=False,
)
.query.distinct(BuildLivingSpace.person_id)
.all()
)
if not build_living_spaces_people:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="No living spaces found for the building",
)
print(
f"Tnvite UUID : {book_invitation.uu_id} Message : {data.message} Planned date : {data.planned_date}"
)
# Send invitation to all the users as attend and update the manager as build manager
attendance_occupant_type = OccupantTypes.find_or_abort(
occupant_code="MT-ATT", occupant_category_type="MT"
)
manager_occupant_type = OccupantTypes.find_or_abort(
occupant_code="BU-MNG", occupant_category_type="BU"
)
build_decision_book_person_dict = dict(
build_decision_book_id=decision_book.id,
build_decision_book_uu_id=str(decision_book.uu_id),
invite_id=book_invitation.id,
invite_uu_id=str(book_invitation.uu_id),
send_date=str(DateTimeLocal.now().date()),
expiry_starts=decision_book.expiry_starts,
expiry_ends=decision_book.expiry_ends,
is_confirmed=True,
)
# Check if the invitation is already created at database
for build_living_spaces_user in build_living_spaces_people:
if invite := BuildDecisionBookPerson.find_one(
invite_id=book_invitation.id,
build_living_space_id=build_living_spaces_user.id,
):
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Invitation already send to {build_living_spaces_user.email} "
f"for invite {invite.uu_id} date : {str(book_invitation.planned_date)}",
)
invitations_person = BuildDecisionBookPerson.find_or_create(
**build_decision_book_person_dict,
build_living_space_id=build_living_spaces_user.id,
build_living_space_uu_id=str(build_living_spaces_user.uu_id),
person_id=build_living_spaces_user.person_id,
token=Users.generate_token(40),
)
invitations_person.add_occupant_type(occupant_type=attendance_occupant_type)
if invitations_person and not invitations_person.is_found:
print(f'"{invitations_person.token}",')
spaces_user = Users.find_one(
active=True,
is_confirmed=True,
person_id=build_living_spaces_user.person_id,
)
# print(
# f"Invitation is send : {spaces_user.email} "
# f"Token : {invitations_person.token} "
# f"Send Date : {str(invitations_person.send_date.date())}"
# )
manager_living_spaces = BuildLivingSpace.filter_active(
BuildLivingSpace.person_id == token_dict.person_id,
)
manager_people = BuildDecisionBookPerson.filter_active(
BuildDecisionBookPerson.invite_id == book_invitation.id,
BuildDecisionBookPerson.build_living_space_id.in_(
[
manager_living_space.id
for manager_living_space in manager_living_spaces.data
]
),
)
manager_people_occupants = BuildDecisionBookPersonOccupants.filter_active(
BuildDecisionBookPersonOccupants.build_decision_book_person_id
== manager_people.get(1).id
)
dlt = [
occupants.delete(destroy=True)
for occupants in manager_people_occupants.data
]
dlt = [occupants.delete(destroy=True) for occupants in manager_people.data]
if book_person_manager := BuildDecisionBookPerson.find_or_create(
**build_decision_book_person_dict,
build_living_space_id=token_dict.selected_occupant.living_space_id,
build_living_space_uu_id=str(
token_dict.selected_occupant.living_space_uu_id
),
person_id=token_dict.person_id,
token=Users.generate_token(40),
):
book_person_manager.add_occupant_type(occupant_type=manager_occupant_type)
print(f"Manager Token : {book_person_manager.token}")
return JSONResponse(
status_code=status.HTTP_200_OK,
content={
"completed": True,
"message": "Invitation are send to people related with building",
"data": book_invitation.get_dict(),
},
)
class BuildDecisionBookInvitationsUpdateEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"92413636-53a8-4a05-842c-1485a64e00d1": "decision_book_invitations_attend",
}
@classmethod
def decision_book_invitations_attend(
cls,
data: DecisionBookDecisionBookInvitationsUpdate,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
return
BuildDecisionBookInvitationsListEventMethod = (
BuildDecisionBookInvitationsListEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/invite/list")
)
)
BuildDecisionBookInvitationsCreateEventMethod = (
BuildDecisionBookInvitationsCreateEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/invite/create")
)
)
BuildDecisionBookInvitationsUpdateEventMethod = (
BuildDecisionBookInvitationsUpdateEventMethods(
action=ActionsSchema(endpoint="/build/decision_book/invite/update")
)
)

View File

@ -0,0 +1,6 @@
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from api_validations.core_response import return_json_response_from_alchemy
class ProjectDecisionBookProjectDecisionBookEvents(MethodToEvent): ...

View File

@ -0,0 +1,6 @@
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from api_validations.core_response import return_json_response_from_alchemy
class ProjectDecisionBookProjectDecisionBookPersonEvents(MethodToEvent): ...

View File

View File

@ -0,0 +1,146 @@
from fastapi import status
from fastapi.responses import JSONResponse
from fastapi.exceptions import HTTPException
from databases import (
BuildLivingSpace,
BuildParts,
Build,
Events,
Event2Occupant,
OccupantTypes,
)
from api_validations import RegisterEvents2Occupant
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from api_validations.core_response import return_json_response_from_alchemy
class EventBindOccupantEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"5702f0a9-fe8f-4aae-922e-6e04b497ef6a": "bind_events_occupant_super_user",
}
@classmethod
def bind_events_occupant_super_user(
cls, data: RegisterEvents2Occupant, token_dict: EmployeeTokenObject
):
if not str(token_dict.user_type) == "1":
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="This employee is not authorized to add event to this occupant",
)
occupants_build_part = BuildParts.find_one(uu_id=data.build_part_uu_id)
if not occupants_build_part:
return JSONResponse(
content={
"completed": False,
"message": "This employee is not authorized to add event to this building",
"data": {},
},
status_code=status.HTTP_404_NOT_FOUND,
)
occupant_occupant_type = OccupantTypes.find_one(uu_id=data.occupant_uu_id)
if not occupant_occupant_type:
return JSONResponse(
content={
"completed": False,
"message": "Occupant Types is not found",
"data": {},
},
status_code=status.HTTP_404_NOT_FOUND,
)
events_to_add_to_occupant = Events.filter_active(
Events.uu_id.in_(list(data.event_uu_id_list))
)
if not events_to_add_to_occupant.data:
return JSONResponse(
content={
"completed": False,
"message": "Events are not found. Please contact with your manager",
"data": {},
},
status_code=status.HTTP_404_NOT_FOUND,
)
employee_is_authorized = Build.select_action(
employee_id=token_dict.selected_company.employee_id,
filter_expr=[Build.id == occupants_build_part.build_id],
)
if not employee_is_authorized.first():
return JSONResponse(
content={
"completed": False,
"data": {},
},
status_code=status.HTTP_401_UNAUTHORIZED,
)
occupant_to_add_event = BuildLivingSpace.find_one(
build_parts_id=occupants_build_part.id,
occupant_type=occupant_occupant_type.id,
)
if not occupant_to_add_event:
return JSONResponse(
content={
"completed": False,
"message": "Occupant is not found or this employee is not authorized to add event to this occupant",
"data": {},
},
status_code=status.HTTP_404_NOT_FOUND,
)
events_added = []
for event in events_to_add_to_occupant.data:
if Event2Occupant.find_or_create(
event_id=event.id,
event_uu_id=str(event.uu_id),
build_living_space_id=occupant_to_add_event.id,
build_living_space_uu_id=str(occupant_to_add_event.uu_id),
is_confirmed=True,
):
events_added.append(event)
if events_added:
return JSONResponse(
content={
"completed": True,
"message": "Event added to occupant",
"data": [event.get_dict() for event in events_added],
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={
"completed": False,
"message": "Event is not added to occupant",
"data": [],
},
status_code=status.HTTP_404_NOT_FOUND,
)
class EventBindEmployeeEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"c93a3009-65a0-498d-9191-04484d5cde81": "bind_events_employee",
}
@classmethod
def bind_events_employee(cls, data: RegisterEvents2Occupant, token_dict):
return token_dict.available_event(data=data, token_dict=token_dict)
EventBindOccupantEventMethod = EventBindOccupantEventMethods(
action=ActionsSchema(endpoint="/bind/events/occupant")
)
EventBindEmployeeEventMethod = EventBindEmployeeEventMethods(
action=ActionsSchema(endpoint="/bind/events/employee")
)

View File

@ -0,0 +1,337 @@
import typing
from fastapi import status
from fastapi.responses import JSONResponse
from fastapi.exceptions import HTTPException
from databases import (
Modules,
Employees,
BuildParts,
BuildLivingSpace,
Service2Events,
Services,
OccupantTypes,
Event2Employee,
Event2Occupant,
)
from api_validations import RegisterServices2Occupant, RegisterServices2Employee
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from api_validations.core_response import return_json_response_from_alchemy
class ServiceBindOccupantEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"0d2bc5c9-d4b1-4951-8305-69da4a687fdc": "bind_services_occupant",
}
@classmethod
def bind_services_occupant_system(
cls, build_living_space_id: int, service_id: int, expires_at: str = None
):
from sqlalchemy.dialects.postgresql import insert
living_space = BuildLivingSpace.find_or_abort(
id=build_living_space_id,
)
service = Services.find_or_abort(
id=service_id,
)
default_module = Modules.find_one(module_code="USR-PUB")
add_default_service = Services.find_one(module_id=default_module.id)
service_events = Service2Events.filter_all(
Service2Events.service_id == service.id,
)
default_service_events = Service2Events.filter_all(
Service2Events.service_id == add_default_service.id,
)
add_events_list = service_events.data + default_service_events.data
if not add_events_list:
raise Exception(
"Service has no events registered. Please contact with your manager"
)
event_ids_list = [
{
"build_living_space_id": living_space.id,
"build_living_space_uu_id": str(living_space.uu_id),
"event_id": service_event.event_id,
"event_uu_id": str(service_event.event_uu_id),
"is_confirmed": True,
"expiry_ends": str(expires_at) if expires_at else "2099-12-31 03:00:00",
}
for service_event in add_events_list
]
session_execute = Services.session.execute(
insert(Event2Occupant)
.values(event_ids_list)
.on_conflict_do_nothing(
index_elements=["build_living_space_id", "event_id"],
)
)
count_row = session_execute.rowcount
print(f"{count_row} events are added to occupant {str(living_space.uu_id)}")
Services.session.commit()
Services.session.flush()
@classmethod
def bind_services_occupant(
cls,
data: RegisterServices2Occupant,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
from sqlalchemy.dialects.postgresql import insert
if isinstance(token_dict, EmployeeTokenObject):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Employee is not authorized to add service to any occupant",
)
occupants_build_part = BuildParts.find_one(
uu_id=data.build_part_uu_id,
build_id=token_dict.selected_occupant.build_id,
)
print("occupants_build_part", occupants_build_part)
if not occupants_build_part:
return JSONResponse(
content={
"completed": False,
"message": "User is not authorized to add service to this occupant or flat",
"data": {},
},
status_code=status.HTTP_404_NOT_FOUND,
)
occupant_occupant_type = OccupantTypes.find_one(uu_id=data.occupant_uu_id)
if not occupant_occupant_type:
return JSONResponse(
content={
"completed": False,
"message": "Occupant Types is not found",
"data": {},
},
status_code=status.HTTP_404_NOT_FOUND,
)
service = Services.find_one(uu_id=data.service_uu_id)
if not service:
return JSONResponse(
content={
"completed": False,
"message": "Service is not found",
"data": {},
},
status_code=status.HTTP_404_NOT_FOUND,
)
default_module = Modules.find_one(module_code="USR-PUB")
add_default_service = Services.find_one(module_id=default_module.id)
service_events = Service2Events.filter_all(
Service2Events.service_id == service.id,
)
default_service_events = Service2Events.filter_all(
Service2Events.service_id == add_default_service.id,
)
add_events_list = service_events.data + default_service_events.data
if not add_events_list:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Service has no events registered. Please contact with your manager",
)
living_space = BuildLivingSpace.find_one(
build_parts_id=occupants_build_part.id,
occupant_types_id=occupant_occupant_type.id,
person_id=token_dict.person_id,
)
if not living_space:
return JSONResponse(
content={
"completed": False,
"message": "Living Space is not found with given data. Please check flat and occupant type",
"data": {},
},
status_code=status.HTTP_404_NOT_FOUND,
)
event_ids_list = [
{
"build_living_space_id": living_space.id,
"build_living_space_uu_id": str(living_space.uu_id),
"event_id": service_event.event_id,
"event_uu_id": str(service_event.event_uu_id),
"is_confirmed": True,
}
for service_event in add_events_list
]
session_execute = Services.session.execute(
insert(Event2Occupant)
.values(event_ids_list)
.on_conflict_do_nothing(
index_elements=["employee_id", "event_id"],
)
)
count_row = session_execute.rowcount
print(f"{count_row} events are added to employee {str(living_space.uu_id)}")
Services.session.commit()
Services.session.flush()
class ServiceBindEmployeeEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"50f84023-d8ec-4257-bfce-08ddf077c101": "bind_services_employee_super_user",
}
@classmethod
def bind_services_employee(cls, service_id: int, employee_id: int):
from sqlalchemy.dialects.postgresql import insert
employee = Employees.find_or_abort(
id=employee_id,
)
service = Services.find_or_abort(
id=service_id,
)
default_module = Modules.find_one(module_code="USR-PUB")
add_default_service = Services.find_one(module_id=default_module.id)
service_events = Service2Events.filter_all(
Service2Events.service_id == service.id,
)
default_service_events = Service2Events.filter_all(
Service2Events.service_id == add_default_service.id,
)
add_events_list = service_events.data + default_service_events.data
if not add_events_list:
raise Exception(
"Service has no events registered. Please contact with your manager"
)
event_ids_list = [
{
"employee_id": employee_id,
"employee_uu_id": str(employee.uu_id),
"event_id": service_event.event_id,
"event_uu_id": str(service_event.event_uu_id),
"is_confirmed": True,
}
for service_event in add_events_list
]
session_execute = Services.session.execute(
insert(Event2Employee)
.values(event_ids_list)
.on_conflict_do_nothing(
index_elements=["employee_id", "event_id"],
)
)
count_row = session_execute.rowcount
print(f"{count_row} events are added to employee {employee.uu_id}")
Services.session.commit()
Services.session.flush()
@classmethod
def bind_services_employee_super_user(
cls,
data: RegisterServices2Employee,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
from sqlalchemy.dialects.postgresql import insert
if isinstance(token_dict, OccupantTokenObject):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Occupant is not authorized to add service to any employee",
)
employee = Employees.find_one(uu_id=data.employee_uu_id)
if not employee:
return JSONResponse(
content={
"completed": False,
"message": "This employee is not authorized to add event to this employee",
"data": {},
},
status_code=status.HTTP_404_NOT_FOUND,
)
service = Services.find_one(uu_id=data.service_uu_id)
if not service:
return JSONResponse(
content={
"completed": False,
"message": "Service is not found",
"data": {},
},
status_code=status.HTTP_404_NOT_FOUND,
)
service_events = Service2Events.filter_all(
Service2Events.service_id == service.id,
)
default_module = Modules.find_one(module_code="USR-PUB")
add_default_service = Services.find_one(module_id=default_module.id)
default_service_events = Service2Events.filter_all(
Service2Events.service_id == add_default_service.id,
)
add_events_list = service_events.data + default_service_events.data
if not add_events_list:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Service has no events registered. Please contact with your manager",
)
event_ids_list = [
{
"employee_id": employee.id,
"employee_uu_id": employee.uu_id,
"event_id": service_event.event_id,
"event_uu_id": service_event.event_uu_id,
"is_confirmed": True,
}
for service_event in add_events_list
]
session_execute = Services.session.execute(
insert(Event2Employee)
.values(event_ids_list)
.on_conflict_do_nothing(
index_elements=["employee_id", "event_id"],
)
)
count_row = session_execute.rowcount
Services.session.commit()
Services.session.flush()
if not count_row:
return JSONResponse(
content={
"completed": False,
"message": "No events are added to employee",
"data": {},
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={
"completed": True,
"message": f"{count_row} events are added to employee",
"data": {},
},
status_code=status.HTTP_200_OK,
)
ServiceBindOccupantEventMethod = ServiceBindOccupantEventMethods(
action=ActionsSchema(endpoint="/bind/services/occupant")
)
ServiceBindEmployeeEventMethod = ServiceBindEmployeeEventMethods(
action=ActionsSchema(endpoint="/bind/services/employee")
)

View File

@ -0,0 +1,218 @@
from fastapi.exceptions import HTTPException
from databases import (
Events,
Employees,
Staff,
Duties,
Event2Occupant,
Event2Employee,
BuildLivingSpace,
)
from api_validations import (
RegisterEvents2Employee,
RegisterEvents2Occupant,
CreateEvents,
ListOptions,
)
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from api_validations.core_response import return_json_response_from_alchemy
class EventsListEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"9fa01bef-c0e8-4fe1-b9ed-2ff1c4f35faa": "events_list",
}
@classmethod
def events_list(cls, list_options: ListOptions, token_dict):
records = Events.filter_active(
*Events.get_smart_query(list_options.query),
)
return return_json_response_from_alchemy(
response=records, pagination=list_options
)
class EventsCreateEventMethods(MethodToEvent):
event_type = "CREATE"
__event_keys__ = {
"514a9f8f-e5e5-4e10-9d0b-2de8f461fc1b": "events_create",
}
@classmethod
def events_create(cls, data: CreateEvents, token_dict):
event = Events.find_or_create(
**token_dict.user_creds,
event_name=data.event_name,
event_description=data.event_description,
event_date=data.event_date,
event_location=data.event_location,
active=True,
deleted=False,
)
return {
"status": "success",
"message": "Event created successfully.",
"event": event.uu_id,
}
class EventsUpdateEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"f94e7b79-2369-4840-bf2b-244934ca3136": "events_update",
}
@classmethod
def events_update(cls, data: CreateEvents, token_dict):
event = Events.find_one(uu_id=data.uu_id)
if not event:
raise HTTPException(
status_code=404,
detail="No event found. Please contact your responsible company.",
)
event.update(
**token_dict.user_creds,
event_name=data.event_name,
event_description=data.event_description,
event_date=data.event_date,
event_location=data.event_location,
)
return {
"status": "success",
"message": "Event updated successfully.",
"event": event.uu_id,
}
class EventsPatchEventMethods(MethodToEvent):
event_type = "PATCH"
__event_keys__ = {
"41944c63-22d3-4866-affd-34bcd49da58b": "events_patch",
}
@classmethod
def events_patch(cls, data: CreateEvents, token_dict):
event = Events.find_one(uu_id=data.uu_id)
if not event:
raise HTTPException(
status_code=404,
detail="No event found. Please contact your responsible company.",
)
event.update(
**token_dict.user_creds,
event_name=data.event_name,
event_description=data.event_description,
event_date=data.event_date,
event_location=data.event_location,
)
return {
"status": "success",
"message": "Event patched successfully.",
"event": event.uu_id,
}
class EventsBindEventToOccupantMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"d9aa58aa-37f7-4c27-861d-3105f76f5cdc": "bind_events_employee",
}
@classmethod
def bind_events_employee(cls, data: RegisterEvents2Employee, token_dict):
events = Events.filter_active(Events.uu_id.in_(data.event_id))
if not events:
raise HTTPException(
status_code=401,
detail="No event found. Please contact your super user.",
)
employee = Employees.find_one(employee_uu_id=data.employee_uu_id)
employee_is_not_valid = False
if employee:
staff = Staff.find_one(id=employee.staff_id)
duties = Duties.find_one(id=staff.duties_id)
if duties.company_id not in token_dict.companies_id_list:
employee_is_not_valid = True
if employee_is_not_valid:
raise HTTPException(
status_code=401,
detail="This employee can not be reached by this user. Please contact your super user.",
)
for event in events.data:
employee = Event2Employee.find_or_create(
**token_dict.user_creds, employee_id=employee.id, event_id=event.id
)
return {
"status": "success",
"message": "Events registered successfully.",
"events": [event.uu_id for event in events.data],
}
class EventsBindEventToEmployeeMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"8bb4f4fc-b474-427e-90b3-d8681f308bb5": "bind_events_occupant",
}
@classmethod
def bind_events_occupant(cls, data: RegisterEvents2Occupant, token_dict):
events = Events.filter_active(Events.uu_id.in_(data.event_id))
if not events:
raise HTTPException(
status_code=401,
detail="No event found. Please contact your super user.",
)
occupant = BuildLivingSpace.find_one(uu_id=data.build_living_space_uu_id)
occupant_is_not_valid = False
if occupant_is_not_valid:
raise HTTPException(
status_code=401,
detail="This occupant can not be reached by this user. Please contact your super user.",
)
for event in events.data:
occupant = Event2Occupant.find_or_create(
**token_dict.user_creds,
build_living_space_id=occupant.id,
event_id=event.id,
)
return {
"status": "success",
"message": "Events registered successfully.",
"events": [event.uu_id for event in events.data],
}
EventsListEventMethod = EventsListEventMethods(
action=ActionsSchema(endpoint="/event/list")
)
EventsCreateEventMethod = EventsCreateEventMethods(
action=ActionsSchema(endpoint="/event/create")
)
EventsUpdateEventMethod = EventsUpdateEventMethods(
action=ActionsSchema(endpoint="/event/update")
)
EventsPatchEventMethod = EventsPatchEventMethods(
action=ActionsSchema(endpoint="/event/patch")
)
EventsBindEventToOccupantMethod = EventsBindEventToOccupantMethods(
action=ActionsSchema(endpoint="/bind/events/occupant")
)
EventsBindEventToEmployeeMethod = EventsBindEventToEmployeeMethods(
action=ActionsSchema(endpoint="/bind/events/employee")
)

View File

@ -0,0 +1,85 @@
from fastapi import status
from fastapi.responses import JSONResponse
from api_validations import DepartmentsPydantic, ListOptions
from databases import Events
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from api_validations.core_response import return_json_response_from_alchemy
class ModelEntitiesEvents(MethodToEvent):
@classmethod
def model_entities_list(cls, list_options: ListOptions, token_dict):
Events.filter_attr = list_options
records = Events.filter_active(
*Events.get_smart_query(smart_query=list_options.query),
Events.company_id == token_dict.selected_company.company_id
)
return return_json_response_from_alchemy(
response=records, pagination=list_options
)
@classmethod
def model_entities_create(cls, data: DepartmentsPydantic, token_dict):
created_events = Events.create_action(data=data, token=token_dict)
if created_events.is_found:
return JSONResponse(
content={
"completed": False,
"message": "Events record already exits here is the record",
"data": created_events.get_dict(),
},
status_code=status.HTTP_202_ACCEPTED,
)
return JSONResponse(
content={
"completed": True,
"message": "Create Events record",
"data": created_events.get_dict(),
},
status_code=status.HTTP_200_OK,
)
@classmethod
def model_entities_update(
cls, company_uu_id: str, data: DepartmentsPydantic, token_dict
):
find_one_events = Events.find_one_or_abort(uu_id=company_uu_id)
access_authorized_events = Events.select_action(
duty_id=getattr(token_dict, "duty_id", 5),
filter_expr=[Events.id == token_dict.get("")],
action="update",
data=data,
)
return JSONResponse(
content={
"completed": True,
"message": "Update Events record",
"data": access_authorized_events.get_dict(),
},
status_code=status.HTTP_200_OK,
)
@classmethod
def model_entities_patch(
cls, company_uu_id: str, data: DepartmentsPydantic, token_dict
):
find_one_events = Events.find_one_or_abort(uu_id=company_uu_id)
access_authorized_events = Events.select_action(
duty_id=getattr(token_dict, "duty_id", 5),
filter_expr=[Events.id == token_dict.get("")],
action="patch",
data=data,
)
return JSONResponse(
content={
"completed": True,
"message": "Patch Events record",
"data": access_authorized_events.get_dict(),
},
status_code=status.HTTP_200_OK,
)

View File

@ -0,0 +1,24 @@
from validations import DepartmentsPydantic, PatchRecord, ListOptions
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from api_validations.core_response import return_json_response_from_alchemy
class ModelEvents(MethodToEvent):
@classmethod
def model_list(cls, list_options: ListOptions, token_dict):
return
@classmethod
def model_create(cls, data: DepartmentsPydantic, token_dict):
return
@classmethod
def model_update(cls, company_uu_id: str, data: DepartmentsPydantic, token_dict):
return
@classmethod
def model_patch(cls, company_uu_id: str, data: PatchRecord, token_dict):
return

View File

@ -0,0 +1,24 @@
from validations import DepartmentsPydantic, PatchRecord
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from api_validations.core_response import return_json_response_from_alchemy
class ModulesEvents(MethodToEvent):
@classmethod
def modules_list(cls, request, list_options):
return
@classmethod
def modules_create(cls, data: DepartmentsPydantic, token_dict):
return
@classmethod
def modules_update(cls, module_uu_id: str, data: DepartmentsPydantic, token_dict):
return
@classmethod
def modules_patch(cls, module_uu_id: str, data: PatchRecord, token_dict):
return

View File

@ -0,0 +1,36 @@
from validations import DepartmentsPydantic, PatchRecord, ListOptions
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from api_validations.core_response import return_json_response_from_alchemy
class ServicesEvents(MethodToEvent):
@classmethod
def services_list(cls, list_options: ListOptions):
return
@classmethod
def services_create(cls, data: DepartmentsPydantic, token_dict):
return
@classmethod
def services_update(cls, service_uu_id: str, data: DepartmentsPydantic, token_dict):
return
@classmethod
def services_patch(cls, service_uu_id: str, data: PatchRecord, token_dict):
return
@classmethod
def bind_service_to_action(cls, data, token_dict):
return
@classmethod
def bind_module_to_service(cls, data, token_dict):
return
@classmethod
def bind_events_patch(cls, company_uu_id: str, data: PatchRecord):
return

View File

View File

@ -0,0 +1,140 @@
from fastapi import status
from fastapi.responses import JSONResponse
from databases import (
People,
Users,
Companies,
)
from validations import InsertPerson, UpdateUsers
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from api_validations.core_response import return_json_response_from_alchemy
class PeopleListEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"0a05f03c-6ed8-4230-a4ff-6e7cf886909b": "super_users_people_list",
"b5612538-0445-4a4a-ab13-d2a06037f7a5": "sales_users_people_list",
"c81c2cec-d32c-4cf2-9727-d4493e11ee1f": "human_resources_users_people_list",
"d1b1b1b1-1b1b-1b1b-1b1b-1b1b1b1b1b1b": "people_list_only_occupant_tenant_or_owner",
}
@classmethod
def super_users_people_list(cls, list_options, token_dict):
records = People.filter_active(
*People.get_smart_query(smart_query=list_options.query)
)
return return_json_response_from_alchemy(
response=records, pagination=list_options
)
@classmethod
def sales_users_people_list(cls, data, token_dict):
records = People.filter_active(*People.get_smart_query(smart_query=data.query))
# records = [model_class(**record) for record in records.data]
return return_json_response_from_alchemy(response=records, pagination=data)
@classmethod
def human_resources_users_people_list(cls, data, token_dict):
records = People.filter_active(*People.get_smart_query(smart_query=data.query))
# records = [model_class(**record) for record in records.data]
return return_json_response_from_alchemy(response=records, pagination=data)
class PeopleCreateEventMethods(MethodToEvent):
event_type = "CREATE"
__event_keys__ = {
"2d1513f4-44ed-4fa3-84d1-dfbd0eadf9a1": "people_create",
}
@classmethod
def people_create(cls, data: InsertPerson, token_dict: dict):
created_user = People.create_action(data=data, token=token_dict)
return JSONResponse(
content={
"completed": True,
"message": "Create User record",
"data": created_user.get_dict(),
},
status_code=status.HTTP_200_OK,
)
class PeopleUpdateEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"e05cf22c-16c4-450b-86c8-417896a26afc": "people_update",
}
@classmethod
def people_update(cls, data: UpdateUsers, user_uu_id: str, token_dict: dict):
find_one_user = Users.find_one_or_abort(uu_id=user_uu_id)
access_authorized_company = Companies.select_action(
duty_id=getattr(token_dict, "duty_id", 5),
filter_expr=[Companies.id == find_one_user.id],
)
if access_authorized_company.count:
data_dict = data.excluded_dump()
updated_user = find_one_user.update(**data_dict)
return JSONResponse(
content={
"completed": True,
"message": "Update User record",
"data": updated_user,
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={"completed": True, "message": "Update User record", "data": {}},
status_code=status.HTTP_200_OK,
)
class PeoplePatchEventMethods(MethodToEvent):
event_type = "PATCH"
__event_keys__ = {
"3ae16d66-090b-4d27-b567-cce1b10a1c3b": "people_patch",
}
@classmethod
def people_patch(cls):
return
class PeopleDeleteEventMethods(MethodToEvent):
event_type = "DELETE"
__event_keys__ = {
"7f84c7a2-a120-4867-90d4-6767a41320db": "people_delete",
}
PeopleListEventMethod = PeopleListEventMethods(
action=ActionsSchema(endpoint="/people/list")
)
PeopleCreateEventMethod = PeopleCreateEventMethods(
action=ActionsSchema(endpoint="/people/create")
)
PeopleUpdateEventMethod = PeopleUpdateEventMethods(
action=ActionsSchema(endpoint="/people/update")
)
PeoplePatchEventMethod = PeoplePatchEventMethods(
action=ActionsSchema(endpoint="/people/patch")
)
PeopleDeleteEventMethod = PeopleDeleteEventMethods(
action=ActionsSchema(endpoint="/people/delete")
)

View File

@ -0,0 +1,167 @@
import typing
from fastapi import status
from fastapi.responses import JSONResponse
from databases import MongoQueryIdentity, Users, Companies, People
from databases.no_sql_models.validations import DomainViaUser
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from api_validations.core_response import return_json_response_from_alchemy
from validations import InsertUsers, UpdateUsers, PatchRecord, ListOptions
class UserListEventMethods(MethodToEvent):
event_type = "SELECT"
__event_keys__ = {
"1483a8a2-d244-4593-b9f8-f1b4bcbefcd5": "user_list",
}
@classmethod
def user_list(
cls,
list_options: ListOptions,
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
):
# Users.pre_query = Users.select_action(duty_id_list=[
# token_dict.selected_company.duty_id,
# token_dict.selected_company.bulk_duties_id
# ])
if "user_uu_id_list" in list_options.query:
people_ids = list_options.query.pop("user_uu_id_list")
people_id_list = [
user.person_id
for user in Users.filter_active(Users.uu_id.in_(people_ids)).data
]
records = People.filter_active(People.id.in_(people_id_list))
return return_json_response_from_alchemy(
response=records, pagination=list_options
)
records = Users.filter_active(*Users.get_smart_query(list_options.query))
return return_json_response_from_alchemy(
response=records, pagination=list_options
)
class UserCreateEventMethods(MethodToEvent):
event_type = "CREATE"
__event_keys__ = {
"8eb50c24-4bdc-4309-9836-f7048daee409": "user_create",
}
@classmethod
def user_create(cls, data: InsertUsers, token_dict):
created_user = Users.create_action(create_user=data)
created_user.related_company = token_dict.selected_company.company_uu_id
domain_via_user = DomainViaUser(
**{"user_uu_id": str(created_user.uu_id), "main_domain": "evyos.com.tr"}
)
created_user.save()
mongo_query_identity = MongoQueryIdentity(
company_uuid=created_user.related_company,
)
mongo_query_identity.create_domain_via_user(payload=domain_via_user)
return JSONResponse(
content={
"completed": True,
"message": "Create User record",
"data": created_user.get_dict(),
"password_token": {
"password_token": created_user.password_token,
"password_expires_day": str(created_user.password_expires_day),
"password_expiry_begins": str(created_user.password_expiry_begins),
"hash_password": created_user.hash_password,
"related_company": created_user.related_company,
},
},
status_code=status.HTTP_200_OK,
)
class UserUpdateEventMethods(MethodToEvent):
event_type = "UPDATE"
__event_keys__ = {
"d08a9470-1eb0-4890-a9e8-b6686239d7e9": "user_update",
}
@classmethod
def user_update(cls, data: UpdateUsers, user_uu_id: str, token_dict):
find_one_user = Users.find_one_or_abort(uu_id=user_uu_id)
access_authorized_company = Companies.select_action(
duty_id=getattr(token_dict, "duty_id", 5),
filter_expr=[Companies.id == token_dict.get("")],
)
if access_authorized_company.count:
data_dict = data.excluded_dump()
updated_user = find_one_user.update(**data_dict)
return JSONResponse(
content={
"completed": True,
"message": "Update User record",
"data": updated_user,
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={"completed": True, "message": "Update User record", "data": {}},
status_code=status.HTTP_200_OK,
)
class UserPatchEventMethods(MethodToEvent):
event_type = "PATCH"
__event_keys__ = {
"d26a1a3c-eaeb-4d01-b35b-a5ed714e29c0": "user_patch",
}
@classmethod
def user_patch(cls, data: PatchRecord, user_uu_id: str, token_dict):
find_one_user = Users.find_one_or_abort(uu_id=user_uu_id)
access_authorized_company = Companies.select_action(
duty_id=getattr(token_dict, "duty_id", 5),
filter_expr=[Companies.id == find_one_user.id],
)
if access_authorized_company.count:
action = data.excluded_dump()
find_one_user.active = bool(action.get("active", find_one_user.active))
find_one_user.is_confirmed = bool(
action.get("confirm", find_one_user.is_confirmed)
)
find_one_user.deleted = bool(action.get("delete", find_one_user.deleted))
find_one_user.save()
return JSONResponse(
content={
"completed": True,
"message": "Patch User record completed",
"data": find_one_user.get_dict(),
},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={
"completed": False,
"message": "Patch User record failed",
"data": {},
},
status_code=status.HTTP_200_OK,
)
UserListEventMethod = UserListEventMethods(action=ActionsSchema(endpoint="/user/list"))
UserCreateEventMethod = UserCreateEventMethods(
action=ActionsSchema(endpoint="/user/create")
)
UserUpdateEventMethod = UserUpdateEventMethods(
action=ActionsSchema(endpoint="/user/update")
)
UserPatchEventMethod = UserPatchEventMethods(
action=ActionsSchema(endpoint="/user/patch")
)

View File

@ -0,0 +1,31 @@
from tasks2events.common_tasks.default_user import AuthDefaultEventBlock
from tasks2events.employee_tasks.super_user import SuperUserEventBlock
from tasks2events.occupant_tasks.build_manager import BuildManager
from tasks2events.occupant_tasks.build_owner import BuildOwner
from tasks2events.occupant_tasks.build_resident import BuildResident
from tasks2events.occupant_tasks.build_tenant import BuildTenant
from tasks2events.occupant_tasks.build_represent import BuildRepresent
from tasks2events.occupant_tasks.meeting_writer import BuildMeetingWriter
from tasks2events.occupant_tasks.meeting_advisor import BuildMeetingAdvisor
from tasks2events.occupant_tasks.meeting_attendance import BuildMeetingAttendance
from tasks2events.occupant_tasks.meeting_president import BuildMeetingPresident
from tasks2events.occupant_tasks.meeting_voted_president import (
BuildMeetingVotedPresident,
)
__all__ = [
"AuthDefaultEventBlock",
"SuperUserEventBlock",
"BuildManager",
"BuildOwner",
"BuildResident",
"BuildTenant",
"BuildRepresent",
"BuildMeetingWriter",
"BuildMeetingPresident",
"BuildMeetingAdvisor",
"BuildMeetingAttendance",
"BuildMeetingVotedPresident",
]

View File

@ -0,0 +1,22 @@
from api_events.tasks2events.default_abstract import AddEventFunctionality
class AuthDefaultEventBlock(AddEventFunctionality):
service_code = "AUTH"
related_code = "DF-USER"
events = [
{"function_code": "e672846d-cc45-4d97-85d5-6f96747fac67"},
{"function_code": "cee96b9b-8487-4e9f-aaed-2e8c79687bf9"},
{"function_code": "48379bb2-ba81-4d8e-a9dd-58837cfcbf67"},
{"function_code": "f09f7c1a-bee6-4e32-8444-962ec8f39091"},
{"function_code": "87a15ade-3474-4206-b574-bbf8580cbb14"},
{"function_code": "c519f9af-92e1-47b2-abf7-5a3316d075f7"},
{"function_code": "8b586848-2fb3-4161-abbe-642157eec7ce"},
{"function_code": "5cc22e4e-a0f7-4077-be41-1871feb3dfd1"},
{"function_code": "c90f3334-10c9-4181-b5ff-90d98a0287b2"},
{"function_code": "e3ca6e24-b9f8-4127-949c-3bfa364e3513"},
{"function_code": "c140cd5f-307f-4046-a93e-3ade032a57a7"},
]
def __new__(cls, *args, **kwargs):
return super().retrieve_events(cls.events)

View File

@ -0,0 +1,16 @@
class AddEventFunctionality:
@classmethod
def retrieve_events(cls, events) -> list[tuple[int, str]]:
from database_sql_models import Events
from sqlalchemy import select
get_event_ids = Events.session.execute(
select(Events.id, Events.uu_id).where(
Events.function_code.in_([event["function_code"] for event in events])
)
).all()
if get_event_ids:
return [(get_event[0], str(get_event[1])) for get_event in get_event_ids]
else:
raise Exception("No event found")

View File

@ -0,0 +1,83 @@
from api_events.tasks2events.default_abstract import AddEventFunctionality
class SuperUserEventBlock(AddEventFunctionality):
service_code = "SRE-SUE"
related_code = "SUE"
events = [
{"function_code": "2d1513f4-44ed-4fa3-84d1-dfbd0eadf9a1"},
{"function_code": "0a05f03c-6ed8-4230-a4ff-6e7cf886909b"},
{"function_code": "e05cf22c-16c4-450b-86c8-417896a26afc"},
{"function_code": "3ae16d66-090b-4d27-b567-cce1b10a1c3b"},
{"function_code": "1483a8a2-d244-4593-b9f8-f1b4bcbefcd5"},
{"function_code": "8eb50c24-4bdc-4309-9836-f7048daee409"},
{"function_code": "d08a9470-1eb0-4890-a9e8-b6686239d7e9"},
{"function_code": "d26a1a3c-eaeb-4d01-b35b-a5ed714e29c0"},
{"function_code": "68b3b5ed-b74c-4a27-820f-3959214e94e9"},
{"function_code": "a2271854-6b90-43da-a440-a62b70d90528"},
{"function_code": "5ad38a66-1189-451e-babb-77de2d63d757"},
{"function_code": "e3876bfe-8847-4dea-ae36-e709f7431930"},
{"function_code": "6320d696-1fd1-49f9-860a-8f22e5b8a68d"},
{"function_code": "76f11a08-5f4a-4e1f-961f-aaef21699acd"},
{"function_code": "41ea7f29-006a-4310-b5c4-b2a0e1a504bd"},
{"function_code": "f6900cb5-ac5b-478e-8e7c-fa87e65cd2e5"},
{"function_code": "2cb90331-c1b4-4923-8314-8111326b621a"},
{"function_code": "d8bd3985-7f3b-4267-a74e-d5017e4ea9f8"},
{"function_code": "4172706f-06c9-4c38-9ac8-59085a72f80a"},
{"function_code": "1e272e4f-6c1e-418b-91a7-be8b06c875da"},
{"function_code": "44b72beb-53a8-407b-a12a-76e74b65794d"},
{"function_code": "30c54cce-3303-4d36-959a-b64e383ae177"},
{"function_code": "3524ae42-0825-4af7-be85-7c890a4f65d3"},
{"function_code": "3fc77829-f1ee-4511-a2ca-582daa03125b"},
{"function_code": "ca81c6d1-975a-4288-a27b-1069aea84afe"},
{"function_code": "23231c7d-4ff2-4b39-b71b-ea350d31fadf"},
{"function_code": "c6ea200e-fa17-4393-b390-37f5337c9c65"},
{"function_code": "ad952647-bcf8-482d-9e05-b2ee8086483f"},
{"function_code": "d5c7b5c4-7b4e-4d5b-8e3b-2b9c5f5d0c0b"},
{"function_code": "cb677c92-6b05-4122-af5c-12766fae8095"},
{"function_code": "1e1632c3-bb0e-46a5-8e45-da3f6d88ac43"},
{"function_code": "9015a076-d78c-463d-9474-ea343a125fb8"},
{"function_code": "8446ce0b-9310-4b9f-93e2-61f56a9dacd1"},
{"function_code": "8984a519-99bf-4f25-8f34-2e1aebba468c"},
{"function_code": "8f619257-19fd-404f-b713-7392c588dc36"},
{"function_code": "7724cfbb-c0ee-4261-959b-61b84e88a34f"},
{"function_code": "5329f35d-ff9d-4656-a831-ba9c8204e483"},
{"function_code": "b1cd7c0a-1458-472b-894f-3adc857c8512"},
{"function_code": "5eb04057-7a74-4555-b2c6-14eda32dae89"},
{"function_code": "caf914fa-0899-4b0b-a85a-3d40fdaa06a5"},
{"function_code": "ffdc445f-da10-4ce4-9531-d2bdb9a198ae"},
{"function_code": "b0e55a7e-af81-468c-b46c-a6b3a6b68d5d"},
{"function_code": "1f9c3a9c-e5bd-4dcd-9b9a-3742d7e03a27"},
{"function_code": "68b3b5ed-b74c-4a27-820f-3959214e94e9"},
{"function_code": "a2271854-6b90-43da-a440-a62b70d90528"},
{"function_code": "5ad38a66-1189-451e-babb-77de2d63d757"},
{"function_code": "e3876bfe-8847-4dea-ae36-e709f7431930"},
{"function_code": "9c251d7d-da70-4d63-a72c-e69c26270442"},
{"function_code": "6f1406ac-577d-4f2c-8077-71fff2252c5f"},
{"function_code": "88d37b78-1ac4-4513-9d25-090ac3a24f31"},
{"function_code": "df18e489-a63c-477f-984c-aa52d30640ad"},
{"function_code": "e0ac1269-e9a7-4806-9962-219ac224b0d0"},
{"function_code": "b860e37a-e19b-4c45-9543-461241f7587c"},
{"function_code": "fb403f69-11ed-4f4f-ad71-5e6fb4a793d2"},
{"function_code": "58fdf95e-2110-4ed6-9c26-95f4be87eaee"},
{"function_code": "70b4666f-4ceb-46ec-b89e-24be8712f0e7"},
{"function_code": "8fd04d94-68fb-4a07-9549-8b47aee3a870"},
{"function_code": "b78ca45c-b9f4-41f6-9ddb-2c6f2faa2570"},
{"function_code": "5c10d6ae-2aee-4243-a7c3-94826d028d13"},
{"function_code": "0a68cb44-271a-4829-81f6-cd99a5f326b4"},
{"function_code": "6bc7035c-3b53-4c0a-8cc9-1ec9c6af1e29"},
{"function_code": "7b58ed84-9a65-4588-994d-30df8366b050"},
{"function_code": "eb36de59-8268-4d96-80b6-5d01c12bf0b1"},
{"function_code": "dce10509-0da5-46fb-af3c-a81d54d5481c"},
{"function_code": "f0fdfe1b-806b-4175-ad50-a1a165c0dfb7"},
{"function_code": "42328809-b516-477b-82cc-2d6fadf28843"},
{"function_code": "5c10d6ae-2aee-4243-a7c3-94826d028d13"},
{"function_code": "0a68cb44-271a-4829-81f6-cd99a5f326b4"},
{"function_code": "6bc7035c-3b53-4c0a-8cc9-1ec9c6af1e29"},
{"function_code": "7b58ed84-9a65-4588-994d-30df8366b050"},
{"function_code": "5702f0a9-fe8f-4aae-922e-6e04b497ef6a"},
{"function_code": "c93a3009-65a0-498d-9191-04484d5cde81"},
]
def __new__(cls, *args, **kwargs):
return super().retrieve_events(cls.events)

View File

@ -0,0 +1,37 @@
"""
Toplantı Başkanı Toplantı Başkanı MT-PRS Toplantı
Toplantı Katip Toplantıda tutanak tutan kişi MT-WRT Toplantı
Toplantı Katılımcısı Toplantıda sadece katılan kişi MT-ATT Toplantı
Toplantı Danışman Toplantıda danışmanlık yapan kişi MT-ADV Toplantı
Daire Sahibi Daire Sahibi FL-OWN Daire
Daire Kiracısı Daire Kiracısı FL-TEN Daire
Daire Sakini Daire Sakini FL-RES Daire
Daire Sakini Vekili Daire Sakini Vekili FL-REP Daire
Bina Avukatı Bina Avukatı BU-ATT Bina
Bina Avukatı Yardımcısı Bina Avukatı Yardımcısı BU-ATA Bina
Bina Denetmen Yardımcısı Bina Denetmen Yardımcısı BU-SPA Bina
Bina Denetmeni Bina Denetmeni BU-SPV Bina
Bina Yönetici Yardımcısı Bina Yönetici Yardımcısı BU-MNA Bina
Bina Yöneticisi Bina Yöneticisi BU-MNG Bina
Bina Muhasabecisi Bina Muhasabecisi BU-ACC Bina
"""
MT_PRS = []
MT_WRT = []
MT_ATT = []
MT_ADV = []
FL_OWN = []
FL_TEN = []
FL_RES = []
FL_REP = []
BU_ATT = []
BU_ATA = []
BU_SPA = []
BU_SPV = []
BU_MNA = []
BU_ACC = []

View File

@ -0,0 +1,21 @@
from api_events.tasks2events.default_abstract import AddEventFunctionality
class BuildManager(AddEventFunctionality):
service_code = "SRO-BU-MNG"
related_code = "BU-MNG"
events = [
{"function_code": "dce10509-0da5-46fb-af3c-a81d54d5481c"},
{"function_code": "0d2bc5c9-d4b1-4951-8305-69da4a687fdc"},
{"function_code": "0a68cb44-271a-4829-81f6-cd99a5f326b4"},
{"function_code": "5c10d6ae-2aee-4243-a7c3-94826d028d13"},
{"function_code": "d0bfa20c-841d-421c-98e6-d308f938d16a"},
{"function_code": "68b3b5ed-b74c-4a27-820f-3959214e94e9"},
{"function_code": "f6900cb5-ac5b-478e-8e7c-fa87e65cd2e5"},
{"function_code": "92413636-53a8-4a05-842c-1485a64e00d1"},
{"function_code": "bdcba521-0116-441c-ace1-84c5b68c86c7"},
{"function_code": "c0b65098-9c79-4212-b1d0-c7e7836cf141"},
]
def __new__(cls, *args, **kwargs):
return super().retrieve_events(cls.events)

View File

@ -0,0 +1,13 @@
from api_events.tasks2events.default_abstract import AddEventFunctionality
class BuildOwner(AddEventFunctionality):
service_code = "SRO-FL-OWN"
related_code = "FL-OWN"
events = [
{"function_code": "bdcba521-0116-441c-ace1-84c5b68c86c7"},
]
def __new__(cls, *args, **kwargs):
return super().retrieve_events(cls.events)

View File

@ -0,0 +1,13 @@
from api_events.tasks2events.default_abstract import AddEventFunctionality
class BuildRepresent(AddEventFunctionality):
service_code = "SRO-FL-REP"
related_code = "FL-REP"
events = [
{"function_code": "bdcba521-0116-441c-ace1-84c5b68c86c7"},
]
def __new__(cls, *args, **kwargs):
return super().retrieve_events(cls.events)

View File

@ -0,0 +1,12 @@
from api_events.tasks2events.default_abstract import AddEventFunctionality
class BuildResident(AddEventFunctionality):
service_code = "SRO-FL-RES"
related_code = "FL-RES"
events = [
{"function_code": "bdcba521-0116-441c-ace1-84c5b68c86c7"},
]
def __new__(cls, *args, **kwargs):
return super().retrieve_events(cls.events)

Some files were not shown because too many files have changed in this diff Show More