Skip to content

Commit a34adb0

Browse files
hf-kkleinKonstantinhf-krechan
authored
feat: Add view v_ahbtabellen on top of ahb_hierarchy_materialized (#118)
--------- Co-authored-by: Konstantin <[email protected]> Co-authored-by: kevin <[email protected]>
1 parent 302b4d4 commit a34adb0

File tree

7 files changed

+1896
-19
lines changed

7 files changed

+1896
-19
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
"""
2+
This module contains the SQLModel class for the AHBesser view and a function to create it.
3+
If you never heard about ahbesser, you can safely ignore this module.
4+
https://github.com/Hochfrequenz/ahbesser
5+
"""
6+
7+
import logging
8+
from pathlib import Path
9+
from uuid import UUID
10+
11+
from efoli import EdifactFormatVersion
12+
from sqlalchemy.sql.functions import func
13+
from sqlmodel import Field, Session, SQLModel, select
14+
15+
from fundamend.sqlmodels.internals import _execute_bare_sql
16+
17+
_logger = logging.getLogger(__name__)
18+
19+
20+
def create_ahbtabellen_view(session: Session) -> None:
21+
"""
22+
Create a view for the AHB-Tabellen application: https://github.com/Hochfrequenz/ahbesser
23+
This assumes that create_db_and_populate_with_ahb_view has already been called.
24+
If you don't know what ahbesser is, you can safely ignore this function.
25+
"""
26+
_execute_bare_sql(session=session, path_to_sql_commands=Path(__file__).parent / "create_ahbtabellen_view.sql")
27+
number_of_rows = session.scalar(
28+
select(func.count(AhbTabellenLine.id)) # type:ignore[arg-type] # pylint:disable=not-callable
29+
)
30+
_logger.info(
31+
"There are %d rows in the AHBTabellen view %s",
32+
number_of_rows,
33+
AhbTabellenLine.__tablename__,
34+
)
35+
36+
37+
class AhbTabellenLine(SQLModel, table=True):
38+
"""
39+
Model that represents thew view used by ahbesser. It's created by executing 'create_ahbtabellen_view(session)'
40+
"""
41+
42+
__tablename__ = "v_ahbtabellen"
43+
id: UUID = Field(primary_key=True)
44+
format_version: EdifactFormatVersion = Field()
45+
pruefidentifikator: str = Field()
46+
path: str = Field()
47+
id_path: str = Field()
48+
direction: str = Field()
49+
description: str = Field()
50+
segmentgroup_key: str | None = Field()
51+
segment_code: str | None = Field()
52+
data_element: str | None = Field()
53+
qualifier: str | None = Field()
54+
line_ahb_status: str | None = Field()
55+
line_name: str | None = Field()
56+
sort_path: str = Field()
57+
58+
59+
__all__ = ["create_ahbtabellen_view", "AhbTabellenLine"]

src/fundamend/sqlmodels/ahbview.py

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
SegmentGroup,
3131
SegmentGroupLink,
3232
)
33+
from fundamend.sqlmodels.internals import _execute_bare_sql
3334

3435
_logger = logging.getLogger(__name__)
3536

@@ -39,24 +40,8 @@ def create_ahb_view(session: Session) -> None:
3940
Create a materialized view for the Anwendungshandbücher using a SQLAlchemy session.
4041
Warning: This is only tested for SQLite!
4142
"""
42-
path_to_sql_command = Path(__file__).parent / "materialize_ahb_view.sql"
43-
44-
with open(path_to_sql_command, "r", encoding="utf-8") as sql_file:
45-
bare_sql = sql_file.read()
46-
47-
bare_statements = bare_sql.split(";")
48-
49-
for bare_statement in bare_statements:
50-
statement = bare_statement.strip()
51-
if statement:
52-
try:
53-
session.execute(sqlalchemy.text(statement))
54-
except sqlalchemy.exc.IntegrityError:
55-
if " UNIQUE " in bare_statement:
56-
session.execute(sqlalchemy.text(bare_statement.replace(" UNIQUE ", " ")))
57-
else:
58-
raise
59-
session.commit()
43+
_execute_bare_sql(session=session, path_to_sql_commands=Path(__file__).parent / "materialize_ahb_view.sql")
44+
6045
number_of_inserted_rows = session.scalar(
6146
select(func.count(AhbHierarchyMaterialized.id)) # type:ignore[arg-type] # pylint:disable=not-callable #
6247
)

src/fundamend/sqlmodels/anwendungshandbuch.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
# sqlmodel is only an optional dependency when fundamend is used to fill a database
2121
raise
2222

23-
2423
from fundamend.models.anwendungshandbuch import Anwendungsfall as PydanticAnwendungsfall
2524
from fundamend.models.anwendungshandbuch import Anwendungshandbuch as PydanticAnwendungshandbuch
2625
from fundamend.models.anwendungshandbuch import Bedingung as PydanticBedingung
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
-- Assume that materialize_ahb_view.sql has been executed already.
2+
-- Then we can create another view on top of ahb_hierarchy_materialized.
3+
-- This is especially useful for our ahbesser frontend (aka "AHB-Tabellen")
4+
5+
DROP TABLE IF EXISTS v_ahbtabellen; -- this is because sqlmodel tries to create a table first... it doesn't know that this is just a view. bit dirty but ok.
6+
DROP VIEW IF EXISTS v_ahbtabellen;
7+
CREATE VIEW v_ahbtabellen as
8+
SELECT id as id,
9+
edifact_format_version as format_version,
10+
pruefidentifikator as pruefidentifikator,
11+
path,
12+
id_path,
13+
kommunikation_von as direction,
14+
beschreibung as description,
15+
'SG' || segmentgroup_id as segmentgroup_key, -- eg 'SG6'
16+
segment_id as segment_code, -- e.g 'NAD'
17+
dataelement_id as data_element, -- e.g 'D_3035'
18+
--CASE
19+
-- WHEN dataelement_id IS NOT NULL THEN SUBSTR(dataelement_id, 3)
20+
-- END AS dataelement_without_leading_d_, -- e.g '3035'
21+
code_value as qualifier,
22+
23+
coalesce(code_ahb_status, coalesce(dataelement_ahb_status,
24+
coalesce(segment_ahb_status, segmentgroup_ahb_status))) as line_ahb_status, -- e.g. 'Muss [28] ∧ [64]'
25+
coalesce(code_name, coalesce(dataelement_name, coalesce(dataelementgroup_name,
26+
coalesce(segment_name, segmentgroup_name)))) as line_name, -- e.g. 'Datums- oder Uhrzeit- oder Zeitspannen-Format, Code' or 'Produkt-Daten für Lieferant relevant'
27+
sort_path as sort_path
28+
-- the bedingung column is still missing, but we'll solve this one separately
29+
FROM ahb_hierarchy_materialized
30+
WHERE TYPE != 'dataelementgroup' AND (TYPE != 'dataelement' OR dataelement_ahb_status IS NOT Null) ;

src/fundamend/sqlmodels/internals.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"""internal helper functions"""
2+
3+
from pathlib import Path
4+
5+
try:
6+
import sqlalchemy
7+
from sqlmodel import Session
8+
except ImportError as import_error:
9+
import_error.msg += "; Did you install fundamend[sqlmodels] or did you try to import from fundamend.models instead?"
10+
# sqlmodel is only an optional dependency when fundamend is used to fill a database
11+
raise
12+
13+
14+
def _execute_bare_sql(session: Session, path_to_sql_commands: Path) -> None:
15+
"""
16+
Execute bare SQL from the path_to_sqlcommands in the given SQLAlchemy session.
17+
"""
18+
19+
with open(path_to_sql_commands, "r", encoding="utf-8") as sql_file:
20+
bare_sql = sql_file.read()
21+
22+
bare_statements = bare_sql.split(";")
23+
24+
for bare_statement in bare_statements:
25+
statement = bare_statement.strip()
26+
if statement:
27+
try:
28+
session.execute(sqlalchemy.text(statement))
29+
except sqlalchemy.exc.IntegrityError:
30+
if " UNIQUE " in bare_statement:
31+
session.execute(sqlalchemy.text(bare_statement.replace(" UNIQUE ", " ")))
32+
else:
33+
raise
34+
session.commit()

0 commit comments

Comments
 (0)