File size: 7,341 Bytes
3493993
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
from __future__ import annotations

from datetime import datetime
from uuid import uuid4

from sqlalchemy import (
    JSON,
    Boolean,
    CheckConstraint,
    DateTime,
    ForeignKey,
    Index,
    Integer,
    Numeric,
    String,
    Text,
    UniqueConstraint,
)
from sqlalchemy.orm import Mapped, mapped_column

from app.security.models import Base, utcnow


class BrandKit(Base):
    __tablename__ = "brand_kits"
    __table_args__ = (
        CheckConstraint("status in ('active','archived')", name="ck_brand_kits_status"),
        Index("ix_brand_kits_workspace_updated", "workspace_id", "updated_at"),
        Index("ix_brand_kits_workspace_default", "workspace_id", "is_default"),
    )

    id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid4()))
    workspace_id: Mapped[str] = mapped_column(
        String(36), ForeignKey("workspaces.id", ondelete="RESTRICT"), nullable=False
    )
    name: Mapped[str] = mapped_column(String(200), nullable=False)
    description: Mapped[str | None] = mapped_column(Text)
    status: Mapped[str] = mapped_column(String(16), nullable=False, default="active")
    is_default: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
    active_version_id: Mapped[str | None] = mapped_column(String(36))
    created_by: Mapped[str] = mapped_column(
        String(36), ForeignKey("users.id", ondelete="RESTRICT"), nullable=False
    )
    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), nullable=False, default=utcnow
    )
    updated_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), nullable=False, default=utcnow, onupdate=utcnow
    )


class BrandKitVersion(Base):
    __tablename__ = "brand_kit_versions"
    __table_args__ = (
        UniqueConstraint("brand_kit_id", "version_number", name="uq_brand_kit_version"),
        CheckConstraint("status in ('draft','published','archived')", name="ck_brand_version_status"),
        Index("ix_brand_versions_kit_created", "brand_kit_id", "created_at"),
    )

    id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid4()))
    workspace_id: Mapped[str] = mapped_column(
        String(36), ForeignKey("workspaces.id", ondelete="RESTRICT"), nullable=False
    )
    brand_kit_id: Mapped[str] = mapped_column(
        String(36), ForeignKey("brand_kits.id", ondelete="CASCADE"), nullable=False
    )
    version_number: Mapped[int] = mapped_column(Integer, nullable=False)
    status: Mapped[str] = mapped_column(String(16), nullable=False, default="draft")
    logo_asset_id: Mapped[str | None] = mapped_column(String(36), ForeignKey("media_assets.id", ondelete="SET NULL"))
    favicon_asset_id: Mapped[str | None] = mapped_column(String(36), ForeignKey("media_assets.id", ondelete="SET NULL"))
    primary_color: Mapped[str | None] = mapped_column(String(32))
    secondary_color: Mapped[str | None] = mapped_column(String(32))
    accent_color: Mapped[str | None] = mapped_column(String(32))
    background_color: Mapped[str | None] = mapped_column(String(32))
    text_color: Mapped[str | None] = mapped_column(String(32))
    font_family_primary: Mapped[str | None] = mapped_column(String(255))
    font_family_secondary: Mapped[str | None] = mapped_column(String(255))
    heading_font: Mapped[str | None] = mapped_column(String(255))
    body_font: Mapped[str | None] = mapped_column(String(255))
    voice_style: Mapped[str | None] = mapped_column(String(255))
    tone: Mapped[str | None] = mapped_column(String(255))
    default_cta: Mapped[str | None] = mapped_column(String(255))
    default_hashtags: Mapped[dict[str, object]] = mapped_column(JSON, nullable=False, default=list)
    watermark_asset_id: Mapped[str | None] = mapped_column(String(36), ForeignKey("media_assets.id", ondelete="SET NULL"))
    watermark_position: Mapped[str | None] = mapped_column(String(32))
    watermark_opacity: Mapped[float | None] = mapped_column(Numeric(precision=3, scale=2))
    metadata: Mapped[dict[str, object]] = mapped_column(JSON, nullable=False, default=dict)
    created_by: Mapped[str] = mapped_column(
        String(36), ForeignKey("users.id", ondelete="RESTRICT"), nullable=False
    )
    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), nullable=False, default=utcnow
    )
    published_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))


class BrandKitAsset(Base):
    __tablename__ = "brand_kit_assets"
    __table_args__ = (
        UniqueConstraint("brand_kit_version_id", "role", name="uq_brand_asset_role"),
        Index("ix_brand_assets_workspace_asset", "workspace_id", "asset_id"),
    )

    id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid4()))
    workspace_id: Mapped[str] = mapped_column(
        String(36), ForeignKey("workspaces.id", ondelete="RESTRICT"), nullable=False
    )
    brand_kit_version_id: Mapped[str] = mapped_column(
        String(36), ForeignKey("brand_kit_versions.id", ondelete="CASCADE"), nullable=False
    )
    asset_id: Mapped[str] = mapped_column(
        String(36), ForeignKey("media_assets.id", ondelete="RESTRICT"), nullable=False
    )
    role: Mapped[str] = mapped_column(String(32), nullable=False)
    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), nullable=False, default=utcnow
    )


class BrandKitPlatformSetting(Base):
    __tablename__ = "brand_kit_platform_settings"
    __table_args__ = (
        UniqueConstraint(
            "brand_kit_version_id", "provider", name="uq_brand_platform_setting"
        ),
        Index("ix_brand_platform_settings_workspace", "workspace_id"),
    )

    id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid4()))
    workspace_id: Mapped[str] = mapped_column(
        String(36), ForeignKey("workspaces.id", ondelete="RESTRICT"), nullable=False
    )
    brand_kit_version_id: Mapped[str] = mapped_column(
        String(36), ForeignKey("brand_kit_versions.id", ondelete="CASCADE"), nullable=False
    )
    provider: Mapped[str] = mapped_column(String(32), nullable=False)
    settings_json: Mapped[dict[str, object]] = mapped_column(
        "settings", JSON, nullable=False, default=dict
    )


class BrandGovernanceSetting(Base):
    __tablename__ = "brand_governance_settings"
    __table_args__ = (UniqueConstraint("workspace_id", name="uq_brand_governance_workspace"),)

    id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid4()))
    workspace_id: Mapped[str] = mapped_column(
        String(36), ForeignKey("workspaces.id", ondelete="CASCADE"), nullable=False
    )
    require_brand_kit_for_publish: Mapped[bool] = mapped_column(
        Boolean, nullable=False, default=False
    )
    require_published_brand_version: Mapped[bool] = mapped_column(
        Boolean, nullable=False, default=False
    )
    allow_user_override_brand_defaults: Mapped[bool] = mapped_column(
        Boolean, nullable=False, default=True
    )
    updated_by: Mapped[str] = mapped_column(
        String(36), ForeignKey("users.id", ondelete="RESTRICT"), nullable=False
    )
    updated_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), nullable=False, default=utcnow, onupdate=utcnow
    )