refactor: remove unnecessary fields and improve validation in cadastro_jogos desktop XML
davinTI/jogos_matheus/pipeline/head There was a failure building this commit

This commit is contained in:
Matheus
2026-09-24 14:26:57 -03:00
parent 6891f63534
commit c4fce638ca
2 changed files with 170 additions and 56 deletions
+101 -52
View File
@@ -20,7 +20,6 @@
'GENERO', 'GENERO',
'ANO_LANCAMENTO', 'ANO_LANCAMENTO',
'PRODUTORA', 'PRODUTORA',
'NOTA_MEDIA',
'DESCRICAO' 'DESCRICAO'
], ],
camposTable: [ camposTable: [
@@ -29,7 +28,6 @@
'GENERO', 'GENERO',
'ANO_LANCAMENTO', 'ANO_LANCAMENTO',
'PRODUTORA', 'PRODUTORA',
'NOTA_MEDIA',
'DESCRICAO' 'DESCRICAO'
], ],
}, },
@@ -39,7 +37,6 @@
['GENERO', 'cbbGenero', 'String'], ['GENERO', 'cbbGenero', 'String'],
['ANO_LANCAMENTO', 'txfAnoLancamento', 'Number'], ['ANO_LANCAMENTO', 'txfAnoLancamento', 'Number'],
['PRODUTORA', 'txfProdutora', 'String'], ['PRODUTORA', 'txfProdutora', 'String'],
['NOTA_MEDIA', 'txfNotaMedia', 'Number'],
['DESCRICAO', 'txaDescricao', 'String'] ['DESCRICAO', 'txaDescricao', 'String']
], ],
validacaoExclusao: [], validacaoExclusao: [],
@@ -106,7 +103,7 @@
engine.getField("txfEmail").setValue(""); engine.getField("txfEmail").setValue("");
engine.getField("txfComentario").setValue(""); engine.getField("txfComentario").setValue("");
engine.getField("dcfNota").setValue(""); engine.getField("dcfNota").setValue("");
engine.getField("dtfDataAvaliacao").setValue(null);
} }
function resetPanelGames(){ function resetPanelGames(){
@@ -119,29 +116,26 @@
engine.getField("txfNotaMedia").setValue(""); engine.getField("txfNotaMedia").setValue("");
} }
/*
* Gerencia apenas os campos de negócio obrigatórios.
* Os campos de ID (CODIGO) NÃO entram aqui, pois são
* gerados automaticamente e ficariam vazios em uma inclusão.
*/
function organizeRequiredFields(whichForm, isToRequest) { function organizeRequiredFields(whichForm, isToRequest) {
var fields = []; var fields = [];
if(whichForm === "jogos"){ if(whichForm === "jogos"){
fields = ["txfCodigo", "txfTitulo", "cbbGenero", "txfAnoLancamento", "txfProdutora", "txaDescricao"]; fields = ["txfTitulo", "cbbGenero", "txfAnoLancamento", "txfProdutora", "txaDescricao"];
} else if(whichForm === "avaliacoes") { } else if(whichForm === "avaliacoes") {
fields = ["txfCodigoAvaliacao", "txfCodigoJogo", "txfNome", "txfEmail", "txfComentario", "dcfNota"]; fields = ["txfNome", "txfEmail", "txfComentario", "dcfNota"];
} }
if(isToRequest) { fields.forEach(function(fieldId) {
fields.forEach(function(fieldId) { var field = engine.getField(fieldId);
var field = engine.getField(fieldId); if (field) {
if (field) { field.setRequired(isToRequest);
field.setRequired(true); }
} });
}); }
} else {
fields.forEach(function(fieldId) {
var field = engine.getField(fieldId);
if (field) {
field.setRequired(false);
}
});
}};
function showTableReviews(gameId) { function showTableReviews(gameId) {
if(!gameId) { if(!gameId) {
@@ -195,13 +189,37 @@
caption="Comentário" required="true" /> caption="Comentário" required="true" />
<DecimalField width="100%" id="dcfNota" type="decimal" <DecimalField width="100%" id="dcfNota" type="decimal"
caption="Nota (0 a 10)" caption="Nota (0 a 10)"
required="true" /> required="true">
<validation>
<script language="JavaScript">
<![CDATA[
function validator(){
this.getMessage = function(){
return "A nota deve ser um número entre 0 e 10.";
};
this.isValid = function(){
if(!engine.getField("dcfNota").isRequired()){
return true;
}
var value = engine.getField("dcfNota").getValue();
if(value === null || value === ""){
return true; /* obrigatoriedade tratada pelo required */
}
return value >= 0 && value <= 10;
};
}
var script = new validator();
]]>
</script>
</validation>
</DecimalField>
<ButtonWidget id="btnSalvarAvaliacao" caption="Salvar" defaultIcon="SAVE" <ButtonWidget id="btnSalvarAvaliacao" caption="Salvar" defaultIcon="SAVE"
style="BLUE"> style="BLUE">
<onClickScript language="JavaScript"> <onClickScript language="JavaScript">
<![CDATA[ <![CDATA[
function run() { function run() {
engine.getGlobalVariable("organizeRequiredFields")("avaliacoes", false); engine.getGlobalVariable("organizeRequiredFields")("avaliacoes", true);
engine.getField("txfCodigoJogo").setValue(engine.getField("dbtJogos").getValue()); engine.getField("txfCodigoJogo").setValue(engine.getField("dbtJogos").getValue());
var hoje = new Date(); var hoje = new Date();
@@ -209,16 +227,14 @@
engine.getField("dtfDataAvaliacao").setValue(javaDate); engine.getField("dtfDataAvaliacao").setValue(javaDate);
if(engine.isValid()){ if(engine.isValid()){
engine.getField("txfCodigoJogo").setValue(engine.getField("dbtJogos").getValue());
var config_avaliacoes = engine.getGlobalVariable("config_avaliacoes"); var config_avaliacoes = engine.getGlobalVariable("config_avaliacoes");
var lib = libService.loadScript("lib_cadastro_padrao"); var lib = libService.loadScript("lib_cadastro_padrao");
var lib_msg = libService.loadScript("messages");
var id = engine.getField("txfCodigoAvaliacao").getValue(); var id = engine.getField("txfCodigoAvaliacao").getValue();
var retorno = lib.fncGravarRegistro(config_avaliacoes, id); var retorno = lib.fncGravarRegistro(config_avaliacoes, id);
engine.getField("dbtJogos").refresh(); engine.getField("dbtJogos").refresh();
if (retorno) { if (retorno) {
var lib_msg = libService.loadScript("messages");
engine.getField("txfCodigoAvaliacao").setValue(retorno); engine.getField("txfCodigoAvaliacao").setValue(retorno);
engine.getField("dbtAvaliacoes").refresh(); engine.getField("dbtAvaliacoes").refresh();
lib_msg.showNotification({ lib_msg.showNotification({
@@ -227,11 +243,16 @@
msg: "Avaliação foi salva com sucesso!", msg: "Avaliação foi salva com sucesso!",
position: lib_msg.notificationPosition.bottom_right, position: lib_msg.notificationPosition.bottom_right,
}); });
} engine.getLayout("wltCriarAvaliacoes").closeWindow();
engine.getLayout("wltCriarAvaliacoes").closeWindow(); engine.getLayout("wltListaAvaliacoes").showWindow();
engine.getLayout("wltListaAvaliacoes").showWindow(); } else {
engine.getGlobalVariable("organizeRequiredFields")("avaliacoes", true); lib_msg.showNotification({
type: lib_msg.notificationType.tray,
caption: "Erro!",
msg: "Não foi possível salvar a avaliação.",
position: lib_msg.notificationPosition.bottom_right,
});
}
} }
} }
]]> ]]>
@@ -255,7 +276,11 @@
var sqlBase = "SELECT * FROM TB_MATHEUS_MEDEIROS_AVALIACOES ORDER BY CODIGO"; var sqlBase = "SELECT * FROM TB_MATHEUS_MEDEIROS_AVALIACOES ORDER BY CODIGO";
var id_jogo = engine.getField("dbtJogos").getValue(); var id_jogo = engine.getField("dbtJogos").getValue();
if(id_jogo != null){ if(id_jogo != null){
sqlBase = "SELECT * FROM TB_MATHEUS_MEDEIROS_AVALIACOES WHERE ID_JOGO = " + id_jogo + " ORDER BY CODIGO"; /* Cast numérico para evitar injeção via concatenação */
id_jogo = parseInt(id_jogo, 10);
if(!isNaN(id_jogo)){
sqlBase = "SELECT * FROM TB_MATHEUS_MEDEIROS_AVALIACOES WHERE ID_JOGO = " + id_jogo + " ORDER BY CODIGO";
}
} }
return sqlBase; return sqlBase;
} }
@@ -350,7 +375,7 @@
<CrudPanel id="pnlListaJogos" width="100%" height="100%" visible="true"> <CrudPanel id="pnlListaJogos" width="100%" height="100%" visible="true">
<Header> <Header>
<Caption></Caption> <Caption>Lista de jogos</Caption>
<SubCaption>Cadastro de jogos</SubCaption> <SubCaption>Cadastro de jogos</SubCaption>
</Header> </Header>
<Section height="100%" width="100%" caption="Jogos" subCaption="Veja todos os jogos" id = "secJogos"> <Section height="100%" width="100%" caption="Jogos" subCaption="Veja todos os jogos" id = "secJogos">
@@ -382,7 +407,7 @@
</HorizontalLayout> </HorizontalLayout>
<DBTable id="dbtJogos" align="MIDDLE_CENTER" width="100%" height="100%" type="string" expandRatio="0.5" showRowCount="true" drawRefreshButton="true" gridSelectable="true" > <DBTable id="dbtJogos" align="MIDDLE_CENTER" width="100%" height="100%" type="string" expandRatio="0.5" showRowCount="true" drawRefreshButton="true" gridSelectable="true" >
<datasource> <datasource>
<sqlBuilderDataSource connection-key="" language="JavaScript"> <sqlBuilderDataSource connection-key="vitruvio" language="JavaScript">
<![CDATA[ <![CDATA[
function buildSQL(_){ function buildSQL(_){
var txfPesquisa = engine.getField("txfPesquisa").getValue(); var txfPesquisa = engine.getField("txfPesquisa").getValue();
@@ -390,7 +415,10 @@
var sqlBase = "SELECT J.CODIGO, J.TITULO, J.GENERO, J.ANO_LANCAMENTO, J.PRODUTORA, COALESCE(ROUND(AVG(A.NOTA), 2), 0) AS NOTA_MEDIA, J.DESCRICAO FROM TB_MATHEUS_MEDEIROS_JOGOS J LEFT JOIN TB_MATHEUS_MEDEIROS_AVALIACOES A ON J.CODIGO = A.ID_JOGO"; var sqlBase = "SELECT J.CODIGO, J.TITULO, J.GENERO, J.ANO_LANCAMENTO, J.PRODUTORA, COALESCE(ROUND(AVG(A.NOTA), 2), 0) AS NOTA_MEDIA, J.DESCRICAO FROM TB_MATHEUS_MEDEIROS_JOGOS J LEFT JOIN TB_MATHEUS_MEDEIROS_AVALIACOES A ON J.CODIGO = A.ID_JOGO";
if (txfPesquisa) { if (txfPesquisa) {
sqlBase += " WHERE UPPER(J.TITULO) LIKE UPPER('%" + txfPesquisa + "%')"; /* Escapa aspas simples para mitigar SQL Injection.
O ideal é usar bind/parâmetro do framework. */
var safe = ("" + txfPesquisa).replace(/'/g, "''");
sqlBase += " WHERE UPPER(J.TITULO) LIKE UPPER('%" + safe + "%')";
} }
sqlBase += " GROUP BY J.CODIGO, J.TITULO, J.GENERO, J.ANO_LANCAMENTO, J.PRODUTORA, J.DESCRICAO"; sqlBase += " GROUP BY J.CODIGO, J.TITULO, J.GENERO, J.ANO_LANCAMENTO, J.PRODUTORA, J.DESCRICAO";
@@ -498,6 +526,7 @@
<onClickScript language="JavaScript"> <onClickScript language="JavaScript">
<![CDATA[ <![CDATA[
function run (){ function run (){
engine.getGlobalVariable("resetPanelGames")();
engine.getGlobalVariable("changeCrudPanel")("cadastroJogo"); engine.getGlobalVariable("changeCrudPanel")("cadastroJogo");
} }
]]> ]]>
@@ -529,7 +558,7 @@
<VerticalLayout caption="Dados do Jogo" width="100%" spacing="true"> <VerticalLayout caption="Dados do Jogo" width="100%" spacing="true">
<TextField id="txfCodigo" caption="Código" type="number" width="100%" enabled="false" visible="false"/> <TextField id="txfCodigo" caption="Código" type="number" width="100%" enabled="false" visible="false"/>
<NumericField id="txfNotaMedia" caption="Nota Média" type="number" width="100%" enabled="false" visible="false"/> <NumericField id="txfNotaMedia" caption="Nota Média" type="number" width="100%" enabled="false" visible="false"/>
<TextField id="txfTitulo" caption="Título" type="string" width="100%" required="true"/> <TextField id="txfTitulo" caption="Título" type="string" width="100%" required="true" minLength="3"/>
<ComboBox id="cbbGenero" type="string" caption="Gênero" width="100%" required="true"> <ComboBox id="cbbGenero" type="string" caption="Gênero" width="100%" required="true">
<entry key="ACAO" value="Ação"/> <entry key="ACAO" value="Ação"/>
<entry key="AVENTURA" value="Aventura"/> <entry key="AVENTURA" value="Aventura"/>
@@ -540,19 +569,32 @@
<entry key="Sobrevivencia" value="Sobrevivência"/> <entry key="Sobrevivencia" value="Sobrevivência"/>
</ComboBox> </ComboBox>
<TextField id="txfAnoLancamento" caption="Ano de Lançamento" type="number" width="100%" required="true"> <TextField id="txfAnoLancamento" caption="Ano de Lançamento" type="number" width="100%" required="true">
<validation> <validation>
<script language="JavaScript"> <script language="JavaScript">
<![CDATA[ <![CDATA[
function validate() { function validator(){
var ano = this.getValue();
var anoAtual = new Date().getFullYear();
if (ano < 1950 || ano > anoAtual) { this.getMessage = function(){
throw new Error("Ano de lançamento inválido. Deve estar entre 1950 e " + anoAtual); return "O ano de lançamento deve ser um número válido entre 1970 e o ano atual.";
} };
}
]]>
</script> this.isValid = function(){
</validation>
if(!engine.getField("txfAnoLancamento").isRequired()){
return true;
}
var value = engine.getField("txfAnoLancamento").getValue();
var currentYear = new Date().getFullYear();
return value >= 1970 && value <= currentYear;
};
}
var script = new validator();
]]>
</script>
</validation>
</TextField> </TextField>
<TextField id="txfProdutora" caption="Produtora" type="string" width="100%" required="true" maxLength="50"/> <TextField id="txfProdutora" caption="Produtora" type="string" width="100%" required="true" maxLength="50"/>
<TextArea id="txaDescricao" caption="Descrição" type="string" width="100%" required="true" maxLength="500"/> <TextArea id="txaDescricao" caption="Descrição" type="string" width="100%" required="true" maxLength="500"/>
@@ -583,14 +625,14 @@
<onClickScript language="JavaScript"> <onClickScript language="JavaScript">
<![CDATA[ <![CDATA[
function run() { function run() {
engine.getGlobalVariable("organizeRequiredFields")("jogos", false); engine.getGlobalVariable("organizeRequiredFields")("jogos", true);
if(engine.isValid()){ if(engine.isValid()){
var config_jogos = engine.getGlobalVariable("config_jogos"); var config_jogos = engine.getGlobalVariable("config_jogos");
var lib = libService.loadScript("lib_cadastro_padrao"); var lib = libService.loadScript("lib_cadastro_padrao");
var lib_msg = libService.loadScript("messages");
var id = engine.getField("txfCodigo").getValue(); var id = engine.getField("txfCodigo").getValue();
var retorno = lib.fncGravarRegistro(config_jogos, id); var retorno = lib.fncGravarRegistro(config_jogos, id);
if (retorno) { if (retorno) {
var lib_msg = libService.loadScript("messages");
engine.getField("dbtJogos").refresh(); engine.getField("dbtJogos").refresh();
engine.getGlobalVariable("resetPanelGames")(); engine.getGlobalVariable("resetPanelGames")();
engine.getGlobalVariable("changeCrudPanel")("listaJogos"); engine.getGlobalVariable("changeCrudPanel")("listaJogos");
@@ -600,7 +642,14 @@
msg: "O jogo foi gravado com sucesso!", msg: "O jogo foi gravado com sucesso!",
position: lib_msg.notificationPosition.bottom_right, position: lib_msg.notificationPosition.bottom_right,
}); });
} } else {
lib_msg.showNotification({
type: lib_msg.notificationType.tray,
caption: "Erro!",
msg: "Não foi possível gravar o jogo.",
position: lib_msg.notificationPosition.bottom_right,
});
}
} }
} }
]]> ]]>
+68 -3
View File
@@ -5,13 +5,78 @@
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd
http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd"> http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
<changeSet author="nome.usuario" id="id_unico_changeset">
<changeSet author="matheus.medeiros" id="matheus.medeiros-1">
<preConditions onError="WARN" onFail="MARK_RAN" onSqlOutput="IGNORE"> <preConditions onError="WARN" onFail="MARK_RAN" onSqlOutput="IGNORE">
<not> <not>
<tableExists tableName="go_setor" /> <tableExists tableName="TB_MATHEUS_MEDEIROS_JOGOS" />
</not> </not>
</preConditions> </preConditions>
<sql endDelimiter=";" splitStatements="true" stripComments="false">CREATE TABLE tabela ()</sql>
<sql endDelimiter=";" splitStatements="true" stripComments="false">CREATE TABLE TB_MATHEUS_MEDEIROS_JOGOS (
CODIGO NUMBER(10) NOT NULL,
TITULO VARCHAR2(150) NOT NULL,
GENERO VARCHAR2(30) NOT NULL,
ANO_LANCAMENTO NUMBER(4) NOT NULL,
PRODUTORA VARCHAR2(50) NOT NULL,
DESCRICAO VARCHAR2(500) NOT NULL,
CONSTRAINT PK_MM_JOGOS PRIMARY KEY (CODIGO),
CONSTRAINT CK_MM_JOGOS_ANO
CHECK (ANO_LANCAMENTO BETWEEN 1970 AND EXTRACT(YEAR FROM SYSDATE)),
CHECK (TITULO BETWEEN 3 AND 100)
);
</sql>
</changeSet>
<changeSet author="matheus.medeiros" id="matheus.medeiros-2">
<preConditions onError="WARN" onFail="MARK_RAN" onSqlOutput="IGNORE">
<not>
<sequenceExists sequenceName="TB_MATHEUS_MEDEIROS_JOGOS_SEQ" />
</not>
</preConditions>
<sql endDelimiter=";" splitStatements="true" stripComments="false">
CREATE SEQUENCE TB_MATHEUS_MEDEIROS_JOGOS_SEQ
START WITH 1 INCREMENT BY 1 NOCACHE NOCYCLE;
</sql>
</changeSet> </changeSet>
<changeSet author="matheus.medeiros" id="matheus.medeiros-4">
<preConditions onError="WARN" onFail="MARK_RAN" onSqlOutput="IGNORE">
<not>
<tableExists tableName="TB_MATHEUS_MEDEIROS_AVALIACOES" />
</not>
</preConditions>
<sql endDelimiter=";" splitStatements="true" stripComments="false">
CREATE TABLE TB_MATHEUS_MEDEIROS_AVALIACOES (
CODIGO NUMBER(10) NOT NULL,
NOME VARCHAR2(100) NOT NULL,
EMAIL VARCHAR2(150) NOT NULL,
COMENTARIO VARCHAR2(1000) NOT NULL,
NOTA NUMBER(4,2) NOT NULL,
DATA_AVALIACAO DATE NOT NULL,
ID_JOGO NUMBER(10) NOT NULL,
CONSTRAINT PK_MM_AVALIACOES PRIMARY KEY (CODIGO),
CONSTRAINT FK_MM_AVAL_JOGO
FOREIGN KEY (ID_JOGO)
REFERENCES TB_MATHEUS_MEDEIROS_JOGOS (CODIGO),
CONSTRAINT CK_MM_AVAL_NOTA
CHECK (NOTA BETWEEN 0 AND 10)
);</sql>
</changeSet>
<changeSet author="matheus.medeiros" id="matheus.medeiros-3">
<preConditions onError="WARN" onFail="MARK_RAN" onSqlOutput="IGNORE">
<not>
<sequenceExists sequenceName="TB_MATHEUS_MEDEIROS_AVALIACOES_SEQ" />
</not>
</preConditions>
<sql endDelimiter=";" splitStatements="true" stripComments="false">
CREATE SEQUENCE TB_MATHEUS_MEDEIROS_AVALIACOES_SEQ
START WITH 1 INCREMENT BY 1 NOCACHE NOCYCLE;
</sql>
</changeSet>
</databaseChangeLog> </databaseChangeLog>