package db import ( "context" "database/sql" "github.com/pkg/errors" "github.com/uptrace/bun" ) type deleter[T any] struct { q *bun.DeleteQuery } type systemType interface { isSystem() bool } func DeleteItem[T any](tx bun.Tx) *deleter[T] { return &deleter[T]{ tx.NewDelete(). Model((*T)(nil)), } } func (d *deleter[T]) Where(query string, args ...any) *deleter[T] { d.q = d.q.Where(query, args...) return d } func (d *deleter[T]) Delete(ctx context.Context) error { _, err := d.q.Exec(ctx) if err != nil { if err == sql.ErrNoRows { return nil } } return errors.Wrap(err, "bun.DeleteQuery.Exec") } func DeleteByID[T any](tx bun.Tx, id int) *deleter[T] { return DeleteItem[T](tx).Where("id = ?", id) } func DeleteWithProtection[T systemType](ctx context.Context, tx bun.Tx, id int) error { deleter := DeleteByID[T](tx, id) item, err := GetByID[T](tx, id).GetFirst(ctx) if err != nil { return errors.Wrap(err, "GetByID") } if item == nil { return errors.New("record not found") } if (*item).isSystem() { return errors.New("record is system protected") } return deleter.Delete(ctx) }