2023-11-10 18:53:47 +01:00

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}"
)
]
)