- dms/ai/workflow: qa0x-Pakete nach internal/gates/<thema> verschoben, Paketname = Thema
- internal/migration{acl,audit,...} -> internal/migration/{acl,audit,...}
- Importpfade, Gate-Skripte und zwei relative Migrationspfade angepasst
- keine Logikaenderung; mail-Gates bewusst unveraendert (pfadabhaengig)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
64 lines
2.6 KiB
Go
64 lines
2.6 KiB
Go
package migrationverify
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
)
|
|
|
|
// TenantPoolResolver liefert den Pool der physischen Tenant-Datenbank
|
|
// (Modell C, siehe internal/tenant) zu einem Tenant-Slug.
|
|
type TenantPoolResolver func(ctx context.Context, tenantSlug string) (*pgxpool.Pool, error)
|
|
|
|
// PostgresTenantCountProvider zaehlt users und documents direkt in der
|
|
// Tenant-Datenbank, in die COR-02 (internal/migration/user) bzw. DOK-01
|
|
// (dms/internal/migrationdocument) schreiben. Die Nachrichten-Zieltabelle
|
|
// existiert nicht in Postgres (siehe mail/internal/messagemigration,
|
|
// Metadaten liegen ausschliesslich im Manticore-Suchindex) — das
|
|
// Messages-Feld bleibt hier 0 und muss ueber einen eigenen CountProvider
|
|
// eingespeist werden (siehe CombineUsers-Muster).
|
|
type PostgresTenantCountProvider struct {
|
|
Resolver TenantPoolResolver
|
|
}
|
|
|
|
func (p PostgresTenantCountProvider) Counts(ctx context.Context, tenantSlug string) (TenantCounts, error) {
|
|
pool, err := p.Resolver(ctx, tenantSlug)
|
|
if err != nil {
|
|
return TenantCounts{}, fmt.Errorf("migrationverify: tenant-pool fuer %q: %w", tenantSlug, err)
|
|
}
|
|
|
|
var users, documents int64
|
|
if err := pool.QueryRow(ctx, `SELECT COUNT(*) FROM users`).Scan(&users); err != nil {
|
|
return TenantCounts{}, fmt.Errorf("migrationverify: users zaehlen (%q): %w", tenantSlug, err)
|
|
}
|
|
if err := pool.QueryRow(ctx, `SELECT COUNT(*) FROM documents`).Scan(&documents); err != nil {
|
|
return TenantCounts{}, fmt.Errorf("migrationverify: documents zaehlen (%q): %w", tenantSlug, err)
|
|
}
|
|
return TenantCounts{TenantSlug: tenantSlug, Users: users, Documents: documents}, nil
|
|
}
|
|
|
|
// RegistryApprovedUserCountProvider zaehlt freigegebene
|
|
// user_migration_map-Eintraege je Tenant (siehe
|
|
// internal/migration/user.MapStore.Approved) als Quellzahl der
|
|
// Benutzer-Kerntabelle.
|
|
type RegistryApprovedUserCountProvider struct {
|
|
RegistryPool *pgxpool.Pool
|
|
TenantIDBySlug map[string]string
|
|
}
|
|
|
|
func (p RegistryApprovedUserCountProvider) Counts(ctx context.Context, tenantSlug string) (TenantCounts, error) {
|
|
tenantID, ok := p.TenantIDBySlug[tenantSlug]
|
|
if !ok {
|
|
return TenantCounts{}, fmt.Errorf("migrationverify: kein nexarch_tenant_id fuer slug %q", tenantSlug)
|
|
}
|
|
|
|
var users int64
|
|
if err := p.RegistryPool.QueryRow(ctx, `
|
|
SELECT COUNT(*) FROM user_migration_map WHERE approved_at IS NOT NULL AND nexarch_tenant_id = $1
|
|
`, tenantID).Scan(&users); err != nil {
|
|
return TenantCounts{}, fmt.Errorf("migrationverify: freigegebene user-map-eintraege zaehlen (%q): %w", tenantSlug, err)
|
|
}
|
|
return TenantCounts{TenantSlug: tenantSlug, Users: users}, nil
|
|
}
|