From bbbb371bd127c01fd2decf88d0eddf76b428834f Mon Sep 17 00:00:00 2001 From: Lucas Vaz Date: Tue, 10 Feb 2026 23:46:07 -0300 Subject: [PATCH 1/6] =?UTF-8?q?remo=C3=A7=C3=A3o=20de=20duplicidade=20de?= =?UTF-8?q?=20autores=20da=20base=20de=20dados?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...211011159_fix_remove_autores_duplicados.ts | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 src/database/migration/20260211011159_fix_remove_autores_duplicados.ts diff --git a/src/database/migration/20260211011159_fix_remove_autores_duplicados.ts b/src/database/migration/20260211011159_fix_remove_autores_duplicados.ts new file mode 100644 index 0000000..37416c0 --- /dev/null +++ b/src/database/migration/20260211011159_fix_remove_autores_duplicados.ts @@ -0,0 +1,112 @@ +import { Knex } from 'knex' + +export async function run(knex: Knex): Promise { + await knex.transaction(async (trx) => { + const dupGroups = await trx('autores') + .select([ + 'nome', + 'iniciais', + trx.raw('COUNT(*) as qtde'), + trx.raw('MIN(id) as keep_id'), + trx.raw("GROUP_CONCAT(id ORDER BY id SEPARATOR ',') as ids"), + ]) + .groupBy(['nome', 'iniciais']) + .havingRaw('COUNT(*) > 1') + + if (!dupGroups.length) return + const pairs: Array<{ keep_id: number; drop_id: number }> = [] + for (const g of dupGroups as any[]) { + const keepId = Number(g.keep_id) + const ids = String(g.ids) + .split(',') + .map((s) => Number(s.trim())) + .filter((n) => Number.isFinite(n)) + + for (const id of ids) { + if (id !== keepId) pairs.push({ keep_id: keepId, drop_id: id }) + } + } + + if (!pairs.length) return + await trx.raw(` + DROP TEMPORARY TABLE IF EXISTS autor_merge; + `) + + await trx.raw(` + CREATE TEMPORARY TABLE autor_merge ( + keep_id INT NOT NULL, + drop_id INT NOT NULL, + PRIMARY KEY (drop_id), + KEY (keep_id) + ); + `) + await trx('autor_merge').insert(pairs) + await trx.raw(` + UPDATE especies e + JOIN autor_merge m ON e.autor_id = m.drop_id + SET e.autor_id = m.keep_id; + `) + + await trx.raw(` + UPDATE sub_especies se + JOIN autor_merge m ON se.autor_id = m.drop_id + SET se.autor_id = m.keep_id; + `) + + await trx.raw(` + UPDATE variedades v + JOIN autor_merge m ON v.autor_id = m.drop_id + SET v.autor_id = m.keep_id; + `) + + const hasSubFamiliasAutorId = await trx.schema.hasColumn('sub_familias', 'autor_id') + if (hasSubFamiliasAutorId) { + await trx.raw(` + UPDATE sub_familias sf + JOIN autor_merge m ON sf.autor_id = m.drop_id + SET sf.autor_id = m.keep_id; + `) + } + const [[rest1]] = await trx.raw(` + SELECT COUNT(*) AS c + FROM especies e + JOIN autor_merge m ON e.autor_id = m.drop_id; + `) + + const [[rest2]] = await trx.raw(` + SELECT COUNT(*) AS c + FROM sub_especies se + JOIN autor_merge m ON se.autor_id = m.drop_id; + `) + + const [[rest3]] = await trx.raw(` + SELECT COUNT(*) AS c + FROM variedades v + JOIN autor_merge m ON v.autor_id = m.drop_id; + `) + + const restantes = + Number(rest1?.c ?? 0) + Number(rest2?.c ?? 0) + Number(rest3?.c ?? 0) + + if (restantes > 0) { + throw new Error(`Merge abortado: ainda existem ${restantes} referências para autores duplicados (DROP).`) + } + + if (hasSubFamiliasAutorId) { + const [[rest4]] = await trx.raw(` + SELECT COUNT(*) AS c + FROM sub_familias sf + JOIN autor_merge m ON sf.autor_id = m.drop_id; + `) + if (Number(rest4?.c ?? 0) > 0) { + throw new Error(`Merge abortado: ainda existem ${rest4.c} referências em sub_familias para autores duplicados (DROP).`) + } + } + + await trx.raw(` + DELETE a + FROM autores a + JOIN autor_merge m ON a.id = m.drop_id; + `) + }) +} From 503778bae7c2be6d034e859d8648e5be7411d4dc Mon Sep 17 00:00:00 2001 From: Lucas Vaz Date: Wed, 11 Feb 2026 00:00:01 -0300 Subject: [PATCH 2/6] fix: lint --- ...211011159_fix_remove_autores_duplicados.ts | 123 ++++++++++++------ 1 file changed, 82 insertions(+), 41 deletions(-) diff --git a/src/database/migration/20260211011159_fix_remove_autores_duplicados.ts b/src/database/migration/20260211011159_fix_remove_autores_duplicados.ts index 37416c0..976d921 100644 --- a/src/database/migration/20260211011159_fix_remove_autores_duplicados.ts +++ b/src/database/migration/20260211011159_fix_remove_autores_duplicados.ts @@ -1,26 +1,38 @@ import { Knex } from 'knex' +type DupGroupRow = { + nome: string + iniciais: string | null + qtde: number + keep_id: number + ids: string +} + +type CountRow = { c: number } + export async function run(knex: Knex): Promise { - await knex.transaction(async (trx) => { + await knex.transaction(async trx => { const dupGroups = await trx('autores') .select([ 'nome', 'iniciais', trx.raw('COUNT(*) as qtde'), trx.raw('MIN(id) as keep_id'), - trx.raw("GROUP_CONCAT(id ORDER BY id SEPARATOR ',') as ids"), + trx.raw('GROUP_CONCAT(id ORDER BY id SEPARATOR \',\') as ids') ]) .groupBy(['nome', 'iniciais']) .havingRaw('COUNT(*) > 1') if (!dupGroups.length) return + const pairs: Array<{ keep_id: number; drop_id: number }> = [] - for (const g of dupGroups as any[]) { + + for (const g of dupGroups as unknown as DupGroupRow[]) { const keepId = Number(g.keep_id) const ids = String(g.ids) .split(',') - .map((s) => Number(s.trim())) - .filter((n) => Number.isFinite(n)) + .map(s => Number(s.trim())) + .filter(n => Number.isFinite(n)) for (const id of ids) { if (id !== keepId) pairs.push({ keep_id: keepId, drop_id: id }) @@ -28,85 +40,114 @@ export async function run(knex: Knex): Promise { } if (!pairs.length) return - await trx.raw(` - DROP TEMPORARY TABLE IF EXISTS autor_merge; - `) - await trx.raw(` + await trx.raw('DROP TEMPORARY TABLE IF EXISTS autor_merge') + + await trx.raw( + ` CREATE TEMPORARY TABLE autor_merge ( keep_id INT NOT NULL, drop_id INT NOT NULL, PRIMARY KEY (drop_id), KEY (keep_id) - ); - `) + ) + ` + ) + await trx('autor_merge').insert(pairs) - await trx.raw(` + + await trx.raw( + ` UPDATE especies e JOIN autor_merge m ON e.autor_id = m.drop_id - SET e.autor_id = m.keep_id; - `) + SET e.autor_id = m.keep_id + ` + ) - await trx.raw(` + await trx.raw( + ` UPDATE sub_especies se JOIN autor_merge m ON se.autor_id = m.drop_id - SET se.autor_id = m.keep_id; - `) + SET se.autor_id = m.keep_id + ` + ) - await trx.raw(` + await trx.raw( + ` UPDATE variedades v JOIN autor_merge m ON v.autor_id = m.drop_id - SET v.autor_id = m.keep_id; - `) + SET v.autor_id = m.keep_id + ` + ) const hasSubFamiliasAutorId = await trx.schema.hasColumn('sub_familias', 'autor_id') + if (hasSubFamiliasAutorId) { - await trx.raw(` + await trx.raw( + ` UPDATE sub_familias sf JOIN autor_merge m ON sf.autor_id = m.drop_id - SET sf.autor_id = m.keep_id; - `) + SET sf.autor_id = m.keep_id + ` + ) } - const [[rest1]] = await trx.raw(` + + const [rest1Rows] = await trx.raw( + ` SELECT COUNT(*) AS c FROM especies e - JOIN autor_merge m ON e.autor_id = m.drop_id; - `) + JOIN autor_merge m ON e.autor_id = m.drop_id + ` + ) as unknown as [CountRow[], unknown] - const [[rest2]] = await trx.raw(` + const [rest2Rows] = await trx.raw( + ` SELECT COUNT(*) AS c FROM sub_especies se - JOIN autor_merge m ON se.autor_id = m.drop_id; - `) + JOIN autor_merge m ON se.autor_id = m.drop_id + ` + ) as unknown as [CountRow[], unknown] - const [[rest3]] = await trx.raw(` + const [rest3Rows] = await trx.raw( + ` SELECT COUNT(*) AS c FROM variedades v - JOIN autor_merge m ON v.autor_id = m.drop_id; - `) + JOIN autor_merge m ON v.autor_id = m.drop_id + ` + ) as unknown as [CountRow[], unknown] - const restantes = - Number(rest1?.c ?? 0) + Number(rest2?.c ?? 0) + Number(rest3?.c ?? 0) + const rest1 = rest1Rows[0] + const rest2 = rest2Rows[0] + const rest3 = rest3Rows[0] + + const restantes = Number(rest1?.c ?? 0) + Number(rest2?.c ?? 0) + Number(rest3?.c ?? 0) if (restantes > 0) { throw new Error(`Merge abortado: ainda existem ${restantes} referências para autores duplicados (DROP).`) } if (hasSubFamiliasAutorId) { - const [[rest4]] = await trx.raw(` + const [rest4Rows] = await trx.raw( + ` SELECT COUNT(*) AS c FROM sub_familias sf - JOIN autor_merge m ON sf.autor_id = m.drop_id; - `) + JOIN autor_merge m ON sf.autor_id = m.drop_id + ` + ) as unknown as [CountRow[], unknown] + + const rest4 = rest4Rows[0] + if (Number(rest4?.c ?? 0) > 0) { - throw new Error(`Merge abortado: ainda existem ${rest4.c} referências em sub_familias para autores duplicados (DROP).`) + throw new Error(`Merge abortado: ainda existem ${rest4?.c} referências em sub_familias para autores duplicados (DROP).`) } } - await trx.raw(` + await trx.raw( + ` DELETE a FROM autores a - JOIN autor_merge m ON a.id = m.drop_id; - `) + JOIN autor_merge m ON a.id = m.drop_id + ` + ) }) } From 85473c1d265587f9d2645e946177a7cc0cc924eb Mon Sep 17 00:00:00 2001 From: Lucas Vaz Date: Tue, 3 Mar 2026 23:02:55 -0300 Subject: [PATCH 3/6] =?UTF-8?q?fix:=20renomeia=20coluna=20'iniciais'=20par?= =?UTF-8?q?a=20'observacao'=20e=20ajusta=20c=C3=B3digo=20de=20migration=20?= =?UTF-8?q?para=20Postgres?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controllers/taxonomias-controller.js | 14 +- ...211011159_fix_remove_autores_duplicados.ts | 177 +++++++----------- src/models/Autor.js | 6 +- src/routes/taxonomias.js | 12 +- src/validators/autor-atualiza.js | 11 +- src/validators/autor-cadastro.js | 4 +- 6 files changed, 93 insertions(+), 131 deletions(-) diff --git a/src/controllers/taxonomias-controller.js b/src/controllers/taxonomias-controller.js index 7040b72..253eab9 100644 --- a/src/controllers/taxonomias-controller.js +++ b/src/controllers/taxonomias-controller.js @@ -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: { @@ -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) { @@ -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, @@ -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() @@ -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, }, diff --git a/src/database/migration/20260211011159_fix_remove_autores_duplicados.ts b/src/database/migration/20260211011159_fix_remove_autores_duplicados.ts index 976d921..beada6b 100644 --- a/src/database/migration/20260211011159_fix_remove_autores_duplicados.ts +++ b/src/database/migration/20260211011159_fix_remove_autores_duplicados.ts @@ -2,38 +2,53 @@ import { Knex } from 'knex' type DupGroupRow = { nome: string - iniciais: string | null - qtde: number + observacao: string | null keep_id: number - ids: string + drop_ids: number[] } -type CountRow = { c: number } - export async function run(knex: Knex): Promise { await knex.transaction(async trx => { - const dupGroups = await trx('autores') + 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', - 'iniciais', - trx.raw('COUNT(*) as qtde'), - trx.raw('MIN(id) as keep_id'), - trx.raw('GROUP_CONCAT(id ORDER BY id SEPARATOR \',\') as ids') + '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', 'iniciais']) - .havingRaw('COUNT(*) > 1') + .groupBy(['nome', 'observacao']) + .havingRaw('COUNT(*) > 1')) as unknown as Array<{ + nome: string + observacao: string | null + keep_id: number + ids: number[] + qtde: number + }> if (!dupGroups.length) return const pairs: Array<{ keep_id: number; drop_id: number }> = [] - for (const g of dupGroups as unknown as DupGroupRow[]) { + for (const g of dupGroups) { const keepId = Number(g.keep_id) - const ids = String(g.ids) - .split(',') - .map(s => Number(s.trim())) - .filter(n => Number.isFinite(n)) - + 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 }) } @@ -41,113 +56,51 @@ export async function run(knex: Knex): Promise { if (!pairs.length) return - await trx.raw('DROP TEMPORARY TABLE IF EXISTS autor_merge') - - await trx.raw( - ` - CREATE TEMPORARY TABLE autor_merge ( - keep_id INT NOT NULL, - drop_id INT NOT NULL, - PRIMARY KEY (drop_id), - KEY (keep_id) - ) - ` - ) + 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( - ` + await trx.raw(` UPDATE especies e - JOIN autor_merge m ON e.autor_id = m.drop_id - SET e.autor_id = m.keep_id - ` - ) + SET autor_id = m.keep_id + FROM autor_merge m + WHERE e.autor_id = m.drop_id + `) - await trx.raw( - ` + await trx.raw(` UPDATE sub_especies se - JOIN autor_merge m ON se.autor_id = m.drop_id - SET se.autor_id = m.keep_id - ` - ) + SET autor_id = m.keep_id + FROM autor_merge m + WHERE se.autor_id = m.drop_id + `) - await trx.raw( - ` + await trx.raw(` UPDATE variedades v - JOIN autor_merge m ON v.autor_id = m.drop_id - SET v.autor_id = m.keep_id - ` - ) + 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( - ` + await trx.raw(` UPDATE sub_familias sf - JOIN autor_merge m ON sf.autor_id = m.drop_id - SET sf.autor_id = m.keep_id - ` - ) + SET autor_id = m.keep_id + FROM autor_merge m + WHERE sf.autor_id = m.drop_id + `) } - const [rest1Rows] = await trx.raw( - ` - SELECT COUNT(*) AS c - FROM especies e - JOIN autor_merge m ON e.autor_id = m.drop_id - ` - ) as unknown as [CountRow[], unknown] - - const [rest2Rows] = await trx.raw( - ` - SELECT COUNT(*) AS c - FROM sub_especies se - JOIN autor_merge m ON se.autor_id = m.drop_id - ` - ) as unknown as [CountRow[], unknown] - - const [rest3Rows] = await trx.raw( - ` - SELECT COUNT(*) AS c - FROM variedades v - JOIN autor_merge m ON v.autor_id = m.drop_id - ` - ) as unknown as [CountRow[], unknown] - - const rest1 = rest1Rows[0] - const rest2 = rest2Rows[0] - const rest3 = rest3Rows[0] - - const restantes = Number(rest1?.c ?? 0) + Number(rest2?.c ?? 0) + Number(rest3?.c ?? 0) - - if (restantes > 0) { - throw new Error(`Merge abortado: ainda existem ${restantes} referências para autores duplicados (DROP).`) - } + await trx.raw(` + DELETE FROM autores a + USING autor_merge m + WHERE a.id = m.drop_id + `) - if (hasSubFamiliasAutorId) { - const [rest4Rows] = await trx.raw( - ` - SELECT COUNT(*) AS c - FROM sub_familias sf - JOIN autor_merge m ON sf.autor_id = m.drop_id - ` - ) as unknown as [CountRow[], unknown] - - const rest4 = rest4Rows[0] - - if (Number(rest4?.c ?? 0) > 0) { - throw new Error(`Merge abortado: ainda existem ${rest4?.c} referências em sub_familias para autores duplicados (DROP).`) - } - } - - await trx.raw( - ` - DELETE a - FROM autores a - JOIN autor_merge m ON a.id = m.drop_id - ` - ) + await trx.schema.dropTable('autor_merge') }) -} +} \ No newline at end of file diff --git a/src/models/Autor.js b/src/models/Autor.js index 0287ed9..e66529d 100644 --- a/src/models/Autor.js +++ b/src/models/Autor.js @@ -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, }, }; @@ -39,4 +39,4 @@ export default (Sequelize, DataTypes) => { Model.associate = associate; return Model; -}; +}; \ No newline at end of file diff --git a/src/routes/taxonomias.js b/src/routes/taxonomias.js index 3c88bee..8aa16c5 100644 --- a/src/routes/taxonomias.js +++ b/src/routes/taxonomias.js @@ -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: @@ -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 @@ -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': @@ -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': diff --git a/src/validators/autor-atualiza.js b/src/validators/autor-atualiza.js index 8724754..6102c6e 100644 --- a/src/validators/autor-atualiza.js +++ b/src/validators/autor-atualiza.js @@ -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, }, -}; +}; \ No newline at end of file diff --git a/src/validators/autor-cadastro.js b/src/validators/autor-cadastro.js index 89e8243..56f669d 100644 --- a/src/validators/autor-cadastro.js +++ b/src/validators/autor-cadastro.js @@ -7,9 +7,9 @@ export default { options: [{ min: 3 }], }, }, - iniciais: { + observacao: { in: 'body', isString: true, optional: true, }, -}; +}; \ No newline at end of file From fa8933c7d17fdcf7e4a038c203e05a7990cfd4e5 Mon Sep 17 00:00:00 2001 From: Lucas Vaz Date: Tue, 3 Mar 2026 23:22:12 -0300 Subject: [PATCH 4/6] fix: lint --- .../20260211011159_fix_remove_autores_duplicados.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/database/migration/20260211011159_fix_remove_autores_duplicados.ts b/src/database/migration/20260211011159_fix_remove_autores_duplicados.ts index beada6b..d478ab1 100644 --- a/src/database/migration/20260211011159_fix_remove_autores_duplicados.ts +++ b/src/database/migration/20260211011159_fix_remove_autores_duplicados.ts @@ -1,12 +1,5 @@ import { Knex } from 'knex' -type DupGroupRow = { - nome: string - observacao: string | null - keep_id: number - drop_ids: number[] -} - export async function run(knex: Knex): Promise { await knex.transaction(async trx => { const hasIniciais = await trx.schema.hasColumn('autores', 'iniciais') From c527ace3d7be41863dae28e5fb24bd971d7b4601 Mon Sep 17 00:00:00 2001 From: Lucas Vaz Date: Tue, 3 Mar 2026 23:55:48 -0300 Subject: [PATCH 5/6] fix: lint --- .../migration/20260211011159_fix_remove_autores_duplicados.ts | 4 ++-- src/models/Autor.js | 4 ++-- src/validators/autor-atualiza.js | 2 +- src/validators/autor-cadastro.js | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/database/migration/20260211011159_fix_remove_autores_duplicados.ts b/src/database/migration/20260211011159_fix_remove_autores_duplicados.ts index d478ab1..743e7e0 100644 --- a/src/database/migration/20260211011159_fix_remove_autores_duplicados.ts +++ b/src/database/migration/20260211011159_fix_remove_autores_duplicados.ts @@ -24,7 +24,7 @@ export async function run(knex: Knex): Promise { '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'), + trx.raw('COUNT(*)::int as qtde') ]) .groupBy(['nome', 'observacao']) .havingRaw('COUNT(*) > 1')) as unknown as Array<{ @@ -96,4 +96,4 @@ export async function run(knex: Knex): Promise { await trx.schema.dropTable('autor_merge') }) -} \ No newline at end of file +} diff --git a/src/models/Autor.js b/src/models/Autor.js index e66529d..7848efa 100644 --- a/src/models/Autor.js +++ b/src/models/Autor.js @@ -25,7 +25,7 @@ export default (Sequelize, DataTypes) => { allowNull: false, }, observacao: { - type: DataTypes.STRING(500), + type: DataTypes.STRING(500), allowNull: true, }, }; @@ -39,4 +39,4 @@ export default (Sequelize, DataTypes) => { Model.associate = associate; return Model; -}; \ No newline at end of file +}; diff --git a/src/validators/autor-atualiza.js b/src/validators/autor-atualiza.js index 6102c6e..d85fb1e 100644 --- a/src/validators/autor-atualiza.js +++ b/src/validators/autor-atualiza.js @@ -20,4 +20,4 @@ export default { isInt: true, notEmpty: true, }, -}; \ No newline at end of file +}; diff --git a/src/validators/autor-cadastro.js b/src/validators/autor-cadastro.js index 56f669d..5f0554c 100644 --- a/src/validators/autor-cadastro.js +++ b/src/validators/autor-cadastro.js @@ -12,4 +12,4 @@ export default { isString: true, optional: true, }, -}; \ No newline at end of file +}; From 45c174eb8d9a4e963227420f1937a5f27c892bb7 Mon Sep 17 00:00:00 2001 From: Lucas Vaz Date: Wed, 4 Mar 2026 00:12:12 -0300 Subject: [PATCH 6/6] fix: lint --- ...211011159_fix_remove_autores_duplicados.ts | 68 ++++++++++--------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/src/database/migration/20260211011159_fix_remove_autores_duplicados.ts b/src/database/migration/20260211011159_fix_remove_autores_duplicados.ts index 743e7e0..80ded0b 100644 --- a/src/database/migration/20260211011159_fix_remove_autores_duplicados.ts +++ b/src/database/migration/20260211011159_fix_remove_autores_duplicados.ts @@ -1,5 +1,13 @@ 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 { await knex.transaction(async trx => { const hasIniciais = await trx.schema.hasColumn('autores', 'iniciais') @@ -12,6 +20,7 @@ export async function run(knex: Knex): Promise { } const hasObservacaoNow = await trx.schema.hasColumn('autores', 'observacao') + if (hasObservacaoNow) { await trx.schema.alterTable('autores', table => { table.string('observacao', 500).nullable().alter() @@ -27,13 +36,7 @@ export async function run(knex: Knex): Promise { trx.raw('COUNT(*)::int as qtde') ]) .groupBy(['nome', 'observacao']) - .havingRaw('COUNT(*) > 1')) as unknown as Array<{ - nome: string - observacao: string | null - keep_id: number - ids: number[] - qtde: number - }> + .havingRaw('COUNT(*) > 1')) as unknown as DupGroupRow[] if (!dupGroups.length) return @@ -42,6 +45,7 @@ export async function run(knex: Knex): Promise { 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 }) } @@ -50,6 +54,7 @@ export async function run(knex: Knex): Promise { 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() @@ -58,41 +63,42 @@ export async function run(knex: Knex): Promise { 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 - `) + 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 - `) + 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 - `) + 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 - `) + 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 - `) + DELETE FROM autores a + USING autor_merge m + WHERE a.id = m.drop_id + `) await trx.schema.dropTable('autor_merge') })