Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions src/controllers/taxonomias-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -1341,9 +1341,9 @@ export const editarVariedade = (request, response, next) => {

// //////////////////AUTORES//////////////////
export const cadastrarAutores = (request, response, next) => {
let { nome, iniciais } = request.body;
let { nome, observacao } = request.body;
nome = limparEspacos(nome);
iniciais = limparEspacos(iniciais);
observacao = limparEspacos(observacao);
const callback = transaction => Promise.resolve()
.then(() => Autor.findOne({
where: {
Expand All @@ -1356,7 +1356,7 @@ export const cadastrarAutores = (request, response, next) => {
throw new BadRequestExeption(513);
}
})
.then(() => Autor.create({ nome, iniciais }, transaction));
.then(() => Autor.create({ nome, observacao }, transaction));
sequelize.transaction(callback)
.then(autorCriado => {
if (!autorCriado) {
Expand Down Expand Up @@ -1409,7 +1409,7 @@ export const buscarAutores = async (request, response, next) => {
];

const result = await Autor.findAndCountAll({
attributes: ['id', 'nome', 'iniciais'],
attributes: ['id', 'nome', 'observacao'],
order,
limit: limite,
offset,
Expand Down Expand Up @@ -1476,9 +1476,9 @@ export const excluirAutores = (request, response, next) => {
};

export const editarAutores = (request, response, next) => {
let { nome, iniciais } = request.body;
let { nome, observacao } = request.body;
nome = limparEspacos(nome);
iniciais = limparEspacos(iniciais);
observacao = limparEspacos(observacao);
const autorId = parseInt(request.params.autor_id);

const callback = transaction => Promise.resolve()
Expand All @@ -1493,7 +1493,7 @@ export const editarAutores = (request, response, next) => {
throw new BadRequestExeption(517);
}
})
.then(() => Autor.update({ nome, iniciais }, {
.then(() => Autor.update({ nome, observacao }, {
where: {
id: autorId,
},
Expand Down
105 changes: 105 additions & 0 deletions src/database/migration/20260211011159_fix_remove_autores_duplicados.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { Knex } from 'knex'

type DupGroupRow = {
nome: string
observacao: string | null
keep_id: number
ids: number[]
qtde: number
}

export async function run(knex: Knex): Promise<void> {
await knex.transaction(async trx => {
const hasIniciais = await trx.schema.hasColumn('autores', 'iniciais')
const hasObservacao = await trx.schema.hasColumn('autores', 'observacao')

if (hasIniciais && !hasObservacao) {
await trx.schema.alterTable('autores', table => {
table.renameColumn('iniciais', 'observacao')
})
}

const hasObservacaoNow = await trx.schema.hasColumn('autores', 'observacao')

if (hasObservacaoNow) {
await trx.schema.alterTable('autores', table => {
table.string('observacao', 500).nullable().alter()
})
}

const dupGroups = (await trx('autores')
.select([
'nome',
'observacao',
trx.raw('MIN(id)::int as keep_id'),
trx.raw('ARRAY_AGG(id ORDER BY id) as ids'),
trx.raw('COUNT(*)::int as qtde')
])
.groupBy(['nome', 'observacao'])
.havingRaw('COUNT(*) > 1')) as unknown as DupGroupRow[]

if (!dupGroups.length) return

const pairs: Array<{ keep_id: number; drop_id: number }> = []

for (const g of dupGroups) {
const keepId = Number(g.keep_id)
const ids = (g.ids ?? []).map(n => Number(n)).filter(Number.isFinite)

for (const id of ids) {
if (id !== keepId) pairs.push({ keep_id: keepId, drop_id: id })
}
}

if (!pairs.length) return

await trx.raw('DROP TABLE IF EXISTS autor_merge')

await trx.schema.createTable('autor_merge', table => {
table.integer('keep_id').notNullable()
table.integer('drop_id').notNullable().primary()
})

await trx('autor_merge').insert(pairs)

await trx.raw(`
UPDATE especies e
SET autor_id = m.keep_id
FROM autor_merge m
WHERE e.autor_id = m.drop_id
`)

await trx.raw(`
UPDATE sub_especies se
SET autor_id = m.keep_id
FROM autor_merge m
WHERE se.autor_id = m.drop_id
`)

await trx.raw(`
UPDATE variedades v
SET autor_id = m.keep_id
FROM autor_merge m
WHERE v.autor_id = m.drop_id
`)

const hasSubFamiliasAutorId = await trx.schema.hasColumn('sub_familias', 'autor_id')

if (hasSubFamiliasAutorId) {
await trx.raw(`
UPDATE sub_familias sf
SET autor_id = m.keep_id
FROM autor_merge m
WHERE sf.autor_id = m.drop_id
`)
}

await trx.raw(`
DELETE FROM autores a
USING autor_merge m
WHERE a.id = m.drop_id
`)

await trx.schema.dropTable('autor_merge')
})
}
4 changes: 2 additions & 2 deletions src/models/Autor.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ export default (Sequelize, DataTypes) => {
type: DataTypes.STRING(200),
allowNull: false,
},
iniciais: {
type: DataTypes.STRING(200),
observacao: {
type: DataTypes.STRING(500),
allowNull: true,
},
};
Expand Down
12 changes: 9 additions & 3 deletions src/routes/taxonomias.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ const generosOrdenacaoMiddleware = criaOrdenacaoMiddleware(['genero', 'familia',
const especiesOrdenacaoMiddleware = criaOrdenacaoMiddleware(['especie', 'reino', 'familia', 'genero', 'familia', 'autor'], 'nome', 'asc');
const subEspeciesOrdenacaoMiddleware = criaOrdenacaoMiddleware(['subespecie', 'reino', 'familia', 'genero', 'especie', 'autor'], 'nome', 'asc');
const variedadesOrdenacaoMiddleware = criaOrdenacaoMiddleware(['variedade', 'reino', 'familia', 'genero', 'especie', 'autor'], 'nome', 'asc');
const autorOrdenacaoMiddleware = criaOrdenacaoMiddleware(['autor', 'iniciais'], 'nome', 'asc');

const autorOrdenacaoMiddleware = criaOrdenacaoMiddleware(['autor', 'observacao'], 'nome', 'asc');
/**
* @swagger
* tags:
Expand Down Expand Up @@ -1534,10 +1533,15 @@ export default app => {
* properties:
* nome:
* type: string
* observacao:
* type: string
* nullable: true
* maxLength: 500
* required:
* - nome
* example:
* nome: "A. Author"
* observacao: "Observação opcional sobre o autor"
* responses:
* 201:
* description: Autor cadastrado com sucesso
Expand All @@ -1548,6 +1552,7 @@ export default app => {
* example:
* id: 1
* nome: "A. Author"
* observacao: "Observação opcional sobre o autor"
* '400':
* $ref: '#/components/responses/BadRequest'
* '401':
Expand Down Expand Up @@ -1600,9 +1605,10 @@ export default app => {
* type: integer
* nome:
* type: string
* iniciais:
* observacao:
* type: string
* nullable: true
* maxLength: 500
* '400':
* $ref: '#/components/responses/BadRequest'
* '401':
Expand Down
9 changes: 6 additions & 3 deletions src/validators/autor-atualiza.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,22 @@ export default {
nome: {
in: 'body',
isString: true,
isEmpty: false,
notEmpty: true,
isLength: {
options: [{ min: 3 }],
},
},
iniciais: {
observacao: {
in: 'body',
isString: true,
optional: true,
isLength: {
options: [{ max: 500 }],
},
},
autor_id: {
in: 'params',
isInt: true,
isEmpty: false,
notEmpty: true,
},
};
2 changes: 1 addition & 1 deletion src/validators/autor-cadastro.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export default {
options: [{ min: 3 }],
},
},
iniciais: {
observacao: {
in: 'body',
isString: true,
optional: true,
Expand Down
Loading