mirror of
https://github.com/fhswf/aki_prj23_transparenzregister.git
synced 2025-05-13 16:18:46 +02:00
417 lines
13 KiB
Python
417 lines
13 KiB
Python
"""Dash elements."""
|
|
|
|
from datetime import datetime
|
|
from typing import Any
|
|
|
|
import numpy as np
|
|
import pandas as pd
|
|
from babel.numbers import format_currency
|
|
from dash import dash_table, dcc, html
|
|
from sqlalchemy.orm import Session
|
|
|
|
from aki_prj23_transparenzregister.ui import data_elements, finance_elements
|
|
from aki_prj23_transparenzregister.utils.networkx.network_2d import create_2d_graph
|
|
from aki_prj23_transparenzregister.utils.networkx.network_base import initialize_network
|
|
from aki_prj23_transparenzregister.utils.networkx.networkx_data import (
|
|
create_edge_and_node_list_for_company,
|
|
find_company_relations,
|
|
get_relations_number_from_id,
|
|
)
|
|
|
|
COLORS = {
|
|
"light": "#edefef",
|
|
"lavender-blush": "#f3e8ee",
|
|
"ash-gray": "#bacdb0",
|
|
"cambridge-blue": "#729b79",
|
|
"paynes-gray": "#475b63",
|
|
"raisin-black": "#2e2c2f",
|
|
}
|
|
|
|
|
|
def format_currency_de(value: Any) -> str:
|
|
"""Checks if given value is not empty and formats currency to german format.
|
|
|
|
Args:
|
|
value: Currency value.
|
|
|
|
Returns:
|
|
Formatted currency or "n.a.".
|
|
"""
|
|
if not value or value == "n.a." or np.isnan(value):
|
|
return "n.a."
|
|
return format_currency(
|
|
float(value),
|
|
"EUR",
|
|
locale="de_DE",
|
|
)
|
|
|
|
|
|
def format_date_de(value: Any) -> str:
|
|
"""Checks if given value is not empty and formats date to german format.
|
|
|
|
Args:
|
|
value: Date value.
|
|
|
|
Returns:
|
|
Formatted date.
|
|
"""
|
|
if not value or value == "n.a." or isinstance(value, str):
|
|
return datetime.today().strftime("%d.%m.%Y")
|
|
return value.strftime("%d.%m.%Y")
|
|
|
|
|
|
def create_company_stats(
|
|
selected_company_id: int, selected_company_data: pd.Series, session: Session
|
|
) -> html:
|
|
"""Create company stats.
|
|
|
|
Args:
|
|
selected_company_id: Id of the chosen company.
|
|
selected_company_data: A series containing all company information of the selected company.
|
|
session: A session connecting to the database.
|
|
|
|
Returns:
|
|
The html div to create the company stats table and the three small widgets.
|
|
"""
|
|
company_data = {
|
|
"col1": ["Unternehmen", "Straße", "Stadt"],
|
|
"col2": [
|
|
selected_company_data["company_name"],
|
|
str(
|
|
selected_company_data["company_street"]
|
|
+ " "
|
|
+ selected_company_data["company_house_number"]
|
|
),
|
|
str(
|
|
selected_company_data["company_zip_code"]
|
|
+ " "
|
|
+ selected_company_data["company_city"]
|
|
),
|
|
],
|
|
"col3": ["Rechtsform", "Amtsgericht", "Gründungsdatum"],
|
|
"col4": [
|
|
selected_company_data["company_company_type"],
|
|
selected_company_data["district_court_name"],
|
|
format_date_de(selected_company_data["company_founding_date"]),
|
|
],
|
|
}
|
|
df_company_data = pd.DataFrame(data=company_data)
|
|
|
|
# set data for first widget
|
|
widget1_title = (
|
|
"Stammkapital"
|
|
if not str.title(selected_company_data["company_capital_type"])
|
|
or str.title(selected_company_data["company_capital_type"]) == "N.A."
|
|
else str.title(selected_company_data["company_capital_type"])
|
|
)
|
|
widget1_content = format_currency_de(selected_company_data["company_capital_value"])
|
|
|
|
# set data for second widget
|
|
finance_data = data_elements.get_finance_data_of_one_company(
|
|
session, selected_company_id
|
|
)
|
|
finance_data_updated = (
|
|
pd.DataFrame(
|
|
data={
|
|
"revenue": [""],
|
|
"date": datetime.today(),
|
|
}
|
|
)
|
|
if finance_data.empty
|
|
else finance_data.sort_values(by=["date"], ascending=False)
|
|
)
|
|
widget2_content = format_currency_de(finance_data_updated["revenue"].iloc[0])
|
|
|
|
# set data for third widget
|
|
widget3_title = "Stimmung"
|
|
|
|
return html.Div(
|
|
className="stats-wrapper",
|
|
children=[
|
|
html.Div(
|
|
className="widget-large",
|
|
children=[
|
|
html.H3(
|
|
className="widget-title",
|
|
children="Stammdaten",
|
|
),
|
|
dash_table.DataTable(
|
|
df_company_data.to_dict("records"),
|
|
[{"name": i, "id": i} for i in df_company_data.columns],
|
|
style_table={
|
|
"width": "90%",
|
|
"marginLeft": "auto",
|
|
"marginRight": "auto",
|
|
"paddingBottom": "20px",
|
|
"color": COLORS["raisin-black"],
|
|
},
|
|
# hide header of table
|
|
css=[
|
|
{
|
|
"selector": "tr:first-child",
|
|
"rule": "display: none",
|
|
},
|
|
],
|
|
style_cell={
|
|
"textAlign": "center",
|
|
"fontFamily": "Times",
|
|
"paddingLeft": "5px",
|
|
"paddingRight": "5px",
|
|
},
|
|
style_cell_conditional=[
|
|
{"if": {"column_id": c}, "fontWeight": "bold"}
|
|
for c in ["col1", "col3"]
|
|
],
|
|
style_data={
|
|
"whiteSpace": "normal",
|
|
"height": "auto",
|
|
},
|
|
),
|
|
],
|
|
),
|
|
html.Div(
|
|
className="widget-small",
|
|
children=[
|
|
html.H3(
|
|
className="widget-title",
|
|
children=[widget1_title],
|
|
),
|
|
html.H1(
|
|
className="widget-content",
|
|
children=[widget1_content],
|
|
),
|
|
html.Div(
|
|
className="widget-info",
|
|
children=[
|
|
"Stand: "
|
|
+ format_date_de(
|
|
selected_company_data["company_last_update"]
|
|
)
|
|
],
|
|
),
|
|
],
|
|
),
|
|
html.Div(
|
|
className="widget-small",
|
|
children=[
|
|
html.H3(
|
|
className="widget-title",
|
|
children=["Umsatz"],
|
|
),
|
|
html.H1(
|
|
className="widget-content",
|
|
children=[widget2_content],
|
|
),
|
|
html.Div(
|
|
className="widget-info",
|
|
children=[
|
|
"Stand: "
|
|
+ format_date_de(finance_data_updated["date"].iloc[0])
|
|
],
|
|
),
|
|
],
|
|
),
|
|
html.Div(
|
|
className="widget-small",
|
|
children=[
|
|
html.H3(
|
|
className="widget-title",
|
|
children=[widget3_title],
|
|
),
|
|
html.H1(
|
|
className="widget-content",
|
|
children="1234",
|
|
),
|
|
],
|
|
),
|
|
],
|
|
)
|
|
|
|
|
|
def create_tabs(session: Session, selected_company_id: int) -> html:
|
|
"""Create tabs for more company information.
|
|
|
|
Args:
|
|
session: A session connecting to the database.
|
|
selected_company_id: Id of the chosen company in the dropdown.
|
|
|
|
Returns:
|
|
The html div to create the tabs of the company page.
|
|
"""
|
|
return html.Div(
|
|
className="tabs",
|
|
children=[
|
|
dcc.Tabs(
|
|
id="tabs",
|
|
value="tab-1",
|
|
children=[
|
|
dcc.Tab(
|
|
label="Kennzahlen",
|
|
value="tab-1",
|
|
className="tab-style",
|
|
selected_className="selected-tab-style",
|
|
children=[
|
|
finance_elements.financial_metrics_layout(
|
|
session, selected_company_id
|
|
)
|
|
],
|
|
),
|
|
dcc.Tab(
|
|
label="Beteiligte Personen",
|
|
value="tab-2",
|
|
className="tab-style",
|
|
selected_className="selected-tab-style",
|
|
children=[
|
|
person_relations_layout(selected_company_id, session)
|
|
],
|
|
),
|
|
dcc.Tab(
|
|
label="Stimmung",
|
|
value="tab-3",
|
|
className="tab-style",
|
|
selected_className="selected-tab-style",
|
|
),
|
|
dcc.Tab(
|
|
label="Verflechtungen",
|
|
value="tab-4",
|
|
className="tab-style",
|
|
selected_className="selected-tab-style",
|
|
children=[network_layout(selected_company_id)],
|
|
),
|
|
],
|
|
),
|
|
html.Div(id="tabs-example-content-1"),
|
|
],
|
|
)
|
|
|
|
|
|
def person_relations_layout(selected_company_id: int, session: Session) -> html:
|
|
"""Create person relation tab.
|
|
|
|
Args:
|
|
selected_company_id: Id of the chosen company in the dropdown.
|
|
session: A session connecting to the database.
|
|
|
|
Returns:
|
|
The html div to create the person relations tab of the company page.
|
|
"""
|
|
relations = data_elements.get_person_relations_of_one_company(
|
|
selected_company_id, session
|
|
)
|
|
if relations.empty:
|
|
return html.Div(
|
|
className="choose-metric",
|
|
children=[
|
|
html.H3(
|
|
className="metrics-title",
|
|
children=[
|
|
"Für dieses Unternehmen wurden leider keine beteiligten Personen gefunden."
|
|
],
|
|
)
|
|
],
|
|
)
|
|
table = (
|
|
relations[["firstname", "lastname", "relation", "date_from", "date_to"]]
|
|
.fillna("n.a.")
|
|
.rename(
|
|
columns={
|
|
"firstname": "Vorname",
|
|
"lastname": "Nachname",
|
|
"relation": "Rolle",
|
|
"date_from": "Von",
|
|
"date_to": "Bis",
|
|
}
|
|
)
|
|
.sort_values(by=["Nachname"])
|
|
)
|
|
return dash_table.DataTable(
|
|
table.to_dict("records"),
|
|
[{"name": i, "id": i} for i in table.columns],
|
|
style_table={
|
|
"width": "80%",
|
|
"marginLeft": "auto",
|
|
"marginRight": "auto",
|
|
"padding": "20px",
|
|
"color": COLORS["raisin-black"],
|
|
},
|
|
style_cell={"textAlign": "center", "fontFamily": "Times", "fontSize": "14px"},
|
|
style_header={
|
|
"backgroundColor": COLORS["raisin-black"],
|
|
"fontWeight": "bold",
|
|
"color": "white",
|
|
"fontSize": "16px",
|
|
},
|
|
page_size=15,
|
|
sort_action="native",
|
|
sort_mode="multi",
|
|
column_selectable="single",
|
|
filter_action="native",
|
|
filter_options={"placeholder_text": "Filter"},
|
|
style_filter={"text-align": "center", "backgroundColor": COLORS["light"]},
|
|
)
|
|
|
|
def kennzahlen_layout(selected_finance_df: pd.DataFrame) -> html:
|
|
"""Create metrics tab.
|
|
|
|
Args:
|
|
selected_finance_df: A dataframe containing all available finance information of the companies.
|
|
|
|
Returns:
|
|
The html div to create the metrics tab of the company page.
|
|
"""
|
|
return html.Div(
|
|
[
|
|
dcc.Graph(
|
|
figure=finance_elements.financials_figure(
|
|
selected_finance_df, "annual_finance_statement_ebit"
|
|
)
|
|
)
|
|
]
|
|
)
|
|
|
|
|
|
def network_layout(selected_company_id: int) -> html.Div:
|
|
"""Create network tab.
|
|
|
|
Args:
|
|
selected_company_id: Id of the chosen company in the dropdown.
|
|
|
|
Returns:
|
|
The html div to create the network tab of the company page.
|
|
"""
|
|
person_relations, company_relations = find_company_relations(selected_company_id)
|
|
|
|
# get_all_metrics_from_id(selected_company_id)
|
|
get_relations_number_from_id(f"c_{selected_company_id}")
|
|
|
|
# Create Edge and Node List from data
|
|
nodes, edges = create_edge_and_node_list_for_company(company_relations)
|
|
# Initialize the Network and receive the Graph and a DataFrame with Metrics
|
|
if nodes != {}:
|
|
graph, metrics = initialize_network(nodes=nodes, edges=edges)
|
|
metric = "None"
|
|
figure = create_2d_graph(
|
|
graph,
|
|
nodes,
|
|
edges,
|
|
metrics,
|
|
metric,
|
|
layout="Spring",
|
|
edge_annotation=True,
|
|
node_annotation=False,
|
|
edge_thickness=1,
|
|
)
|
|
return html.Div(
|
|
children=[
|
|
dcc.Graph(figure=figure, id="company-graph", className="graph-style")
|
|
]
|
|
)
|
|
|
|
return html.Div(
|
|
[
|
|
html.H3(
|
|
f"Leider gibt es keine Verbindungen vom Unternehmen mit ID: {selected_company_id}"
|
|
)
|
|
]
|
|
)
|