feat: descrição arquivística NOBRADE multinível com exportação EAD 3, EAC-CPF e AtoM
- pipeline/nobrade: normalizadores de datas (ISO 8601-2), séries, autoridades, espécie/suporte, direitos, lugar e assuntos; montagem dos níveis 0–5 com código de referência BR RJXYZ.BF.<seção>.<série>.<handle>.<imagem> - validador dos elementos obrigatórios: 0 pendências em 26.454 unidades - EAD 3 e 457 EAC-CPF validados contra os XSD - mural: cartão com código, data normalizada, série e reprodução; filtro por série
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
"""Validador dos elementos obrigatórios da NOBRADE, por nível.
|
||||
|
||||
Obrigatórios: 1.1, 1.2, 1.3 (data de produção), 1.4, 1.5, 2.1; 4.1 só nos
|
||||
níveis 0 e 1. Além deles, lista avisos que não reprovam mas pedem revisão.
|
||||
Escreve descricao/pendencias.md e devolve o número de pendências.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections import Counter, defaultdict
|
||||
|
||||
from .config import SAIDA
|
||||
|
||||
|
||||
def verifica(u: dict) -> tuple[list[str], list[str]]:
|
||||
erros, avisos = [], []
|
||||
n = u['nivel']
|
||||
if not u.get('1.1'):
|
||||
erros.append('1.1 código de referência ausente')
|
||||
if not (u.get('1.2') or {}).get('titulo', '').strip():
|
||||
erros.append('1.2 título ausente')
|
||||
prod = (u.get('1.3') or {}).get('producao') or {}
|
||||
if not prod.get('inicio') and not prod.get('fim'):
|
||||
erros.append('1.3 data de produção ausente')
|
||||
if not (u.get('1.4') or {}).get('nome'):
|
||||
erros.append('1.4 nível ausente')
|
||||
if not (u.get('1.5') or {}).get('texto'):
|
||||
erros.append('1.5 dimensão e suporte ausente')
|
||||
if not u.get('2.1'):
|
||||
erros.append('2.1 produtor ausente')
|
||||
if n <= 1 and not u.get('4.1'):
|
||||
erros.append('4.1 condições de acesso ausente (obrigatório nos níveis 0 e 1)')
|
||||
|
||||
if n == 4:
|
||||
if prod.get('qualidade') == 'atribuída pelo arquivista' or (prod.get('notas') or [''])[0].startswith('data atribuída'):
|
||||
avisos.append('1.3 data atribuída pelo arquivista — conferir')
|
||||
if prod.get('motivo') == 'ilegível':
|
||||
avisos.append('1.3 data da origem ilegível')
|
||||
if all(p.get('id') is None for p in u.get('2.1') or []):
|
||||
avisos.append('2.1 autoria não identificada')
|
||||
if u['id'].split('.')[-2] == 'AV':
|
||||
avisos.append('nível 3 em Avulsos — série de origem não identificada')
|
||||
if any('presumida' in x for x in u.get('6.2') or []):
|
||||
avisos.append('1.5 espécie presumida')
|
||||
if any('corrompidos' in x for x in u.get('6.2') or []):
|
||||
avisos.append('valores corrompidos na origem')
|
||||
if u.get('6.1'):
|
||||
avisos.append('6.1 preservação indisponível na origem')
|
||||
if (u.get('4.2') or {}).get('categoria') == 'consultar o detentor':
|
||||
avisos.append('4.2 condição de reprodução não informada na origem')
|
||||
if not (u.get('3.1') or '').strip():
|
||||
avisos.append('3.1 sem âmbito e conteúdo')
|
||||
return erros, avisos
|
||||
|
||||
|
||||
def valida(unidades) -> int:
|
||||
erros, avisos = defaultdict(list), defaultdict(list)
|
||||
por_nivel = Counter()
|
||||
for u in unidades:
|
||||
por_nivel[u['nivel']] += 1
|
||||
e, a = verifica(u)
|
||||
for x in e:
|
||||
erros[x].append(u['id'])
|
||||
for x in a:
|
||||
avisos[x].append(u['id'])
|
||||
|
||||
total = sum(len(v) for v in erros.values())
|
||||
linhas = ['# Pendências da descrição NOBRADE', '',
|
||||
'Gerado por `python -m nobrade`. Obrigatórios reprovam; avisos pedem revisão.', '',
|
||||
'| Nível | Unidades |', '|---|--:|']
|
||||
nomes = {0: 'acervo', 1: 'coleção', 2: 'seção', 3: 'série', 4: 'dossiê', 5: 'item'}
|
||||
linhas += [f'| {n} {nomes[n]} | {c:,} |'.replace(',', '.') for n, c in sorted(por_nivel.items())]
|
||||
linhas += ['', f'## Obrigatórios faltando: {total}', '']
|
||||
if not erros:
|
||||
linhas.append('Nenhum. Todas as unidades têm os elementos obrigatórios do seu nível.')
|
||||
for k, ids in sorted(erros.items(), key=lambda kv: -len(kv[1])):
|
||||
linhas += [f'### {k} — {len(ids)}', '', *[f'- `{i}`' for i in ids[:50]]]
|
||||
if len(ids) > 50:
|
||||
linhas.append(f'- … e mais {len(ids) - 50}')
|
||||
linhas.append('')
|
||||
linhas += ['', '## Avisos', '', '| Aviso | Dossiês |', '|---|--:|']
|
||||
linhas += [f'| {k} | {len(v):,} |'.replace(',', '.') for k, v in sorted(avisos.items(), key=lambda kv: -len(kv[1]))]
|
||||
linhas.append('')
|
||||
(SAIDA / 'pendencias.md').write_text('\n'.join(linhas), encoding='utf-8')
|
||||
return total
|
||||
Reference in New Issue
Block a user