Implement client cost attribution
This commit is contained in:
parent
d2b9bc4b32
commit
33883e0977
15 changed files with 362 additions and 21 deletions
|
|
@ -5,15 +5,25 @@ from __future__ import annotations
|
|||
import uuid
|
||||
from datetime import date
|
||||
|
||||
from sqlalchemy import Date, Float, String
|
||||
from sqlalchemy import CheckConstraint, Date, Float, String, event
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from hub_core.models.base import Base, TimestampMixin
|
||||
from fin_hub.attribution import optional_attribution
|
||||
|
||||
|
||||
class ServiceCost(Base, TimestampMixin):
|
||||
__tablename__ = "fin_service_costs"
|
||||
__table_args__ = (
|
||||
CheckConstraint(
|
||||
"(client_id IS NULL AND application_id IS NULL AND app_instance_id IS NULL "
|
||||
"AND cost_attribution_key IS NULL) OR "
|
||||
"(client_id IS NOT NULL AND application_id IS NOT NULL "
|
||||
"AND app_instance_id IS NOT NULL AND cost_attribution_key IS NOT NULL)",
|
||||
name="ck_fin_service_costs_complete_attribution",
|
||||
),
|
||||
)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
||||
service_id: Mapped[str] = mapped_column(String(128), nullable=False, index=True)
|
||||
|
|
@ -23,4 +33,20 @@ class ServiceCost(Base, TimestampMixin):
|
|||
currency: Mapped[str] = mapped_column(String(3), nullable=False, default="EUR")
|
||||
source: Mapped[str] = mapped_column(String(32), nullable=False)
|
||||
incurred_on: Mapped[date | None] = mapped_column(Date, nullable=True)
|
||||
notes: Mapped[str | None] = mapped_column(String(512), nullable=True)
|
||||
notes: Mapped[str | None] = mapped_column(String(512), nullable=True)
|
||||
client_id: Mapped[str | None] = mapped_column(String(128), nullable=True, index=True)
|
||||
application_id: Mapped[str | None] = mapped_column(String(128), nullable=True, index=True)
|
||||
app_instance_id: Mapped[str | None] = mapped_column(String(128), nullable=True, index=True)
|
||||
cost_attribution_key: Mapped[str | None] = mapped_column(String(423), nullable=True, index=True)
|
||||
|
||||
|
||||
@event.listens_for(ServiceCost, "before_insert")
|
||||
@event.listens_for(ServiceCost, "before_update")
|
||||
def _normalize_service_cost_attribution(_mapper, _connection, target: ServiceCost) -> None:
|
||||
attribution = optional_attribution(
|
||||
target.client_id, target.application_id, target.app_instance_id
|
||||
)
|
||||
expected_key = attribution.key if attribution else None
|
||||
if target.cost_attribution_key not in (None, expected_key):
|
||||
raise ValueError("cost_attribution_key does not match its attribution dimensions")
|
||||
target.cost_attribution_key = expected_key
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue