package repository import ( "context" "errors" "time" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" "github.com/geo-platform/tenant-api/internal/tenant/repository/generated" ) type KolPrompt struct { ID int64 TenantID int64 PackageID int64 Name string PlatformHint *string Status string SortOrder int PublishedRevisionNo *int DraftRevisionNo *int CreatedBy int64 UpdatedBy int64 CreatedAt time.Time UpdatedAt time.Time } type KolPromptRevision struct { ID int64 TenantID int64 PromptID int64 RevisionNo int PromptAssetKey string SchemaJSON []byte CardConfigJSON []byte CreatedBy int64 CreatedAt time.Time } type ActiveKolPrompt struct { ID int64 TenantID int64 PackageID int64 PublishedRevisionNo *int } type CreateKolPromptInput struct { TenantID int64 PackageID int64 Name string PlatformHint *string SortOrder int CreatedBy int64 } type UpdateKolPromptMetadataInput struct { ID int64 TenantID int64 Name string PlatformHint *string SortOrder int UpdatedBy int64 } type CreateKolPromptRevisionInput struct { TenantID int64 PromptID int64 RevisionNo int PromptAssetKey string SchemaJSON []byte CardConfigJSON []byte CreatedBy int64 } type KolPromptRepository interface { Create(ctx context.Context, input CreateKolPromptInput) (*KolPrompt, error) GetByID(ctx context.Context, tenantID, id int64) (*KolPrompt, error) ListByPackage(ctx context.Context, tenantID, packageID int64) ([]KolPrompt, error) ListActiveByPackage(ctx context.Context, tenantID, packageID int64) ([]ActiveKolPrompt, error) UpdateMetadata(ctx context.Context, input UpdateKolPromptMetadataInput) error SetDraftRevision(ctx context.Context, tenantID, promptID int64, revNo int, updatedBy int64) error SetPublishedRevision(ctx context.Context, tenantID, promptID int64, revNo int, updatedBy int64) error UpdateStatus(ctx context.Context, tenantID, id int64, status string, updatedBy int64) error SoftDelete(ctx context.Context, tenantID, id int64) error CreateRevision(ctx context.Context, input CreateKolPromptRevisionInput) (*KolPromptRevision, error) GetRevision(ctx context.Context, tenantID, promptID int64, revNo int) (*KolPromptRevision, error) NextRevisionNo(ctx context.Context, tenantID, promptID int64) (int, error) } type kolPromptRepository struct { q generated.Querier } func NewKolPromptRepository(db generated.DBTX) KolPromptRepository { return &kolPromptRepository{q: newQuerier(db)} } func mapKolPrompt(row generated.GetKolPromptByIDRow) *KolPrompt { return &KolPrompt{ ID: row.ID, TenantID: row.TenantID, PackageID: row.PackageID, Name: row.Name, PlatformHint: nullableText(row.PlatformHint), Status: row.Status, SortOrder: int(row.SortOrder), PublishedRevisionNo: nullableIntFromInt4(row.PublishedRevisionNo), DraftRevisionNo: nullableIntFromInt4(row.DraftRevisionNo), CreatedBy: row.CreatedBy, UpdatedBy: row.UpdatedBy, CreatedAt: timeFromTimestamp(row.CreatedAt), UpdatedAt: timeFromTimestamp(row.UpdatedAt), } } func (r *kolPromptRepository) Create(ctx context.Context, input CreateKolPromptInput) (*KolPrompt, error) { row, err := r.q.CreateKolPrompt(ctx, generated.CreateKolPromptParams{ TenantID: input.TenantID, PackageID: input.PackageID, Name: input.Name, PlatformHint: pgText(input.PlatformHint), SortOrder: int32(input.SortOrder), CreatedBy: input.CreatedBy, }) if err != nil { return nil, err } return &KolPrompt{ ID: row.ID, TenantID: row.TenantID, PackageID: row.PackageID, Name: row.Name, PlatformHint: nullableText(row.PlatformHint), Status: row.Status, SortOrder: int(row.SortOrder), PublishedRevisionNo: nullableIntFromInt4(row.PublishedRevisionNo), DraftRevisionNo: nullableIntFromInt4(row.DraftRevisionNo), CreatedBy: row.CreatedBy, UpdatedBy: row.UpdatedBy, CreatedAt: timeFromTimestamp(row.CreatedAt), UpdatedAt: timeFromTimestamp(row.UpdatedAt), }, nil } func (r *kolPromptRepository) GetByID(ctx context.Context, tenantID, id int64) (*KolPrompt, error) { row, err := r.q.GetKolPromptByID(ctx, generated.GetKolPromptByIDParams{ ID: id, TenantID: tenantID, }) if err != nil { if errors.Is(err, pgx.ErrNoRows) { return nil, nil } return nil, err } return mapKolPrompt(row), nil } func (r *kolPromptRepository) ListByPackage(ctx context.Context, tenantID, packageID int64) ([]KolPrompt, error) { rows, err := r.q.ListKolPromptsByPackage(ctx, generated.ListKolPromptsByPackageParams{ PackageID: packageID, TenantID: tenantID, }) if err != nil { return nil, err } result := make([]KolPrompt, len(rows)) for i, row := range rows { result[i] = KolPrompt{ ID: row.ID, TenantID: row.TenantID, PackageID: row.PackageID, Name: row.Name, PlatformHint: nullableText(row.PlatformHint), Status: row.Status, SortOrder: int(row.SortOrder), PublishedRevisionNo: nullableIntFromInt4(row.PublishedRevisionNo), DraftRevisionNo: nullableIntFromInt4(row.DraftRevisionNo), CreatedBy: row.CreatedBy, UpdatedBy: row.UpdatedBy, CreatedAt: timeFromTimestamp(row.CreatedAt), UpdatedAt: timeFromTimestamp(row.UpdatedAt), } } return result, nil } func (r *kolPromptRepository) ListActiveByPackage(ctx context.Context, tenantID, packageID int64) ([]ActiveKolPrompt, error) { rows, err := r.q.ListActiveKolPromptsByPackage(ctx, generated.ListActiveKolPromptsByPackageParams{ PackageID: packageID, TenantID: tenantID, }) if err != nil { return nil, err } result := make([]ActiveKolPrompt, len(rows)) for i, row := range rows { result[i] = ActiveKolPrompt{ ID: row.ID, TenantID: row.TenantID, PackageID: row.PackageID, PublishedRevisionNo: nullableIntFromInt4(row.PublishedRevisionNo), } } return result, nil } func (r *kolPromptRepository) UpdateMetadata(ctx context.Context, input UpdateKolPromptMetadataInput) error { return r.q.UpdateKolPromptMetadata(ctx, generated.UpdateKolPromptMetadataParams{ Name: input.Name, PlatformHint: pgText(input.PlatformHint), SortOrder: int32(input.SortOrder), UpdatedBy: input.UpdatedBy, ID: input.ID, TenantID: input.TenantID, }) } func (r *kolPromptRepository) SetDraftRevision(ctx context.Context, tenantID, promptID int64, revNo int, updatedBy int64) error { return r.q.UpdateKolPromptDraftRevision(ctx, generated.UpdateKolPromptDraftRevisionParams{ RevisionNo: pgtype.Int4{Int32: int32(revNo), Valid: true}, UpdatedBy: updatedBy, ID: promptID, TenantID: tenantID, }) } func (r *kolPromptRepository) SetPublishedRevision(ctx context.Context, tenantID, promptID int64, revNo int, updatedBy int64) error { return r.q.UpdateKolPromptPublishedRevision(ctx, generated.UpdateKolPromptPublishedRevisionParams{ RevisionNo: pgtype.Int4{Int32: int32(revNo), Valid: true}, UpdatedBy: updatedBy, ID: promptID, TenantID: tenantID, }) } func (r *kolPromptRepository) UpdateStatus(ctx context.Context, tenantID, id int64, status string, updatedBy int64) error { return r.q.UpdateKolPromptStatus(ctx, generated.UpdateKolPromptStatusParams{ Status: status, UpdatedBy: updatedBy, ID: id, TenantID: tenantID, }) } func (r *kolPromptRepository) SoftDelete(ctx context.Context, tenantID, id int64) error { return r.q.SoftDeleteKolPrompt(ctx, generated.SoftDeleteKolPromptParams{ ID: id, TenantID: tenantID, }) } func (r *kolPromptRepository) CreateRevision(ctx context.Context, input CreateKolPromptRevisionInput) (*KolPromptRevision, error) { row, err := r.q.CreateKolPromptRevision(ctx, generated.CreateKolPromptRevisionParams{ TenantID: input.TenantID, PromptID: input.PromptID, RevisionNo: int32(input.RevisionNo), PromptAssetKey: input.PromptAssetKey, SchemaJson: input.SchemaJSON, CardConfigJson: input.CardConfigJSON, CreatedBy: input.CreatedBy, }) if err != nil { return nil, err } return &KolPromptRevision{ ID: row.ID, TenantID: input.TenantID, PromptID: row.PromptID, RevisionNo: int(row.RevisionNo), PromptAssetKey: row.PromptAssetKey, SchemaJSON: row.SchemaJson, CardConfigJSON: row.CardConfigJson, CreatedBy: row.CreatedBy, CreatedAt: timeFromTimestamp(row.CreatedAt), }, nil } func (r *kolPromptRepository) GetRevision(ctx context.Context, tenantID, promptID int64, revNo int) (*KolPromptRevision, error) { row, err := r.q.GetKolPromptRevision(ctx, generated.GetKolPromptRevisionParams{ PromptID: promptID, RevisionNo: int32(revNo), TenantID: tenantID, }) if err != nil { if errors.Is(err, pgx.ErrNoRows) { return nil, nil } return nil, err } return &KolPromptRevision{ ID: row.ID, TenantID: tenantID, PromptID: row.PromptID, RevisionNo: int(row.RevisionNo), PromptAssetKey: row.PromptAssetKey, SchemaJSON: row.SchemaJson, CardConfigJSON: row.CardConfigJson, CreatedBy: row.CreatedBy, CreatedAt: timeFromTimestamp(row.CreatedAt), }, nil } func (r *kolPromptRepository) NextRevisionNo(ctx context.Context, tenantID, promptID int64) (int, error) { next, err := r.q.NextKolPromptRevisionNo(ctx, generated.NextKolPromptRevisionNoParams{ PromptID: promptID, TenantID: tenantID, }) if err != nil { return 0, err } return int(next), nil } func nullableIntFromInt4(value pgtype.Int4) *int { if !value.Valid { return nil } v := int(value.Int32) return &v }