Assets as document: replace snapshot with publish workflow
Remove assets from the snapshot system and replace with a publish-based document workflow that generates versioned ProseMirror documents. - Remove snapshot_id/source_id from asset and asset_vendor models - Delete AssetFilter (no longer needed without snapshot filtering) - Add PublishAssetList service, GraphQL mutation, MCP tool, CLI command, and n8n operation - Add asset_list_document_id column to generated_documents table - Generate ProseMirror documents with asset inventory tables (name, type, amount, data types stored, owner, vendors) - Add AssetListDocument resolver on Organization type - Update frontend to remove snapshot routes/params and add publish dialog - Add e2e tests for asset publish (immediate, with approvers, reuse, RBAC) - Add migration script for converting legacy asset snapshots to documents - Exclude ASSETS from snapshot type lists and e2e snapshot tests - Move generated_documents SQL to coredata methods on Datum and Asset - Clear generated document and SOA references on soft delete and archive Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
@@ -155,32 +155,30 @@ Map `pgx.ErrNoRows` to `ErrResourceNotFound`. Check unique constraint violations
|
||||
Filters implement `SQLFragment() string` and `SQLArguments() pgx.NamedArgs`. Use double pointers for three-state filtering: `nil` = no filter, `*nil` = IS NULL, `*val` = equals.
|
||||
|
||||
```go
|
||||
type AssetFilter struct {
|
||||
snapshotID **gid.GID
|
||||
type CookieBannerFilter struct {
|
||||
state *CookieBannerState
|
||||
}
|
||||
|
||||
func NewAssetFilter(snapshotID **gid.GID) *AssetFilter {
|
||||
return &AssetFilter{snapshotID: snapshotID}
|
||||
func NewCookieBannerFilter(state *CookieBannerState) *CookieBannerFilter {
|
||||
return &CookieBannerFilter{state: state}
|
||||
}
|
||||
|
||||
func (f *AssetFilter) SQLFragment() string {
|
||||
if f.snapshotID == nil {
|
||||
return "TRUE"
|
||||
}
|
||||
|
||||
if *f.snapshotID == nil {
|
||||
return "snapshot_id IS NULL"
|
||||
}
|
||||
|
||||
return "snapshot_id = @filter_snapshot_id"
|
||||
func (f *CookieBannerFilter) SQLFragment() string {
|
||||
return `(
|
||||
CASE
|
||||
WHEN @filter_state::text IS NOT NULL THEN
|
||||
state = @filter_state::cookie_banner_state
|
||||
ELSE TRUE
|
||||
END
|
||||
)`
|
||||
}
|
||||
|
||||
func (f *AssetFilter) SQLArguments() pgx.NamedArgs {
|
||||
if f.snapshotID == nil || *f.snapshotID == nil {
|
||||
return pgx.NamedArgs{}
|
||||
func (f *CookieBannerFilter) SQLArguments() pgx.StrictNamedArgs {
|
||||
args := pgx.StrictNamedArgs{"filter_state": nil}
|
||||
if f.state != nil {
|
||||
args["filter_state"] = string(*f.state)
|
||||
}
|
||||
|
||||
return pgx.NamedArgs{"filter_snapshot_id": **f.snapshotID}
|
||||
return args
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user