diff --git a/src/controllers/reflora-controller.js b/src/controllers/reflora-controller.js index c0490658..bcf56498 100644 --- a/src/controllers/reflora-controller.js +++ b/src/controllers/reflora-controller.js @@ -14,45 +14,71 @@ import { * A função preparaRequisicao, faz um select no banco verificando se tem registros * onde o horário de fim é nulo e o serviço é Reflora. Se o resultado dessa consulta * é maior que zero significa que foi retornado algum registro. Se existe algum registro no BD, - * onde a data de fim é nula e o serviço é Reflora eu verifico a periodicidade que é. Se a - * periodicidade for manual, ele não pode nem agendar nem pedir novamente. Agora se a periodicidade - * for semanal, mensal ou a cada dois meses, verificamos se a data atual é diferente dá data de - * próxima atualização se for eu atualizo com o novo valor, independentemente se é manual ou periódica. - * Caso seja a mesma data não poderá ser feito a troca. - * @param {*} request, é a requisição vinda do front end, às vezes pode - * conter alguns parâmetros nesse cabeçalhos para conseguir informações - * específicas. - * @param {*} response, é a resposta que será enviada ao back end. - * @param {*} next, é utilizado para chamar a próxima função da pilha. + * onde a data de fim é nula e o serviço é Reflora eu verifico a periodicidade que é. */ export const preparaRequisicao = (request, response) => { const { periodicidade } = request.query; const proximaAtualizacao = request.query.data_proxima_atualizacao; + selectEstaExecutandoServico(1).then(listaExecucaoReflora => { if (listaExecucaoReflora.length > 0) { - const periodicidadeBD = listaExecucaoReflora[0].dataValues.periodicidade; + const execucao = listaExecucaoReflora[0].dataValues; + const { periodicidade: periodicidadeBD } = execucao; + if (periodicidadeBD === 'MANUAL') { - response.status(200).json(JSON.parse(' { "result": "failed" } ')); - } else if ((periodicidadeBD === 'SEMANAL') || (periodicidadeBD === '1MES') || (periodicidadeBD === '2MESES')) { - if (moment().format('DD/MM/YYYY') !== listaExecucaoReflora[0].dataValues.data_proxima_atualizacao) { - const { id } = listaExecucaoReflora[0].dataValues; - atualizaTabelaConfiguracao(1, id, getHoraAtual(), null, periodicidade, proximaAtualizacao).then(() => { - response.status(200).json(JSON.parse(' { "result": "success" } ')); + response.status(200).json({ result: 'failed' }); + return; + } + + if ( + periodicidadeBD === 'SEMANAL' + || periodicidadeBD === '1MES' + || periodicidadeBD === '2MESES' + ) { + const { data_proxima_atualizacao: dataProximaAtualizacao } = execucao; + + const podeExecutar = !dataProximaAtualizacao + || moment().isAfter(moment(dataProximaAtualizacao), 'day'); + + if (podeExecutar) { + atualizaTabelaConfiguracao( + 1, + execucao.id, + getHoraAtual(), + null, + periodicidade, + proximaAtualizacao, + ).then(() => { + response.status(200).json({ result: 'success' }); }); } else { - response.status(200).json(JSON.parse(' { "result": "failed" } ')); + response.status(200).json({ result: 'failed' }); } } } else { selectTemExecucaoServico(1).then(execucaoReflora => { if (execucaoReflora.length === 0) { - insereExecucao(getHoraAtual(), null, periodicidade, proximaAtualizacao, 1).then(() => { - response.status(200).json(JSON.parse(' { "result": "success" } ')); + insereExecucao( + getHoraAtual(), + null, + periodicidade, + proximaAtualizacao, + 1, + ).then(() => { + response.status(200).json({ result: 'success' }); }); } else { - const { id } = execucaoReflora[0].dataValues; - atualizaTabelaConfiguracao(1, id, getHoraAtual(), null, periodicidade, proximaAtualizacao).then(() => { - response.status(200).json(JSON.parse(' { "result": "success" } ')); + const execucao = execucaoReflora[0].dataValues; + + atualizaTabelaConfiguracao( + 1, + execucao.id, + getHoraAtual(), + null, + periodicidade, + proximaAtualizacao, + ).then(() => { + response.status(200).json({ result: 'success' }); }); } }); @@ -62,37 +88,48 @@ export const preparaRequisicao = (request, response) => { /** * A função estaExecutando, faz um select no banco verificando se tem registros - * de execução do Reflora. Se tem execução do reflora é verificado a periodicidade - * se a periodicidade é manual, eu envio um JSON com informações de que está executando - * e que a periodicidade é manual (MANUAL === execução imediata). O mesmo processo vale para - * uma periodicidade que é agendada. Caso não seja retornando nada é retornando ao front - * end que não está sendo executado. - * @param {*} request, é a requisição vinda do front end, às vezes pode - * conter alguns parâmetros nesse cabeçalhos para conseguir informações - * específicas. - * @param {*} response, é a resposta que será enviada ao back end. - * @param {*} next, é utilizado para chamar a próxima função da pilha. + * de execução do Reflora. */ export const estaExecutando = (_, response) => { selectEstaExecutandoServico(1).then(listaExecucaoReflora => { response.header('Access-Control-Allow-Origin', '*'); response.header('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type'); response.header('Access-Control-Allow-Methods', 'GET'); + if (listaExecucaoReflora.length > 0) { - const { periodicidade } = listaExecucaoReflora[0].dataValues; + const execucao = listaExecucaoReflora[0].dataValues; + const { periodicidade } = execucao; + if (periodicidade === 'MANUAL') { - response.status(200).json(JSON.parse(' { "executando": true, "periodicidade": " " } ')); - } else if ((periodicidade === 'SEMANAL') || (periodicidade === '1MES') || (periodicidade === '2MESES')) { - if (moment().format('DD/MM/YYYY') !== listaExecucaoReflora[0].dataValues.data_proxima_atualizacao) { - response.status(200).json(JSON.parse(` { "executando": false, "periodicidade": "${periodicidade}" } `)); - } else { - response.status(200).json(JSON.parse(` { "executando": true, "periodicidade": "${periodicidade}" } `)); - } + response.status(200).json({ + executando: true, + periodicidade: ' ', + }); + return; + } + + if ( + periodicidade === 'SEMANAL' + || periodicidade === '1MES' + || periodicidade === '2MESES' + ) { + const { data_proxima_atualizacao: dataProximaAtualizacao } = execucao; + + const executando = !!dataProximaAtualizacao + && !moment().isAfter(moment(dataProximaAtualizacao), 'day'); + + response.status(200).json({ + executando, + periodicidade, + }); } } else { - response.status(200).json(JSON.parse(' { "executando": false, "periodicidade": " " } ')); + response.status(200).json({ + executando: false, + periodicidade: ' ', + }); } }); }; -export default { }; +export default {}; diff --git a/src/controllers/specieslink-controller.js b/src/controllers/specieslink-controller.js index 5990fdd6..09ce86ac 100644 --- a/src/controllers/specieslink-controller.js +++ b/src/controllers/specieslink-controller.js @@ -12,47 +12,80 @@ import { /** * A função preparaRequisicao, faz um select no banco verificando se tem registros - * onde o horário de fim é nulo e o serviço é Specieslink. Se o resultado dessa consulta + * onde o horário de fim é nulo e o serviço é SpeciesLink. Se o resultado dessa consulta * é maior que zero significa que foi retornado algum registro. Se existe algum registro no BD, - * onde a data de fim é nula e o serviço é Specieslink eu verifico a periodicidade que é. Se a + * onde a data de fim é nula e o serviço é SpeciesLink eu verifico a periodicidade que é. Se a * periodicidade for manual, ele não pode nem agendar nem pedir novamente. Agora se a periodicidade - * for semanal, mensal ou a cada dois meses, verificamos se a data atual é diferente dá data de - * próxima atualização se for eu atualizo com o novo valor, independentemente se é manual ou periódica. - * Caso seja a mesma data não poderá ser feito a troca. - * @param {*} request, é a requisição vinda do front end, às vezes pode - * conter alguns parâmetros nesse cabeçalhos para conseguir informações - * específicas. - * @param {*} response, é a resposta que será enviada ao back end. - * @param {*} next, é utilizado para chamar a próxima função da pilha. + * for semanal, mensal ou a cada dois meses, verificamos se a data atual é diferente da data de + * próxima atualização; se for, eu atualizo com o novo valor. + * Caso seja a mesma data, não poderá ser feito a troca. + * + * @param {*} request requisição vinda do front end + * @param {*} response resposta enviada ao front end */ export const preparaRequisicao = (request, response) => { const { periodicidade } = request.query; const proximaAtualizacao = request.query.data_proxima_atualizacao; + selectEstaExecutandoServico(2).then(listaExecucaoSpecieslink => { if (listaExecucaoSpecieslink.length > 0) { - const periodicidadeBD = listaExecucaoSpecieslink[0].dataValues.periodicidade; + const execucao = listaExecucaoSpecieslink[0].dataValues; + const periodicidadeBD = execucao.periodicidade; + if (periodicidadeBD === 'MANUAL') { - response.status(200).json(JSON.parse(' { "result": "failed" } ')); - } else if ((periodicidadeBD === 'SEMANAL') || (periodicidadeBD === '1MES') || (periodicidadeBD === '2MESES')) { - if (moment().format('DD/MM/YYYY') !== listaExecucaoSpecieslink[0].dataValues.data_proxima_atualizacao) { - const { id } = listaExecucaoSpecieslink[0].dataValues; - atualizaTabelaConfiguracao(2, id, getHoraAtual(), null, periodicidade, proximaAtualizacao).then(() => { - response.status(200).json(JSON.parse(' { "result": "success" } ')); + response.status(200).json({ result: 'failed' }); + return; + } + + if ( + periodicidadeBD === 'SEMANAL' + || periodicidadeBD === '1MES' + || periodicidadeBD === '2MESES' + ) { + const dataProximaAtualizacao = execucao.data_proxima_atualizacao; + + const podeExecutar = !dataProximaAtualizacao + || moment().isAfter(moment(dataProximaAtualizacao), 'day'); + + if (podeExecutar) { + atualizaTabelaConfiguracao( + 2, + execucao.id, + getHoraAtual(), + null, + periodicidade, + proximaAtualizacao, + ).then(() => { + response.status(200).json({ result: 'success' }); }); } else { - response.status(200).json(JSON.parse(' { "result": "failed" } ')); + response.status(200).json({ result: 'failed' }); } } } else { selectTemExecucaoServico(2).then(execucaoSpecieslink => { if (execucaoSpecieslink.length === 0) { - insereExecucao(getHoraAtual(), null, periodicidade, proximaAtualizacao, 2).then(() => { - response.status(200).json(JSON.parse(' { "result": "success" } ')); + insereExecucao( + getHoraAtual(), + null, + periodicidade, + proximaAtualizacao, + 2, + ).then(() => { + response.status(200).json({ result: 'success' }); }); } else { - const { id } = execucaoSpecieslink[0].dataValues; - atualizaTabelaConfiguracao(2, id, getHoraAtual(), null, periodicidade, proximaAtualizacao).then(() => { - response.status(200).json(JSON.parse(' { "result": "success" } ')); + const execucao = execucaoSpecieslink[0].dataValues; + + atualizaTabelaConfiguracao( + 2, + execucao.id, + getHoraAtual(), + null, + periodicidade, + proximaAtualizacao, + ).then(() => { + response.status(200).json({ result: 'success' }); }); } }); @@ -62,37 +95,54 @@ export const preparaRequisicao = (request, response) => { /** * A função estaExecutando, faz um select no banco verificando se tem registros - * de execução do Specieslink. Se tem execução do Specieslink é verificado a periodicidade - * se a periodicidade é manual, eu envio um JSON com informações de que está executando - * e que a periodicidade é manual (MANUAL === execução imediata). O mesmo processo vale para - * uma periodicidade que é agendada. Caso não seja retornando nada é retornando ao front - * end que não está sendo executado. - * @param {*} request, é a requisição vinda do front end, às vezes pode - * conter alguns parâmetros nesse cabeçalhos para conseguir informações - * específicas. - * @param {*} response, é a resposta que será enviada ao back end. - * @param {*} next, é utilizado para chamar a próxima função da pilha. + * de execução do SpeciesLink. Se tem execução é verificado a periodicidade. + * Se a periodicidade é manual, eu envio um JSON informando que está executando. + * O mesmo processo vale para uma periodicidade agendada. + * Caso não exista execução, é retornado que não está executando. + * + * @param {*} request requisição vinda do front end + * @param {*} response resposta enviada ao front end */ export const estaExecutando = (_, response) => { selectEstaExecutandoServico(2).then(listaExecucaoSpecieslink => { response.header('Access-Control-Allow-Origin', '*'); response.header('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type'); response.header('Access-Control-Allow-Methods', 'GET'); + if (listaExecucaoSpecieslink.length > 0) { - const { periodicidade } = listaExecucaoSpecieslink[0].dataValues; + const execucao = listaExecucaoSpecieslink[0].dataValues; + const { periodicidade } = execucao; + if (periodicidade === 'MANUAL') { - response.status(200).json(JSON.parse(' { "executando": true, "periodicidade": " " } ')); - } else if ((periodicidade === 'SEMANAL') || (periodicidade === '1MES') || (periodicidade === '2MESES')) { - if (moment().format('DD/MM/YYYY') !== listaExecucaoSpecieslink[0].dataValues.data_proxima_atualizacao) { - response.status(200).json(JSON.parse(` { "executando": false, "periodicidade": "${periodicidade}" } `)); - } else { - response.status(200).json(JSON.parse(` { "executando": true, "periodicidade": "${periodicidade}" } `)); - } + response.status(200).json({ + executando: true, + periodicidade: ' ', + }); + return; + } + + if ( + periodicidade === 'SEMANAL' + || periodicidade === '1MES' + || periodicidade === '2MESES' + ) { + const dataProximaAtualizacao = execucao.data_proxima_atualizacao; + + const executando = !!dataProximaAtualizacao + && !moment().isAfter(moment(dataProximaAtualizacao), 'day'); + + response.status(200).json({ + executando, + periodicidade, + }); } } else { - response.status(200).json(JSON.parse(' { "executando": false, "periodicidade": " " } ')); + response.status(200).json({ + executando: false, + periodicidade: ' ', + }); } }); }; -export default { }; +export default {}; diff --git a/src/database/migration/20251215003403_altera-tipos-data-configuracao.ts b/src/database/migration/20251215003403_altera-tipos-data-configuracao.ts new file mode 100644 index 00000000..79332d52 --- /dev/null +++ b/src/database/migration/20251215003403_altera-tipos-data-configuracao.ts @@ -0,0 +1,10 @@ +import { Knex } from 'knex' + +export async function run(knex: Knex): Promise { + await knex.raw(` + ALTER TABLE configuracao + MODIFY hora_inicio TIME NOT NULL, + MODIFY hora_fim TIME NULL, + MODIFY data_proxima_atualizacao DATETIME NULL; + `) +} diff --git a/src/herbarium/herbariumdatabase.js b/src/herbarium/herbariumdatabase.js index 803335a8..2c630ac8 100644 --- a/src/herbarium/herbariumdatabase.js +++ b/src/herbarium/herbariumdatabase.js @@ -131,11 +131,19 @@ export function selectEstaExecutandoServico(idServico) { export function insereExecucao(horaAtual, horaFim, periodicidadeUsuario, proximaAtualizacao, servicoUsuario) { const tabelaConfiguracao = modeloConfiguracao(conexao, Sequelize); const promessa = Q.defer(); + const horaInicioFormatada = typeof horaAtual === 'string' + ? horaAtual + : horaAtual.toISOString().substring(11, 19); + + const horaFimFormatada = horaFim ? (typeof horaFim === 'string' ? horaFim : horaFim.toISOString().substring(11, 19)) : null; + + const proximaAtualizacaoISO = proximaAtualizacao ? new Date(proximaAtualizacao) : null; + tabelaConfiguracao.create({ - hora_inicio: horaAtual, - hora_fim: horaFim, + hora_inicio: horaInicioFormatada, + hora_fim: horaFimFormatada, periodicidade: periodicidadeUsuario, - data_proxima_atualizacao: proximaAtualizacao, + data_proxima_atualizacao: proximaAtualizacaoISO, nome_arquivo: null, servico: servicoUsuario, }).then(() => { @@ -161,38 +169,43 @@ export function insereExecucao(horaAtual, horaFim, periodicidadeUsuario, proxima * @return promessa.promise, como é assíncrono ele só retorna quando resolver, ou seja, * quando terminar de realizar a atualização. */ -export function atualizaTabelaConfiguracao(idServico, idExecucao, horaInicio, horaFim, periodicidadeUsuario, proximaAtualizacao) { - if (idServico === 1) { - const tabelaConfiguracaoReflora = modeloConfiguracao(conexao, Sequelize); - const promessa = Q.defer(); - tabelaConfiguracaoReflora.update( - { - hora_inicio: horaInicio, - hora_fim: horaFim, - periodicidade: periodicidadeUsuario, - data_proxima_atualizacao: proximaAtualizacao, - }, - { where: { id: idExecucao } }, - ).then(() => { - promessa.resolve(); - }); - return promessa.promise; - } - const tabelaConfiguracaoSpeciesLink = modeloConfiguracao(conexao, Sequelize); +export function atualizaTabelaConfiguracao( + idServico, + idExecucao, + horaInicio, + horaFim, + periodicidadeUsuario, + proximaAtualizacao, +) { + const tabelaConfiguracao = modeloConfiguracao(conexao, Sequelize); const promessa = Q.defer(); - tabelaConfiguracaoSpeciesLink.update( + + // Normaliza hora_inicio + const horaInicioFormatada = horaInicio instanceof Date + ? horaInicio.toISOString().substring(11, 19) + : horaInicio; + + // Normaliza hora_fim + const horaFimFormatada = horaFim ? (horaFim instanceof Date ? horaFim.toISOString().substring(11, 19) : horaFim) : null; + + // Normaliza data_proxima_atualizacao (ISO) + const proximaAtualizacaoISO = proximaAtualizacao + ? new Date(proximaAtualizacao) + : null; + + tabelaConfiguracao.update( { - hora_inicio: horaInicio, - hora_fim: horaFim, + hora_inicio: horaInicioFormatada, + hora_fim: horaFimFormatada, periodicidade: periodicidadeUsuario, - data_proxima_atualizacao: proximaAtualizacao, + data_proxima_atualizacao: proximaAtualizacaoISO, }, { where: { id: idExecucao } }, ).then(() => { promessa.resolve(); }); - return promessa.promise; + return promessa.promise; } /** diff --git a/src/herbarium/main.js b/src/herbarium/main.js index 9da5e197..89bba3dc 100644 --- a/src/herbarium/main.js +++ b/src/herbarium/main.js @@ -138,7 +138,11 @@ function ehPossivelFazerComparacao(nomeArquivo, idServico) { */ export function preparaExecucao(existeExecucao, idServico) { const promessa = Q.defer(); - const nomeArquivo = processaNomeLog(existeExecucao.dataValues.hora_inicio); + const horaInicio = existeExecucao.dataValues.hora_inicio; + const horaInicioFormatada = horaInicio instanceof Date + ? horaInicio.toISOString().substring(11, 19) // HH:mm:ss + : horaInicio; + const nomeArquivo = processaNomeLog(horaInicioFormatada); ehPossivelFazerComparacao(nomeArquivo, idServico).then(() => { const { id } = existeExecucao.dataValues; let conteudoLOG; diff --git a/src/models/Configuracao.js b/src/models/Configuracao.js index 61723144..9fa7be34 100644 --- a/src/models/Configuracao.js +++ b/src/models/Configuracao.js @@ -1,27 +1,16 @@ -function associate(/* modelos */) { +function associate(/* models */) { + // não há associações para este model } -/** -CREATE TABLE `configuracao` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `hora_inicio` varchar(19) NOT NULL, - `hora_fim` varchar(19) DEFAULT NULL, - `periodicidade` enum('MANUAL','SEMANAL','1MES','2MESES') DEFAULT NULL, - `data_proxima_atualizacao` varchar(10) DEFAULT NULL, - `nome_arquivo` varchar(50) DEFAULT NULL, - `servico` enum('REFLORA','SPECIESLINK') DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET='latin1'; - */ export default (Sequelize, DataTypes) => { const attributes = { hora_inicio: { - type: DataTypes.STRING(19), + type: DataTypes.TIME, allowNull: false, }, hora_fim: { - type: DataTypes.STRING(19), + type: DataTypes.TIME, allowNull: true, }, periodicidade: { @@ -30,7 +19,7 @@ export default (Sequelize, DataTypes) => { allowNull: true, }, data_proxima_atualizacao: { - type: DataTypes.STRING(10), + type: DataTypes.DATE, allowNull: true, }, nome_arquivo: { @@ -45,7 +34,6 @@ export default (Sequelize, DataTypes) => { const options = { freezeTableName: false, - // Disabilita o created_at e updated_at timestamps: false, tableName: 'configuracao', };