Passed
Push — main ( d0a955...ec822a )
by Jochen
04:45
created

create_db_entries()   A

Complexity

Conditions 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 5
nop 3
dl 0
loc 8
ccs 4
cts 4
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
"""
2
byceps.services.shop.order.order_log_service
3
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4
5
:Copyright: 2014-2024 Jochen Kupperschmidt
6
:License: Revised BSD (see `LICENSE` file for details)
7
"""
8
9 1
from collections.abc import Iterable
10
from datetime import datetime
11 1
12 1
from sqlalchemy import select
13
14 1
from byceps.database import db
15
from byceps.services.shop.shop.models import ShopID
16 1
from byceps.services.user.models.user import UserID
17 1
from byceps.util.uuid import generate_uuid7
18 1
19 1
from .dbmodels.log import DbOrderLogEntry
20
from .dbmodels.order import DbOrder
21 1
from .models.log import OrderLogEntry, OrderLogEntryData
22 1
from .models.order import OrderID
23 1
24 1
25
def create_db_entry(
26
    event_type: str,
27 1
    order_id: OrderID,
28
    data: OrderLogEntryData,
29
    *,
30
    occurred_at: datetime | None = None,
31
) -> None:
32
    """Create an order log entry."""
33
    db_entry = build_db_entry(
34
        event_type, order_id, data, occurred_at=occurred_at
35 1
    )
36
37 1
    db.session.add(db_entry)
38 1
    db.session.commit()
39
40
41 1
def create_db_entries(
42
    event_type: str, order_id: OrderID, datas: Iterable[OrderLogEntryData]
43
) -> None:
44
    """Create a sequence of order log entries."""
45 1
    db_entries = [build_db_entry(event_type, order_id, data) for data in datas]
46
47 1
    db.session.add_all(db_entries)
48 1
    db.session.commit()
49
50
51 1
def build_db_entry(
52
    event_type: str,
53
    order_id: OrderID,
54
    data: OrderLogEntryData,
55
    *,
56
    occurred_at: datetime | None = None,
57
) -> DbOrderLogEntry:
58
    """Assemble, but not persist, an order log entry."""
59 1
    entry_id = generate_uuid7()
60
61 1
    if occurred_at is None:
62 1
        occurred_at = datetime.utcnow()
63
64 1
    return DbOrderLogEntry(entry_id, occurred_at, event_type, order_id, data)
65
66
67 1
def to_db_entry(entry: OrderLogEntry) -> DbOrderLogEntry:
68
    """Convert log entry to database entity."""
69 1
    return DbOrderLogEntry(
70
        entry.id,
71
        entry.occurred_at,
72
        entry.event_type,
73
        entry.order_id,
74
        entry.data,
75
    )
76
77
78 1
def get_entries_for_order(order_id: OrderID) -> list[OrderLogEntry]:
79
    """Return the log entries for that order."""
80 1
    db_entries = db.session.scalars(
81
        select(DbOrderLogEntry)
82
        .filter_by(order_id=order_id)
83
        .order_by(DbOrderLogEntry.occurred_at)
84
    ).all()
85
86 1
    return [_db_entity_to_entry(db_entry) for db_entry in db_entries]
87
88
89 1
def get_entries_of_type_for_order(
90
    order_id: OrderID, event_type: str
91
) -> list[OrderLogEntry]:
92
    """Return the log entries of that type for that order."""
93
    db_entries = db.session.scalars(
94
        select(DbOrderLogEntry)
95
        .filter_by(order_id=order_id)
96
        .filter_by(event_type=event_type)
97
        .order_by(DbOrderLogEntry.occurred_at)
98
    ).all()
99
100
    return [_db_entity_to_entry(db_entry) for db_entry in db_entries]
101
102
103 1
def get_entries_by_initiator(
104
    initiator_id: UserID, event_types: frozenset[str]
105
) -> list[OrderLogEntry]:
106
    """Return the log entries of these types initiated by the user."""
107 1
    if not event_types:
108
        return []
109
110 1
    db_entries = db.session.scalars(
111
        select(DbOrderLogEntry)
112
        .filter(DbOrderLogEntry.event_type.in_(event_types))
113
        .filter(
114
            DbOrderLogEntry.data['initiator_id'].astext == str(initiator_id)
115
        )
116
        .order_by(DbOrderLogEntry.occurred_at)
117
    ).all()
118
119 1
    return [_db_entity_to_entry(db_entry) for db_entry in db_entries]
120
121
122 1
def get_latest_entries_for_shop(
123
    shop_id: ShopID, event_types: frozenset[str], limit: int
124
) -> list[OrderLogEntry]:
125
    """Return the most recent log entries of these types for that shop."""
126
    if not event_types:
127
        return []
128
129
    db_entries = db.session.scalars(
130
        select(DbOrderLogEntry)
131
        .join(DbOrder)
132
        .filter(DbOrder.shop_id == shop_id)
133
        .filter(DbOrderLogEntry.event_type.in_(event_types))
134
        .order_by(DbOrderLogEntry.occurred_at.desc())
135
        .limit(limit)
136
    ).all()
137
138
    return [_db_entity_to_entry(db_entry) for db_entry in db_entries]
139
140
141 1
def _db_entity_to_entry(db_entry: DbOrderLogEntry) -> OrderLogEntry:
142 1
    return OrderLogEntry(
143
        id=db_entry.id,
144
        occurred_at=db_entry.occurred_at,
145
        event_type=db_entry.event_type,
146
        order_id=db_entry.order_id,
147
        data=db_entry.data.copy(),
148
    )
149