generated from dopt-python/py311
1106 lines
37 KiB
Python
1106 lines
37 KiB
Python
from __future__ import annotations
|
|
|
|
import copy
|
|
import datetime
|
|
from pprint import pformat
|
|
from typing import TYPE_CHECKING, Any, cast
|
|
|
|
import polars as pl
|
|
import sqlalchemy as sa
|
|
from dopt_basics.result_pattern import wrap_result
|
|
from sqlalchemy.dialects.sqlite import insert as sqlite_insert
|
|
|
|
from wce_crm import db
|
|
from wce_crm.constants import TIMEZONE_CEST
|
|
from wce_crm.data_models import (
|
|
FIELD_DB_MAPPING_GRUNDERERFASSUNG_PERSONEN,
|
|
FIELD_DB_MAPPING_GRUNDERERFASSUNG_UNTERNEHMEN,
|
|
Beratungsgespraech_Einzelgespraech,
|
|
Beratungsgespraech_Vorgang,
|
|
InitRec,
|
|
Page_InitRec_Form_Data,
|
|
)
|
|
from wce_crm.logging import logger_back as logger
|
|
from wce_crm.types import (
|
|
CompanyInfo,
|
|
CompanyProfileConsultationEntry,
|
|
CompanyProfileConsultations,
|
|
ConsultingType,
|
|
ContactPersonInfo,
|
|
EntityIds,
|
|
EntityType,
|
|
LinkingConsultationsEntryCompany,
|
|
LinkingConsultationsEntryPerson,
|
|
MainPageEntry,
|
|
RecordingType,
|
|
)
|
|
|
|
if TYPE_CHECKING:
|
|
from dopt_basics.datastructures import DualDict
|
|
|
|
from wce_crm.types import ConsId, ExtAnId, ExtMaId, RecId
|
|
|
|
|
|
def _transform_for_gui_output(
|
|
data: pl.DataFrame,
|
|
) -> pl.DataFrame:
|
|
q = (
|
|
data.lazy()
|
|
.with_columns(
|
|
pl.col(pl.Datetime).dt.to_string("%d.%m.%Y"),
|
|
pl.col(pl.Date).dt.to_string("%d.%m.%Y"),
|
|
pl.when(pl.col(pl.Boolean))
|
|
.then(pl.lit("Ja"))
|
|
.otherwise(pl.lit("Nein"))
|
|
.name.keep(),
|
|
)
|
|
.with_columns(pl.all().cast(pl.String))
|
|
)
|
|
|
|
return q.collect()
|
|
|
|
|
|
def initrec_comp_search_choices() -> tuple[tuple[str, int], ...]:
|
|
# TODO no reload functionality
|
|
logger.debug("[Call backend] comp_search_choices")
|
|
q = db.DF_CRM_MASTER.lazy()
|
|
counter = pl.int_range(0, pl.len()).over(pl.col.ma_unternehmensname)
|
|
q = q.with_columns(
|
|
dedupl=pl.when(counter == 0)
|
|
.then(pl.col.ma_unternehmensname)
|
|
.otherwise(pl.format("{} ({})", pl.col.ma_unternehmensname, counter))
|
|
)
|
|
df = q.collect()
|
|
|
|
return tuple(zip(df["dedupl"], df["ma_id"]))
|
|
|
|
|
|
def initrec_comp_search_get_info(
|
|
ma_id: ExtMaId,
|
|
) -> CompanyInfo:
|
|
logger.debug("[Call backend] comp_search_get_info")
|
|
df = db.DF_CRM_MASTER.filter(pl.col.ma_id == ma_id)
|
|
if df.height > 1 or df.height == 0:
|
|
raise ValueError(f"Größe des zurückgelieferten Datenpakets ungültig: {df.height}")
|
|
|
|
df = _transform_for_gui_output(df)
|
|
return cast(CompanyInfo, df.row(0, named=True))
|
|
|
|
|
|
def initrec_comp_contact_person_search_choices(
|
|
ma_id: ExtMaId | None,
|
|
use_both_names: bool,
|
|
) -> tuple[tuple[str, int], ...]:
|
|
# TODO no reload functionality
|
|
logger.debug("[Call backend] contact_person_search_choices")
|
|
q = db.DF_CONTACT_PERSON.lazy()
|
|
if ma_id is not None:
|
|
q = q.filter(pl.col.ma_id == ma_id)
|
|
|
|
dedupl_col = pl.col.an_nachname
|
|
if use_both_names:
|
|
q = q.with_columns(
|
|
name_search=(pl.format("{}, {}", pl.col.an_nachname, pl.col.an_vorname))
|
|
)
|
|
dedupl_col = pl.col.name_search
|
|
|
|
counter = pl.int_range(0, pl.len()).over(dedupl_col)
|
|
q = q.with_columns(
|
|
dedupl=pl.when(counter == 0)
|
|
.then(dedupl_col)
|
|
.otherwise(pl.format("{} ({})", dedupl_col, counter))
|
|
)
|
|
df = q.collect()
|
|
|
|
return tuple(zip(df["dedupl"], df["an_id"]))
|
|
|
|
|
|
def initrec_comp_contact_person_search_get_info(
|
|
an_id: ExtAnId,
|
|
) -> ContactPersonInfo:
|
|
logger.debug("[Call backend] contact_person_search_get_info")
|
|
df = db.DF_CONTACT_PERSON.filter(pl.col.an_id == an_id)
|
|
if df.height > 1 or df.height == 0:
|
|
raise ValueError(f"Größe des zurückgelieferten Datenpakets ungültig: {df.height}")
|
|
|
|
df = _transform_for_gui_output(df)
|
|
return cast(ContactPersonInfo, df.row(0, named=True))
|
|
|
|
|
|
# // internals
|
|
# TODO check removal
|
|
# def initrec_company_insert_initial_recording(
|
|
# data: dict[str, Any],
|
|
# ) -> RecId:
|
|
# logger.debug("[Call backend] insert_initial_recording")
|
|
# stmt = db.grunderfassung_unternehmen.insert()
|
|
# with db.ENGINE.begin() as conn:
|
|
# ret = conn.execute(stmt, data)
|
|
|
|
# if ret.rowcount == 0:
|
|
# raise IOError("Entry was not inserted correctly")
|
|
|
|
# prim_keys = ret.inserted_primary_key
|
|
# assert prim_keys
|
|
|
|
# return prim_keys[0]
|
|
|
|
|
|
# def initrec_company_update_initial_recording(
|
|
# id_: RecId,
|
|
# data: dict[str, Any],
|
|
# ) -> None:
|
|
# logger.debug("[Call backend] update_initial_recording")
|
|
# stmt = db.grunderfassung_unternehmen.update().where(
|
|
# db.grunderfassung_unternehmen.c.un_id == id_
|
|
# )
|
|
# with db.ENGINE.begin() as conn:
|
|
# conn.execute(stmt, data)
|
|
|
|
|
|
# def initrec_company_to_db(
|
|
# auto_form_data: InitRec,
|
|
# ) -> InitRec:
|
|
# logger.debug("[AutoForm -- backend] Call database saving routine...")
|
|
|
|
# dump_data = copy.deepcopy(auto_form_data.db_data)
|
|
# dump_data["geloescht"] = auto_form_data.geloescht
|
|
|
|
# with db.ENGINE.begin() as conn:
|
|
# if auto_form_data.ids.un_id is None:
|
|
# logger.debug("[AutoForm -- backend] Insert...")
|
|
|
|
# stmt = db.grunderfassung_unternehmen.insert().returning(
|
|
# db.grunderfassung_unternehmen.c.un_id,
|
|
# db.grunderfassung_unternehmen.c.Metadaten_aktualisierung,
|
|
# db.grunderfassung_unternehmen.c.geloescht,
|
|
# )
|
|
# ret = conn.execute(stmt, dump_data)
|
|
|
|
# from_db = ret.mappings().fetchall()
|
|
# assert len(from_db) == 1, "expected excactly one returned row"
|
|
# data_from_db = from_db[0]
|
|
# auto_form_data.ids.un_id = data_from_db["un_id"]
|
|
# auto_form_data.geloescht = data_from_db["geloescht"]
|
|
# auto_form_data.db_data["Metadaten_aktualisierung"] = data_from_db[
|
|
# "Metadaten_aktualisierung"
|
|
# ]
|
|
|
|
# logger.debug("[AutoForm -- backend] Inserted InitRec Company successfully")
|
|
|
|
# else:
|
|
# logger.debug("[AutoForm -- backend] Update...")
|
|
# stmt = (
|
|
# db.grunderfassung_unternehmen.update()
|
|
# .where(db.grunderfassung_unternehmen.c.un_id == auto_form_data.ids.un_id)
|
|
# .returning(
|
|
# db.grunderfassung_unternehmen.c.Metadaten_aktualisierung,
|
|
# db.grunderfassung_unternehmen.c.geloescht,
|
|
# )
|
|
# )
|
|
# ret = conn.execute(stmt, dump_data)
|
|
|
|
# from_db = ret.mappings().fetchall()
|
|
# assert len(from_db) == 1, "expected excatly one returned row"
|
|
# data_from_db = from_db[0]
|
|
|
|
# auto_form_data.db_data["Metadaten_aktualisierung"] = data_from_db[
|
|
# "Metadaten_aktualisierung"
|
|
# ]
|
|
|
|
# logger.debug(
|
|
# "[AutoForm -- backend] Updated InitRec Company with ID %d successfully",
|
|
# auto_form_data.ids.un_id,
|
|
# )
|
|
|
|
# return auto_form_data
|
|
|
|
|
|
# def initrec_company_from_db(
|
|
# id_: RecId,
|
|
# ) -> InitRec:
|
|
# logger.debug("[AutoForm -- backend] Call database loading routine...")
|
|
# stmt = db.grunderfassung_unternehmen.select().where(
|
|
# db.grunderfassung_unternehmen.c.un_id == id_
|
|
# )
|
|
# with db.ENGINE.connect() as conn:
|
|
# ret = conn.execute(stmt)
|
|
|
|
# from_db = ret.mappings().all()
|
|
# assert len(from_db) == 1, "not excactly one company initial recording obtained"
|
|
# data_from_db = dict(from_db[0])
|
|
|
|
# geloescht = data_from_db["geloescht"]
|
|
# del data_from_db["geloescht"]
|
|
|
|
# return InitRec(
|
|
# ids=EntityIds(un_id=id_),
|
|
# # rec_id=id_, # TODO remove
|
|
# geloescht=geloescht,
|
|
# db_data=data_from_db,
|
|
# )
|
|
|
|
|
|
# def initrec_person_to_db(
|
|
# auto_form_data: InitRec,
|
|
# ) -> InitRec:
|
|
# logger.debug("[AutoForm -- backend] Call database saving routine...")
|
|
|
|
# dump_data = copy.deepcopy(auto_form_data.db_data)
|
|
# dump_data["geloescht"] = auto_form_data.geloescht
|
|
|
|
# with db.ENGINE.begin() as conn:
|
|
# if auto_form_data.ids.pers_id is None:
|
|
# logger.debug("[AutoForm -- backend] Insert...")
|
|
|
|
# stmt = sa.insert(db.t_grunderfassung_personen).returning(
|
|
# db.t_grunderfassung_personen.c.pers_id,
|
|
# db.t_grunderfassung_personen.c.Metadaten_aktualisierung,
|
|
# db.t_grunderfassung_personen.c.geloescht,
|
|
# )
|
|
# stmt_compiled = str(stmt.compile(db.ENGINE))
|
|
# logger.debug(
|
|
# "[AutoForm -- backend] Data to insert:\nStatement: %s\n%s",
|
|
# stmt_compiled,
|
|
# pformat(dump_data),
|
|
# )
|
|
|
|
# ret = conn.execute(stmt, dump_data)
|
|
|
|
# from_db = ret.mappings().fetchall()
|
|
# assert len(from_db) == 1, "expected excactly one returned row"
|
|
# data_from_db = from_db[0]
|
|
# auto_form_data.ids.pers_id = data_from_db["pers_id"]
|
|
# auto_form_data.geloescht = data_from_db["geloescht"]
|
|
# auto_form_data.db_data["Metadaten_aktualisierung"] = data_from_db[
|
|
# "Metadaten_aktualisierung"
|
|
# ]
|
|
|
|
# logger.debug("[AutoForm -- backend] Inserted InitRec Person successfully")
|
|
|
|
# else:
|
|
# logger.debug("[AutoForm -- backend] Update...")
|
|
# stmt = (
|
|
# db.t_grunderfassung_personen.update()
|
|
# .where(db.t_grunderfassung_personen.c.pers_id == auto_form_data.ids.pers_id)
|
|
# .returning(
|
|
# db.t_grunderfassung_personen.c.Metadaten_aktualisierung,
|
|
# db.t_grunderfassung_personen.c.geloescht,
|
|
# )
|
|
# )
|
|
# ret = conn.execute(stmt, dump_data)
|
|
|
|
# from_db = ret.mappings().fetchall()
|
|
# assert len(from_db) == 1, "expected excatly one returned row"
|
|
# data_from_db = from_db[0]
|
|
|
|
# auto_form_data.db_data["Metadaten_aktualisierung"] = data_from_db[
|
|
# "Metadaten_aktualisierung"
|
|
# ]
|
|
|
|
# logger.debug(
|
|
# "[AutoForm -- backend] Updated InitRec Person with ID %d successfully",
|
|
# auto_form_data.ids.pers_id,
|
|
# )
|
|
|
|
# return auto_form_data
|
|
|
|
|
|
# def initrec_person_from_db(
|
|
# id_: RecId,
|
|
# ) -> InitRec:
|
|
# logger.debug("[AutoForm -- backend] Call database loading routine...")
|
|
# stmt = db.t_grunderfassung_personen.select().where(
|
|
# db.t_grunderfassung_personen.c.pers_id == id_
|
|
# )
|
|
# with db.ENGINE.connect() as conn:
|
|
# ret = conn.execute(stmt)
|
|
|
|
# from_db = ret.mappings().all()
|
|
# assert len(from_db) == 1, "not excactly one company initial recording obtained"
|
|
# data_from_db = dict(from_db[0])
|
|
|
|
# geloescht = data_from_db["geloescht"]
|
|
# del data_from_db["geloescht"]
|
|
|
|
# return InitRec(
|
|
# ids=EntityIds(pers_id=id_),
|
|
# # rec_id=id_, # TODO remove
|
|
# geloescht=geloescht,
|
|
# db_data=data_from_db,
|
|
# )
|
|
|
|
|
|
# TODO check removal
|
|
# def initrec_company_get_initial_recording(
|
|
# id_: RecId,
|
|
# ) -> dict[str, Any]:
|
|
# logger.debug("[Call backend] get_initial_recording")
|
|
# stmt = db.grunderfassung_unternehmen.select().where(
|
|
# db.grunderfassung_unternehmen.c.un_id == id_
|
|
# )
|
|
# with db.ENGINE.connect() as conn:
|
|
# ret = conn.execute(stmt)
|
|
|
|
# results = ret.mappings().all()
|
|
# if not results:
|
|
# raise KeyError(f"Database ID {id_} not found")
|
|
|
|
# assert len(results) == 1, "more than one company initial recording obtained"
|
|
|
|
# row = results[0]
|
|
# assert row, "row was not obtained"
|
|
|
|
# return dict(row)
|
|
|
|
|
|
def _rename_db_data(
|
|
db_data: dict[str, Any],
|
|
mapping: DualDict,
|
|
) -> dict[str, Any]:
|
|
new_db_data = copy.deepcopy(db_data)
|
|
|
|
for k, v in db_data.items():
|
|
if k in mapping:
|
|
new_db_data[mapping[k]] = v
|
|
del new_db_data[k]
|
|
|
|
if k in mapping.inverted:
|
|
new_db_data[mapping.inverted[k]] = v
|
|
del new_db_data[k]
|
|
|
|
return new_db_data
|
|
|
|
|
|
def page_initrec_to_db(
|
|
data: InitRec,
|
|
) -> InitRec:
|
|
|
|
with db.ENGINE.begin() as conn:
|
|
# person
|
|
dump_data = _rename_db_data(
|
|
data.form_data.person, FIELD_DB_MAPPING_GRUNDERERFASSUNG_PERSONEN
|
|
)
|
|
dump_data["geloescht"] = data.geloescht
|
|
|
|
if data.ids.pers_id is None:
|
|
logger.debug("[InitRec -- backend] Insert...")
|
|
|
|
stmt = sa.insert(db.t_grunderfassung_personen).returning(
|
|
db.t_grunderfassung_personen.c.pers_id,
|
|
db.t_grunderfassung_personen.c.aktualisiert,
|
|
db.t_grunderfassung_personen.c.geloescht,
|
|
)
|
|
stmt_compiled = str(stmt.compile(db.ENGINE))
|
|
logger.debug(
|
|
"[InitRec -- backend] Data to insert:\nStatement: %s\n%s",
|
|
stmt_compiled,
|
|
pformat(dump_data),
|
|
)
|
|
|
|
ret = conn.execute(stmt, dump_data)
|
|
|
|
from_db = ret.mappings().fetchall()
|
|
assert len(from_db) == 1, "expected excactly one returned row"
|
|
data_from_db = from_db[0]
|
|
|
|
data.ids.pers_id = data_from_db["pers_id"]
|
|
data.geloescht = data_from_db["geloescht"]
|
|
data.form_data.person["Metadaten_aktualisierung"] = data_from_db["aktualisiert"]
|
|
|
|
logger.debug("[AutoForm -- backend] Inserted InitRec Person successfully")
|
|
|
|
else:
|
|
logger.debug("[AutoForm -- backend] Update...")
|
|
stmt = (
|
|
db.t_grunderfassung_personen.update()
|
|
.where(db.t_grunderfassung_personen.c.pers_id == data.ids.pers_id)
|
|
.returning(
|
|
db.t_grunderfassung_personen.c.Metadaten_aktualisierung,
|
|
db.t_grunderfassung_personen.c.geloescht,
|
|
)
|
|
)
|
|
ret = conn.execute(stmt, dump_data)
|
|
|
|
from_db = ret.mappings().fetchall()
|
|
assert len(from_db) == 1, "expected excatly one returned row"
|
|
data_from_db = from_db[0]
|
|
|
|
data.geloescht = data_from_db["geloescht"]
|
|
data.form_data.person["Metadaten_aktualisierung"] = data_from_db[
|
|
"Metadaten_aktualisierung"
|
|
]
|
|
|
|
logger.debug(
|
|
"[InitRec -- backend] Updated InitRec Person with ID %d successfully",
|
|
data.ids.pers_id,
|
|
)
|
|
|
|
# company
|
|
if data.recording_type is RecordingType.WITH_COMPANY:
|
|
# insert into company table and add additional information
|
|
assert data.ids.un_id, "company ID not set"
|
|
assert data.ids.an_id, "contact person (an) ID not set"
|
|
assert data.ids.pers_id, "person ID not set"
|
|
|
|
stmt = (
|
|
sqlite_insert(db.t_unternehmen)
|
|
.values(un_id=data.ids.un_id, geloescht=None)
|
|
.on_conflict_do_nothing(index_elements=["un_id"])
|
|
)
|
|
conn.execute(stmt)
|
|
|
|
# additional information
|
|
dump_data = _rename_db_data(
|
|
data.form_data.company, FIELD_DB_MAPPING_GRUNDERERFASSUNG_UNTERNEHMEN
|
|
)
|
|
dump_data["geloescht"] = data.geloescht
|
|
stmt = sqlite_insert(db.t_zuordnung_personen_unternehmen).values(
|
|
**dump_data, pers_id=data.ids.pers_id
|
|
)
|
|
stmt = stmt.on_conflict_do_update(
|
|
index_elements=["un_id", "pers_id"],
|
|
index_where=sa.text("geloescht IS NULL"),
|
|
set_={
|
|
"an_id": stmt.excluded.an_id,
|
|
"Partnersuche__kanal_aufmerksamkeit": stmt.excluded.Partnersuche__kanal_aufmerksamkeit,
|
|
"aktualisiert": datetime.datetime.now(datetime.UTC),
|
|
},
|
|
).returning(db.t_zuordnung_personen_unternehmen.c.id)
|
|
ret = conn.execute(stmt)
|
|
|
|
from_db = ret.mappings().fetchall()
|
|
assert len(from_db) == 1, "expected excatly one returned row"
|
|
data_from_db = from_db[0]
|
|
data.ids.link_id = data_from_db["id"]
|
|
|
|
return data
|
|
|
|
|
|
def page_initrec_from_db(
|
|
ids: EntityIds,
|
|
) -> InitRec:
|
|
recording_type = RecordingType.WITHOUT_COMPANY
|
|
if ids.valid(EntityType.COMPANY):
|
|
recording_type = RecordingType.WITH_COMPANY
|
|
|
|
# person
|
|
assert ids.pers_id, "person ID not set"
|
|
logger.debug("[AutoForm -- backend] Call database loading routine...")
|
|
stmt = db.t_grunderfassung_personen.select().where(
|
|
db.t_grunderfassung_personen.c.pers_id == ids.pers_id
|
|
)
|
|
with db.ENGINE.connect() as conn:
|
|
ret = conn.execute(stmt)
|
|
|
|
from_db = ret.mappings().all()
|
|
assert len(from_db) == 1, "not excactly one company initial recording obtained"
|
|
data_person_table = dict(from_db[0])
|
|
|
|
data_person_table = _rename_db_data(
|
|
data_person_table, FIELD_DB_MAPPING_GRUNDERERFASSUNG_PERSONEN
|
|
)
|
|
geloescht = data_person_table["geloescht"]
|
|
del data_person_table["geloescht"]
|
|
|
|
data_company_table: dict[str, Any] = {}
|
|
if recording_type is RecordingType.WITH_COMPANY:
|
|
assert ids.un_id, "company ID not set"
|
|
|
|
if ids.link_id:
|
|
stmt = sa.select(
|
|
db.t_zuordnung_personen_unternehmen.c.un_id,
|
|
db.t_zuordnung_personen_unternehmen.c.an_id,
|
|
db.t_zuordnung_personen_unternehmen.c.Partnersuche__kanal_aufmerksamkeit,
|
|
).where(
|
|
db.t_zuordnung_personen_unternehmen.c.id == ids.link_id,
|
|
)
|
|
else:
|
|
stmt = sa.select(
|
|
db.t_zuordnung_personen_unternehmen.c.un_id,
|
|
db.t_zuordnung_personen_unternehmen.c.an_id,
|
|
db.t_zuordnung_personen_unternehmen.c.Partnersuche__kanal_aufmerksamkeit,
|
|
).where(
|
|
db.t_zuordnung_personen_unternehmen.c.pers_id == ids.pers_id,
|
|
db.t_zuordnung_personen_unternehmen.c.un_id == ids.un_id,
|
|
db.t_zuordnung_personen_unternehmen.c.geloescht.is_(None),
|
|
)
|
|
|
|
with db.ENGINE.connect() as conn:
|
|
ret = conn.execute(stmt)
|
|
|
|
from_db = ret.mappings().all()
|
|
assert len(from_db) == 1, "not excactly one company initial recording obtained"
|
|
data_company_table = dict(from_db[0])
|
|
|
|
data_company_table = _rename_db_data(
|
|
data_person_table, FIELD_DB_MAPPING_GRUNDERERFASSUNG_UNTERNEHMEN
|
|
)
|
|
|
|
form_data = Page_InitRec_Form_Data(
|
|
metadata={},
|
|
person=data_person_table,
|
|
company=data_company_table,
|
|
)
|
|
|
|
return InitRec(
|
|
ids=ids,
|
|
recording_type=recording_type,
|
|
geloescht=geloescht,
|
|
form_data=form_data,
|
|
)
|
|
|
|
|
|
# def initrec_company_delete_initial_recording(
|
|
# id_: RecId,
|
|
# ) -> None:
|
|
# logger.debug("[Call backend] delete_initial_recording")
|
|
# stmt = db.grunderfassung_unternehmen.delete().where(
|
|
# db.grunderfassung_unternehmen.c.un_id == id_
|
|
# )
|
|
# with db.ENGINE.begin() as conn:
|
|
# ret = conn.execute(stmt)
|
|
|
|
# if ret.rowcount == 0:
|
|
# raise KeyError(f"Database ID {id_} not found for deletion")
|
|
|
|
|
|
# def initrec_person_insert_initial_recording(
|
|
# data: dict[str, Any],
|
|
# ) -> RecId:
|
|
# logger.debug("[Call backend] insert_initial_recording")
|
|
# stmt = db.grunderfassung_personen.insert()
|
|
# with db.ENGINE.begin() as conn:
|
|
# ret = conn.execute(stmt, data)
|
|
|
|
# if ret.rowcount == 0:
|
|
# raise IOError("Entry was not inserted correctly")
|
|
|
|
# prim_keys = ret.inserted_primary_key
|
|
# assert prim_keys
|
|
|
|
# return prim_keys[0]
|
|
|
|
|
|
# def initrec_person_update_initial_recording(
|
|
# id_: RecId,
|
|
# data: dict[str, Any],
|
|
# ) -> None:
|
|
# logger.debug("[Call backend] update_initial_recording")
|
|
# stmt = db.grunderfassung_personen.update().where(
|
|
# db.grunderfassung_personen.c.pers_id == id_
|
|
# )
|
|
# with db.ENGINE.begin() as conn:
|
|
# conn.execute(stmt, data)
|
|
|
|
|
|
# def initrec_person_get_initial_recording(
|
|
# id_: RecId,
|
|
# ) -> dict[str, Any]:
|
|
# logger.debug("[Call backend] get_initial_recording person")
|
|
# stmt = db.grunderfassung_personen.select().where(
|
|
# db.grunderfassung_personen.c.pers_id == id_
|
|
# )
|
|
# with db.ENGINE.connect() as conn:
|
|
# ret = conn.execute(stmt)
|
|
|
|
# results = ret.mappings().all()
|
|
# if not results:
|
|
# raise KeyError(f"Database ID {id_} not found")
|
|
|
|
# assert len(results) == 1, "more than one person initial recording obtained"
|
|
|
|
# row = results[0]
|
|
# assert row, "row was not obtained"
|
|
|
|
# return dict(row)
|
|
|
|
|
|
# def initrec_person_delete_initial_recording(
|
|
# id_: RecId,
|
|
# ) -> None:
|
|
# logger.debug("[Call backend] delete_initial_recording")
|
|
# stmt = db.grunderfassung_personen.delete().where(
|
|
# db.grunderfassung_personen.c.pers_id == id_
|
|
# )
|
|
# with db.ENGINE.begin() as conn:
|
|
# ret = conn.execute(stmt)
|
|
|
|
# if ret.rowcount == 0:
|
|
# raise KeyError(f"Database ID {id_} not found for deletion")
|
|
|
|
|
|
@wrap_result(10)
|
|
def page_consulting_to_db(
|
|
consultation_data: Beratungsgespraech_Vorgang,
|
|
) -> Beratungsgespraech_Vorgang:
|
|
logger.debug("[Consulting Page] Call database saving routine...")
|
|
|
|
with db.ENGINE.begin() as conn:
|
|
if consultation_data.vorgang_id is None:
|
|
# insert new "Vorgang"
|
|
insert_data_process = consultation_data.model_dump(
|
|
exclude={"vorgang_id", "beratungen"}
|
|
)
|
|
logger.debug(
|
|
"[Consulting Page] Call insert 'Vorgang' with data:\n%s",
|
|
pformat(insert_data_process),
|
|
)
|
|
|
|
stmt = db.t_beratung_vorgang.insert()
|
|
ret = conn.execute(stmt, insert_data_process)
|
|
if ret.rowcount == 0:
|
|
raise IOError("Entry was not inserted correctly")
|
|
prim_keys = ret.inserted_primary_key
|
|
assert prim_keys
|
|
|
|
consultation_data.vorgang_id = cast("ConsId", prim_keys[0])
|
|
logger.debug("[Consulting Page] Inserted 'Vorgang' successfully")
|
|
|
|
else:
|
|
logger.debug(
|
|
"[Consulting Page] VorgangID already set. ID: %d. Update...",
|
|
consultation_data.vorgang_id,
|
|
)
|
|
update_data_process = consultation_data.model_dump(exclude={"beratungen"})
|
|
stmt = db.t_beratung_vorgang.update().where(
|
|
db.t_beratung_vorgang.c.vorgang_id == consultation_data.vorgang_id
|
|
)
|
|
conn.execute(stmt, update_data_process)
|
|
|
|
rows_for_db_insert: list[dict[str, Any]] = []
|
|
rows_for_db_update: list[dict[str, Any]] = []
|
|
|
|
cons_sessions_inserted: list[Beratungsgespraech_Einzelgespraech] = []
|
|
for cons_session in consultation_data.beratungen:
|
|
cons_session.vorgang_id = consultation_data.vorgang_id
|
|
if cons_session.beratung_id is None:
|
|
row_data = cons_session.model_dump(exclude={"beratung_id"})
|
|
rows_for_db_insert.append(row_data)
|
|
cons_sessions_inserted.append(cons_session)
|
|
else:
|
|
row_data = cons_session.model_dump()
|
|
# new bind param to avoid name clashes
|
|
row_data["b_beratung_id"] = row_data["beratung_id"]
|
|
del row_data["beratung_id"]
|
|
rows_for_db_update.append(row_data)
|
|
|
|
if rows_for_db_update:
|
|
# ... update
|
|
logger.debug(
|
|
"[Consulting Page] Call update for sessions:\n%s", pformat(rows_for_db_update)
|
|
)
|
|
stmt = db.t_beratung_einzelberatung.update().where(
|
|
db.t_beratung_einzelberatung.c.beratung_id == sa.bindparam("b_beratung_id")
|
|
)
|
|
conn.execute(stmt, rows_for_db_update)
|
|
|
|
if rows_for_db_insert:
|
|
# ... insert
|
|
logger.debug(
|
|
"[Consulting Page] Call insert for sessions:\n%s", pformat(rows_for_db_insert)
|
|
)
|
|
stmt = db.t_beratung_einzelberatung.insert().returning(
|
|
db.t_beratung_einzelberatung.c.beratung_id
|
|
)
|
|
res = conn.execute(stmt, rows_for_db_insert)
|
|
new_cons_session_ids = cast(list[int], [row[0] for row in res.fetchall()])
|
|
|
|
assert len(cons_sessions_inserted) == len(new_cons_session_ids)
|
|
for cons_session, new_id in zip(cons_sessions_inserted, new_cons_session_ids):
|
|
cons_session.beratung_id = new_id
|
|
|
|
return consultation_data
|
|
|
|
|
|
@wrap_result(10)
|
|
def page_consulting_delete(
|
|
cons_id: ConsId,
|
|
) -> None:
|
|
timestamp_deleted = datetime.datetime.now(datetime.UTC)
|
|
dump_data: dict[str, Any] = {"geloescht": timestamp_deleted}
|
|
|
|
with db.ENGINE.begin() as conn:
|
|
stmt = db.t_beratung_vorgang.update().where(
|
|
db.t_beratung_vorgang.c.vorgang_id == cons_id
|
|
)
|
|
conn.execute(stmt, dump_data)
|
|
|
|
stmt = db.t_beratung_einzelberatung.update().where(
|
|
db.t_beratung_einzelberatung.c.vorgang_id == cons_id,
|
|
db.t_beratung_einzelberatung.c.geloescht.is_(None),
|
|
)
|
|
conn.execute(stmt, dump_data)
|
|
|
|
|
|
@wrap_result(11)
|
|
def page_consulting_from_db(
|
|
cons_id: ConsId,
|
|
) -> Beratungsgespraech_Vorgang:
|
|
# get "Vorgang" and all associated sessions to instantiate Pydantic data model
|
|
logger.debug("[Consulting Page] Call database reading routine...")
|
|
|
|
with db.ENGINE.connect() as conn:
|
|
# get the consultation process
|
|
stmt = db.t_beratung_vorgang.select().where(
|
|
db.t_beratung_vorgang.c.vorgang_id == cons_id
|
|
)
|
|
ret = conn.execute(stmt)
|
|
|
|
results = ret.mappings().all()
|
|
|
|
if not results:
|
|
raise KeyError(f"Database ID {cons_id} not found")
|
|
|
|
assert len(results) == 1, "more than one consulting process obtained"
|
|
consultation_data_db = results[0]
|
|
consultation_data = Beratungsgespraech_Vorgang(
|
|
vorgang_id=consultation_data_db["vorgang_id"],
|
|
un_id=consultation_data_db["un_id"],
|
|
pers_id=consultation_data_db["pers_id"],
|
|
titel=consultation_data_db["titel"],
|
|
beratungs_typ=consultation_data_db["beratungs_typ"],
|
|
erstellt=consultation_data_db["erstellt"],
|
|
aktualisiert=consultation_data_db["aktualisiert"],
|
|
geloescht=consultation_data_db["geloescht"],
|
|
beratungen=[],
|
|
)
|
|
|
|
if consultation_data.geloescht is not None:
|
|
logger.info(
|
|
(
|
|
"[Consulting Page] Obtained entry for ID=%d. This entry was marked "
|
|
"as deleted."
|
|
),
|
|
cons_id,
|
|
)
|
|
|
|
# get all consultation sessions of this process, only the ones
|
|
# which are not marked as deleted
|
|
stmt = db.t_beratung_einzelberatung.select().where(
|
|
db.t_beratung_einzelberatung.c.vorgang_id == cons_id,
|
|
db.t_beratung_einzelberatung.c.geloescht.is_(None),
|
|
)
|
|
ret = conn.execute(stmt)
|
|
cons_sessions = ret.mappings().all()
|
|
# empty results possible
|
|
if not cons_sessions:
|
|
logger.debug("[Consulting Page] No sessions, return directly...")
|
|
return consultation_data
|
|
|
|
for session in cons_sessions:
|
|
cons_session_pydantic = Beratungsgespraech_Einzelgespraech(
|
|
beratung_id=session["beratung_id"],
|
|
vorgang_id=session["vorgang_id"],
|
|
nutzer_id=session["nutzer_id"],
|
|
nutzer_name=session["nutzer_name"],
|
|
zeitstempel=session["zeitstempel"],
|
|
ansprechpartner=session["ansprechpartner"],
|
|
kommunikationsweg=session["kommunikationsweg"],
|
|
thema_crm_matrix=session["thema_crm_matrix"],
|
|
anmerkungen=session["anmerkungen"],
|
|
rueckmeldung=session["rueckmeldung"],
|
|
erstellt=session["erstellt"],
|
|
aktualisiert=session["aktualisiert"],
|
|
)
|
|
consultation_data.beratungen.append(cons_session_pydantic)
|
|
|
|
logger.debug("[Consulting Page] Returning with sessions attached...")
|
|
|
|
return consultation_data
|
|
|
|
|
|
# // consulting page interaction
|
|
# TODO change to correct logic
|
|
def page_consulting_linking_companies(
|
|
un_id: RecId | None,
|
|
) -> list[LinkingConsultationsEntryCompany]:
|
|
raise RuntimeError("TODOs to implement")
|
|
|
|
with db.ENGINE.connect() as conn:
|
|
q_relevant_companies = sa.select(
|
|
db.grunderfassung_unternehmen.c.un_id,
|
|
db.grunderfassung_unternehmen.c.Partnersuche__un_suche,
|
|
).where(
|
|
db.grunderfassung_unternehmen.c.geloescht.is_(None),
|
|
db.grunderfassung_unternehmen.c.Partnersuche__un_suche.is_not(None),
|
|
)
|
|
if un_id is not None:
|
|
q_relevant_companies = q_relevant_companies.where(
|
|
db.grunderfassung_unternehmen.c.un_id == un_id
|
|
)
|
|
|
|
q_relevant_companies = q_relevant_companies.subquery("relevant_companies")
|
|
|
|
stmt = sa.select(
|
|
q_relevant_companies.c.un_id,
|
|
db.t_ext_crm_master_attach.c.ma_unternehmensname,
|
|
).select_from(
|
|
q_relevant_companies.join(
|
|
db.t_ext_crm_master_attach,
|
|
q_relevant_companies.c.Partnersuche__un_suche
|
|
== db.t_ext_crm_master_attach.c.ma_id,
|
|
)
|
|
)
|
|
|
|
ret = conn.execute(stmt)
|
|
company_names = ret.mappings().all()
|
|
if not company_names:
|
|
raise ValueError(f"No companies found for 'un_id': {un_id}")
|
|
|
|
logger.debug("[Page Consulting -- Linking] Retrieved company names:\n%s", company_names)
|
|
|
|
linking_entries: list[LinkingConsultationsEntryCompany] = []
|
|
for entry in company_names:
|
|
linking_entries.append(
|
|
LinkingConsultationsEntryCompany(
|
|
un_id=entry["un_id"],
|
|
display_name=entry["ma_unternehmensname"],
|
|
)
|
|
)
|
|
|
|
return linking_entries
|
|
|
|
|
|
def page_consulting_linking_persons(
|
|
un_id: RecId | None,
|
|
) -> list[LinkingConsultationsEntryPerson]:
|
|
with db.ENGINE.connect() as conn:
|
|
# if un_id None: list all persons
|
|
# else: list just the persons associated with the company
|
|
|
|
person_select = sa.select(
|
|
db.t_grunderfassung_personen.c.pers_id,
|
|
db.t_grunderfassung_personen.c.Stammdaten__name,
|
|
db.t_grunderfassung_personen.c.Stammdaten__vorname,
|
|
db.t_grunderfassung_personen.c.Stammdaten__ort,
|
|
)
|
|
|
|
if un_id is not None:
|
|
person_select = person_select.select_from(
|
|
db.t_grunderfassung_personen.join(
|
|
db.t_zuordnung_personen_unternehmen,
|
|
db.t_grunderfassung_personen.c.pers_id
|
|
== db.t_zuordnung_personen_unternehmen.c.pers_id,
|
|
)
|
|
).where(db.t_zuordnung_personen_unternehmen.c.un_id == un_id)
|
|
|
|
ret = conn.execute(person_select)
|
|
person_names = ret.mappings().all()
|
|
if not person_names:
|
|
logger.warning(f"No persons found for 'un_id': {un_id}")
|
|
return []
|
|
|
|
logger.debug("[Page Consulting -- Linking] Retrieved person names:\n%s", person_names)
|
|
|
|
linking_entries: list[LinkingConsultationsEntryPerson] = []
|
|
for entry in person_names:
|
|
first_name = entry["Stammdaten__vorname"]
|
|
last_name = entry["Stammdaten__name"]
|
|
location_city = entry["Stammdaten__ort"]
|
|
|
|
display_name = f"{first_name} {last_name}"
|
|
if location_city:
|
|
display_name += f" (Ort: {location_city})"
|
|
|
|
linking_entries.append(
|
|
LinkingConsultationsEntryPerson(
|
|
pers_id=entry["pers_id"],
|
|
display_name=display_name,
|
|
)
|
|
)
|
|
|
|
return linking_entries
|
|
|
|
|
|
# TODO wrap result
|
|
def page_consulting_eastablish_link(
|
|
vorgang_id: ConsId,
|
|
un_id: RecId | None,
|
|
pers_id: RecId | None,
|
|
) -> None:
|
|
|
|
stmt = (
|
|
sa.update(db.t_beratung_vorgang)
|
|
.where(db.t_beratung_vorgang.c.vorgang_id == vorgang_id)
|
|
.values(un_id=un_id, pers_id=pers_id)
|
|
)
|
|
|
|
with db.ENGINE.begin() as conn:
|
|
conn.execute(stmt)
|
|
|
|
|
|
def companyprofile_page_get_consultations(
|
|
un_id: RecId,
|
|
) -> CompanyProfileConsultations:
|
|
logger.debug("[Call backend] _companyprofile_page_get_consultations")
|
|
stmt = sa.select(
|
|
db.t_beratung_vorgang.c.vorgang_id,
|
|
db.t_beratung_vorgang.c.aktualisiert,
|
|
db.t_beratung_vorgang.c.titel,
|
|
db.t_beratung_vorgang.c.beratungs_typ,
|
|
).where(
|
|
db.t_beratung_vorgang.c.un_id == un_id, db.t_beratung_vorgang.c.geloescht.is_(None)
|
|
)
|
|
|
|
with db.ENGINE.connect() as conn:
|
|
res = conn.execute(stmt)
|
|
|
|
cons_entries_pauschal: list[CompanyProfileConsultationEntry] = []
|
|
cons_entries_individual: list[CompanyProfileConsultationEntry] = []
|
|
|
|
for entry in res.mappings():
|
|
cons_id = entry["vorgang_id"]
|
|
assert cons_id, "no VorgangID defined"
|
|
|
|
datetime_updated = cast(datetime.datetime, entry["aktualisiert"])
|
|
datetime_updated = datetime_updated.astimezone(TIMEZONE_CEST)
|
|
|
|
base_title = entry["titel"]
|
|
|
|
_cons_type = entry["beratungs_typ"]
|
|
cons_type = ConsultingType(_cons_type)
|
|
|
|
con_entry = CompanyProfileConsultationEntry(
|
|
cons_id=cons_id,
|
|
title=base_title,
|
|
date_updated=datetime_updated,
|
|
cons_type=cons_type,
|
|
)
|
|
|
|
if cons_type is ConsultingType.PAUSCHAL:
|
|
cons_entries_pauschal.append(con_entry)
|
|
elif cons_type is ConsultingType.INDIVIDUAL:
|
|
cons_entries_individual.append(con_entry)
|
|
else:
|
|
raise TypeError(f"Unknown consulting type: {_cons_type}")
|
|
|
|
cons_entries_pauschal.sort(key=lambda x: x.date_updated, reverse=True)
|
|
cons_entries_individual.sort(key=lambda x: x.date_updated, reverse=True)
|
|
|
|
return CompanyProfileConsultations(
|
|
pauschal=cons_entries_pauschal,
|
|
individual=cons_entries_individual,
|
|
)
|
|
|
|
|
|
# // initial recording interaction
|
|
# TODO wrap result
|
|
def initrec_link_person_company(
|
|
un_id: RecId,
|
|
pers_id: RecId,
|
|
unlink: bool,
|
|
) -> None:
|
|
if unlink:
|
|
deleted_ts = datetime.datetime.now(tz=datetime.UTC)
|
|
stmt = (
|
|
sa.update(db.t_zuordnung_personen_unternehmen)
|
|
.where(
|
|
db.t_zuordnung_personen_unternehmen.c.un_id == un_id,
|
|
db.t_zuordnung_personen_unternehmen.c.pers_id == pers_id,
|
|
db.t_zuordnung_personen_unternehmen.c.gueltig_bis.is_(None),
|
|
)
|
|
.values(gueltig_bis=deleted_ts)
|
|
)
|
|
else:
|
|
stmt = (
|
|
sqlite_insert(db.t_zuordnung_personen_unternehmen)
|
|
.values(un_id=un_id, pers_id=pers_id)
|
|
.on_conflict_do_nothing(
|
|
index_elements=["un_id", "pers_id"],
|
|
index_where=sa.text("gueltig_bis IS NULL"),
|
|
)
|
|
)
|
|
|
|
with db.ENGINE.begin() as conn:
|
|
conn.execute(stmt)
|
|
|
|
|
|
# // main page interaction
|
|
# TODO change to correct logic
|
|
def _main_page_get_company_list() -> list[MainPageEntry]:
|
|
logger.debug("[Call backend] get_company_list")
|
|
|
|
raise RuntimeError("TODOs to implement")
|
|
|
|
stmt = sa.select(
|
|
db.grunderfassung_unternehmen.c.un_id,
|
|
db.grunderfassung_unternehmen.c.Partnersuche__un_suche,
|
|
db.grunderfassung_unternehmen.c.Metadaten_aktualisierung,
|
|
).where(db.grunderfassung_unternehmen.c.geloescht.is_(None))
|
|
|
|
with db.ENGINE.connect() as conn:
|
|
res = conn.execute(stmt)
|
|
|
|
main_page_companies: list[MainPageEntry] = []
|
|
|
|
for entry in res.mappings():
|
|
rec_id = entry["un_id"]
|
|
assert rec_id, "no RecID defined"
|
|
ma_id_external = entry["Partnersuche__un_suche"]
|
|
assert ma_id_external is not None, "external MA ID is NULL"
|
|
datetime_akt = cast(datetime.datetime, entry["Metadaten_aktualisierung"])
|
|
datetime_akt = datetime_akt.astimezone(TIMEZONE_CEST)
|
|
|
|
comp_info = initrec_comp_search_get_info(ma_id_external)
|
|
display_name = comp_info["ma_unternehmensname"]
|
|
|
|
main_page_companies.append(
|
|
MainPageEntry(
|
|
rec_id=rec_id,
|
|
display_name=display_name,
|
|
Metadaten_aktualisierung=datetime_akt,
|
|
type=RecordingType.WITH_COMPANY,
|
|
)
|
|
)
|
|
|
|
return main_page_companies
|
|
|
|
|
|
def _main_page_get_person_list() -> list[MainPageEntry]:
|
|
logger.debug("[Call backend] get_company_list")
|
|
stmt = sa.select(
|
|
db.t_grunderfassung_personen.c.pers_id,
|
|
db.t_grunderfassung_personen.c.Stammdaten__vorname,
|
|
db.t_grunderfassung_personen.c.Stammdaten__name,
|
|
db.t_grunderfassung_personen.c.Metadaten_aktualisierung,
|
|
).where(db.t_grunderfassung_personen.c.geloescht.is_(None))
|
|
|
|
with db.ENGINE.connect() as conn:
|
|
res = conn.execute(stmt)
|
|
|
|
main_page_persons: list[MainPageEntry] = []
|
|
|
|
for entry in res.mappings():
|
|
rec_id = entry["pers_id"]
|
|
assert rec_id, "no RecID defined"
|
|
datetime_akt = cast(datetime.datetime, entry["Metadaten_aktualisierung"])
|
|
datetime_akt = datetime_akt.astimezone()
|
|
|
|
surname: str = entry["Stammdaten__name"]
|
|
first_name: str = entry["Stammdaten__vorname"]
|
|
names_to_join = [n for n in (first_name, surname) if n]
|
|
display_name = " ".join(names_to_join)
|
|
|
|
main_page_persons.append(
|
|
MainPageEntry(
|
|
rec_id=rec_id,
|
|
display_name=display_name,
|
|
Metadaten_aktualisierung=datetime_akt,
|
|
type=RecordingType.WITHOUT_COMPANY,
|
|
)
|
|
)
|
|
|
|
return main_page_persons
|
|
|
|
|
|
def main_page_get_entries() -> list[MainPageEntry]:
|
|
companies = _main_page_get_company_list()
|
|
persons = _main_page_get_person_list()
|
|
|
|
all_entries = companies + persons
|
|
|
|
all_entries.sort(key=lambda x: x.Metadaten_aktualisierung, reverse=True)
|
|
|
|
return all_entries
|