feat: ticketing sync workers with idempotent import and orphan flagging (phase 6)
- task domain model + exhaustive §4.4 status machine tests (single source of truth) - per-customer polling workers reconciled every 30s from the customers collection; panic-safe runs; manual sync-now trigger; status provider for the admin panel - §5.3 upsert keyed on (system, key, customerId): refreshes content while status=imported, records upstream_changed timeline + notification after - attachments cached into GridFS via connector-authorized downloads - orphaned tickets flagged with timeline + consultant notification, never deleted; idempotent across polls - consultant identity from users.extra.ticketingIdentities per system - notifications store (insert/list/unread-count/mark-read) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -115,6 +115,23 @@ func (s *Store) LinkOIDC(ctx context.Context, userID, issuer, subject string) er
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListAdminIDs returns ids of all active admins (system notifications).
|
||||
func (s *Store) ListAdminIDs(ctx context.Context) ([]string, error) {
|
||||
cur, err := s.users().Find(ctx, bson.M{"roles.admin": true, "disabled": false})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("list admins: %w", err)
|
||||
}
|
||||
var users []domain.User
|
||||
if err := cur.All(ctx, &users); err != nil {
|
||||
return nil, fmt.Errorf("decode admins: %w", err)
|
||||
}
|
||||
ids := make([]string, len(users))
|
||||
for i, u := range users {
|
||||
ids[i] = u.ID
|
||||
}
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
// TouchLastSeen updates lastSeenAt without bumping version (pure telemetry).
|
||||
func (s *Store) TouchLastSeen(ctx context.Context, userID string) error {
|
||||
_, err := s.users().UpdateOne(ctx, bson.M{"_id": userID},
|
||||
|
||||
Reference in New Issue
Block a user