3.6 KiB
3.6 KiB
Asset relations: Report and Comment
Overview
Reports and comments are child relations of an asset. They are stored in separate tables (asset_reports, asset_comments) and are always loaded/saved through the asset (no standalone Report or Comment repository in this layer).
Comment relation
Storage
- Table:
asset_comments - Columns:
id,asset_id,content,writer_id,writer_type,parent_id,created_at,updated_at,deleted_at - Parent link:
asset_id→assets.id
What happens
| Operation | Behavior |
|---|---|
| Create asset | If asset.Comments is non-empty, each comment is inserted with asset_id = new_asset_id. IDs/timestamps come from DB. |
| FindByID / FindByProfileID | All rows in asset_comments with asset_id = asset.id are loaded and mapped to asset.Comments (flat list). |
| Update asset | All existing comments for that asset are deleted, then asset.Comments is re-inserted (replace strategy). |
| Delete asset | All comments for that asset are deleted in the same transaction before the asset row is deleted. |
Domain vs persistence
- Domain:
CommenthasReplies []Comment(nested). - Persistence: Stored as rows in
asset_commentswithparent_idfor replies. - When loading: A flat list is read from DB, then
buildCommentTree()turns it into a tree: top-level comments haveRepliespopulated. - When saving:
flattenComments()turns the tree into a flat list (parent then its replies); all rows are persisted. Note: when creating a new asset with new nested comments, replyParentIDin the domain may be zero (parent not yet saved); the current single-batch insert does not resolve parent IDs, so nested replies on create may end up withparent_id = NULL. For updates after load, parent IDs exist and nested replies persist correctly.
Report relation
Storage
- Table:
asset_reports - Columns:
id,asset_id,reported_by(JSONB),reported_at,reason(JSONB),status,notes,attachments(JSONB),created_at,updated_at,deleted_at - Parent link:
asset_id→assets.id - Nested data:
ReportedBy,ReportReason, andAttachmentsare stored as JSON in the same row.
What happens
| Operation | Behavior |
|---|---|
| Create asset | If asset.Reports is non-empty, each report is inserted: ReportedBy, Reason, and Attachments are JSON-encoded into the report row. |
| FindByID / FindByProfileID | All rows in asset_reports with asset_id = asset.id are loaded; JSONB columns are decoded into Report.ReportedBy, Report.Reason, Report.Attachments. |
| Update asset | All existing reports for that asset are deleted, then asset.Reports is re-inserted (replace strategy). |
| Delete asset | All reports for that asset are deleted in the same transaction before the asset row is deleted. |
Domain vs persistence
- ReportedBy, ReportReason, Attachments are fully round-tripped via JSON; no separate tables.
- Report ID and ReportedAt are set when loading from DB; on create, IDs/timestamps come from DB.
Summary
- Comment: Stored and loaded as a flat list per asset;
parent_idis persisted but Replies are not built when loading and nested replies are not written when saving. - Report: Stored and loaded as a list per asset; nested structures (ReportedBy, Reason, Attachments) are stored as JSONB and fully restored on load.
- Both relations use a replace-on-update strategy: updating an asset deletes all its comments and reports and re-inserts from
asset.Commentsandasset.Reports.