feat: add Category model and update storage for categories
Models & Storage layer for category feature (Issue #85): - Add Category dataclass to core/models.py - id (slug): lowercase alphabetic only - name: display name - created_at: Unix timestamp - deleted_at: soft delete timestamp (None if active) - Add category_ids field to Bounty dataclass - list[str] for multiple categories per bounty - Default empty list for backward compatibility - Add categories field to RoomData dataclass - list[Category] for room-level categories - Default empty list - Update JsonFileRoomStorage to serialize/deserialize: - Category fields (id, name, created_at, deleted_at) - Bounty.category_ids - RoomData.categories Backward compatible: existing data without categories works fine.
This commit is contained in:
@@ -1,6 +1,20 @@
|
||||
"""Domain dataclasses for JIGAIDO bounty tracker."""
|
||||
|
||||
from dataclasses import dataclass
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
|
||||
@dataclass
|
||||
class Category:
|
||||
"""A category for organizing bounties in a room.
|
||||
|
||||
Categories are per-room and support soft delete.
|
||||
The id (slug) must be lowercase alphabetic only (e.g., "bug", "feature").
|
||||
"""
|
||||
|
||||
id: str # slug: lowercase alphabetic only, e.g., "bug", "feature"
|
||||
name: str # display name: e.g., "Bug", "Feature"
|
||||
created_at: int
|
||||
deleted_at: int | None = None # soft delete
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -12,6 +26,8 @@ class Bounty:
|
||||
|
||||
The deleted_at field indicates soft-delete: None means not deleted,
|
||||
a value means deleted at that Unix timestamp.
|
||||
|
||||
The category_ids field lists category slugs associated with this bounty.
|
||||
"""
|
||||
|
||||
id: int
|
||||
@@ -22,6 +38,7 @@ class Bounty:
|
||||
created_by_user_id: int
|
||||
deleted_at: int | None = None
|
||||
created_by_username: str | None = None
|
||||
category_ids: list[str] = field(default_factory=list)
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -45,6 +62,7 @@ class RoomData:
|
||||
|
||||
The timezone field stores the room's timezone (e.g., "Asia/Jakarta"), default UTC+0.
|
||||
The admin_usernames field lists usernames who have admin privileges in this room.
|
||||
The categories field contains all categories for organizing bounties in this room.
|
||||
"""
|
||||
|
||||
room_id: int
|
||||
@@ -52,10 +70,13 @@ class RoomData:
|
||||
next_id: int
|
||||
timezone: str | None = None
|
||||
admin_usernames: list[str] | None = None
|
||||
categories: list[Category] = field(default_factory=list)
|
||||
|
||||
def __post_init__(self):
|
||||
if self.admin_usernames is None:
|
||||
self.admin_usernames = []
|
||||
if self.categories is None:
|
||||
self.categories = []
|
||||
|
||||
|
||||
@dataclass
|
||||
|
||||
Reference in New Issue
Block a user