feat(certidao): implementar verificação e download de certidão existente
All checks were successful
Dev Build & Deploy Portal / build-deploy (push) Successful in 2m31s

This commit is contained in:
Gabriel Bezerra 2026-05-25 19:28:54 -03:00
parent 5e528f234b
commit c6adda9bfb
4 changed files with 132 additions and 4 deletions

View File

@ -24,10 +24,18 @@ export function useExtratoDebitosPortal() {
{ label: 'Saldo Crédito', value: 3 }, { label: 'Saldo Crédito', value: 3 },
] ]
const ESTADO_DEBITO = 1
const temSelecionado = computed(() => const temSelecionado = computed(() =>
resultados.value.some(t => t.selecionados?.length > 0) resultados.value.some(t => t.selecionados?.length > 0)
) )
const temDebitoSelecionado = computed(() =>
resultados.value.some(t =>
t.selecionados?.some(d => d.codigoEstadoConta === ESTADO_DEBITO)
)
)
const totalizadores = computed(() => { const totalizadores = computed(() => {
let principal = 0, multa = 0, juros = 0, valorTotal = 0 let principal = 0, multa = 0, juros = 0, valorTotal = 0
resultados.value.forEach(t => { resultados.value.forEach(t => {
@ -85,7 +93,13 @@ export function useExtratoDebitosPortal() {
function montarDtoGuia() { function montarDtoGuia() {
return { return {
listaDebitos: resultados.value listaDebitos: resultados.value
.filter(t => t.selecionados?.length > 0) .map(t => ({
...t,
selecionados: (t.selecionados || []).filter(
d => d.codigoEstadoConta === ESTADO_DEBITO
),
}))
.filter(t => t.selecionados.length > 0)
.map(t => ({ .map(t => ({
idTributo: t.idTributo, idTributo: t.idTributo,
identificador: t.identificador, identificador: t.identificador,
@ -139,8 +153,8 @@ export function useExtratoDebitosPortal() {
} }
async function gerarGuia() { async function gerarGuia() {
if (!temSelecionado.value) { if (!temDebitoSelecionado.value) {
mensagemErro.value = 'Selecione pelo menos um débito.' mensagemErro.value = 'Selecione pelo menos um débito em aberto. Parcelas quitadas ou com saldo zerado não geram guia.'
return return
} }
if (!dataVencimento.value) { if (!dataVencimento.value) {
@ -202,6 +216,7 @@ export function useExtratoDebitosPortal() {
filtro, filtro,
opcoesEstadoConta, opcoesEstadoConta,
temSelecionado, temSelecionado,
temDebitoSelecionado,
totalizadores, totalizadores,
consultar, consultar,
limparFiltros, limparFiltros,

View File

@ -22,6 +22,7 @@ const {
filtro, filtro,
opcoesEstadoConta, opcoesEstadoConta,
temSelecionado, temSelecionado,
temDebitoSelecionado,
totalizadores, totalizadores,
consultar, consultar,
limparFiltros, limparFiltros,
@ -209,7 +210,7 @@ function getSegundoNome(texto) {
/> />
</div> </div>
<Button <Button
v-if="temSelecionado" v-if="temDebitoSelecionado"
label="Gerar Guia de Pagamento" label="Gerar Guia de Pagamento"
icon="pi pi-file-pdf" icon="pi pi-file-pdf"
size="small" size="small"

View File

@ -26,6 +26,8 @@ const carregandoConsulta = ref(false)
const carregandoEmissao = ref(false) const carregandoEmissao = ref(false)
const resultado = ref(null) const resultado = ref(null)
const certidaoEmitida = ref(null) const certidaoEmitida = ref(null)
const certidaoExistente = ref(null)
const carregandoDownloadExistente = ref(false)
const mensagemErro = ref('') const mensagemErro = ref('')
const erros = ref({}) const erros = ref({})
@ -147,6 +149,20 @@ async function emitir() {
if (!validarFormulario()) return if (!validarFormulario()) return
carregandoEmissao.value = true carregandoEmissao.value = true
mensagemErro.value = '' mensagemErro.value = ''
try {
const resValida = await certidaoService.verificarValida(documento.value, idModeloSelecionado.value)
const existente = resValida?.data?.data ?? resValida?.data
if (existente?.id != null) {
certidaoExistente.value = existente
etapa.value = 'certidaoExistente'
carregandoEmissao.value = false
return
}
} catch {
// endpoint indisponível prossegue com emissão normalmente
}
try { try {
const buf = await certidaoService.emitir( const buf = await certidaoService.emitir(
documento.value, documento.value,
@ -180,11 +196,34 @@ async function emitir() {
} }
} }
async function downloadCertidaoExistente() {
carregandoDownloadExistente.value = true
mensagemErro.value = ''
try {
const buf = await certidaoService.downloadExistente(certidaoExistente.value.id)
const slug = (certidaoExistente.value?.tituloModelo ?? 'certidao').replace(/\s+/g, '-').toLowerCase()
const url = URL.createObjectURL(new Blob([buf], { type: 'application/pdf' }))
const a = document.createElement('a')
a.href = url
a.download = `certidao-${slug}-${documento.value.replace(/\D/g, '')}.pdf`
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
setTimeout(() => URL.revokeObjectURL(url), 1000)
} catch (e) {
mensagemErro.value = extrairErro(e) ?? 'Erro ao baixar a certidão. Tente novamente.'
} finally {
carregandoDownloadExistente.value = false
}
}
function reiniciar() { function reiniciar() {
documento.value = isAuthenticated.value ? docUsuarioLogado.value : '' documento.value = isAuthenticated.value ? docUsuarioLogado.value : ''
idModeloSelecionado.value = null idModeloSelecionado.value = null
finalidade.value = '' finalidade.value = ''
resultado.value = null resultado.value = null
certidaoEmitida.value = null
certidaoExistente.value = null
mensagemErro.value = '' mensagemErro.value = ''
erros.value = {} erros.value = {}
etapa.value = 'formulario' etapa.value = 'formulario'
@ -360,6 +399,65 @@ function reiniciar() {
</div> </div>
</div> </div>
<div v-else-if="etapa === 'certidaoExistente'" class="space-y-4">
<div class="bg-white dark:bg-slate-800 rounded-2xl border border-amber-200 dark:border-amber-700/50 p-8 flex flex-col items-center text-center gap-4">
<div class="w-16 h-16 bg-amber-50 dark:bg-amber-900/20 rounded-2xl flex items-center justify-center">
<i class="pi pi-exclamation-triangle text-amber-500 dark:text-amber-400 text-3xl" aria-hidden="true" />
</div>
<div>
<p class="text-lg font-bold text-slate-800 dark:text-slate-100"> existe uma certidão válida</p>
<p class="text-sm text-slate-500 dark:text-slate-400 mt-1">
Existe uma certidão do mesmo tipo ainda dentro do prazo de validade.<br>
Você pode baixar a certidão existente em vez de emitir uma nova.
</p>
</div>
</div>
<div class="bg-white dark:bg-slate-800 rounded-2xl border border-slate-200 dark:border-slate-700 p-6 space-y-3">
<p class="text-xs font-semibold text-slate-500 dark:text-slate-400 uppercase tracking-wide">Certidão existente</p>
<div class="space-y-2">
<div class="flex justify-between gap-4">
<span class="text-sm text-slate-500 dark:text-slate-400">Modelo</span>
<span class="text-sm font-medium text-slate-800 dark:text-slate-100 text-right">{{ certidaoExistente?.tituloModelo }}</span>
</div>
<div class="flex justify-between gap-4">
<span class="text-sm text-slate-500 dark:text-slate-400"> certidão</span>
<span class="text-sm font-medium text-slate-800 dark:text-slate-100 text-right">{{ certidaoExistente?.numero }}</span>
</div>
<div class="flex justify-between gap-4">
<span class="text-sm text-slate-500 dark:text-slate-400">Válida até</span>
<span class="text-sm font-semibold text-emerald-600 dark:text-emerald-400 text-right">{{ certidaoExistente?.dataValidade }}</span>
</div>
</div>
</div>
<p v-if="mensagemErro" role="alert" class="text-sm text-red-600 dark:text-red-400 flex items-center gap-1.5">
<i class="pi pi-exclamation-circle" aria-hidden="true" />
{{ mensagemErro }}
</p>
<div class="flex gap-3">
<Button
label="Nova consulta"
severity="secondary"
icon="pi pi-arrow-left"
outlined
class="flex-1"
@click="reiniciar"
/>
<Button
label="Baixar certidão"
icon="pi pi-download"
class="flex-1"
:loading="carregandoDownloadExistente"
:disabled="carregandoDownloadExistente"
@click="downloadCertidaoExistente"
/>
</div>
</div>
<div v-else-if="etapa === 'sucesso'" class="space-y-4"> <div v-else-if="etapa === 'sucesso'" class="space-y-4">
<div class="bg-white dark:bg-slate-800 rounded-2xl border border-emerald-200 dark:border-emerald-700/50 p-8 flex flex-col items-center text-center gap-4"> <div class="bg-white dark:bg-slate-800 rounded-2xl border border-emerald-200 dark:border-emerald-700/50 p-8 flex flex-col items-center text-center gap-4">

View File

@ -26,4 +26,18 @@ export const certidaoService = {
responseType: 'arrayBuffer', responseType: 'arrayBuffer',
}) })
}, },
verificarValida(documento, idModelo) {
return $fetch(proxyUrl('/publico/certidao/valida'), {
headers: FETCH_HEADERS,
query: { documento, idModelo },
})
},
downloadExistente(idCertidao) {
return $fetch(proxyUrl(`/publico/certidao/emitida/${idCertidao}/arquivo`), {
headers: FETCH_HEADERS,
responseType: 'arrayBuffer',
})
},
} }