DepartamentoProdutoForm editar arquivo

0:00 / 0:00

Arquivo central da sequência UPDATE. O DepartamentoProdutoForm que já tinha 3 inner classes (ShowInsert, Insert, Cancelar) ganha mais 2: ShowUpdate (carregar registro e abrir form preenchido) e Update (gravar alterações com transação). O br() também é atualizado pra mostrar o botão Salvar certo em cada modo.

CÓDIGO COMPLETO
package br.xt.app.departamento.produto;

import br.jasap.core.Effect;
import br.jasap.effect.Response;
import br.jasap.gui.Bar;
import br.jasap.gui.Button;
import br.jasap.gui.JasapPage;
import br.jasap.gui.Table;
import br.jasap.gui.form.Form;
import br.jasap.gui.form.Text;
import br.jasap.gui.form.Textarea;
import br.jasap.util.Js;
import br.jasap.util.filters.TransactionFilter;
import br.xt.acore.view.XtPage;

public class DepartamentoProdutoForm extends DepartamentoProdutoAction {

    @Override
    public Effect execute() throws Exception {
        render();
        return new Response();
    }

    public static class ShowInsert extends DepartamentoProdutoForm {
        @Override
        public Effect execute() throws Exception {
            setInsert(FORM);
            getSession().remove(ROOT.concat(DepartamentoProdutoBean.ID_PRODUTO));
            render();
            return new Response();
        }
    }

    public static class Insert extends DepartamentoProdutoAction {
        public Insert() { super.getFilters().add(new TransactionFilter()); }
        @Override
        public Effect execute() throws Exception {
            getFactory().departamento().proModel().insert(proBean());
            evalParent(Js.CLOSE_SUB_WINDOWS);
            return new Response();
        }
    }

    // ADICIONAR
    public static class ShowUpdate extends DepartamentoProdutoForm {
        @Override
        public Effect execute() throws Exception {
            setUpdate(FORM);
            proBean().setId_produto(getInput().getInteger(DepartamentoProdutoBean.ID_PRODUTO));
            getSession().addInt(ROOT.concat(DepartamentoProdutoBean.ID_PRODUTO), proBean().getId_produto());
            getFactory().departamento().proModel().daoSingle(proBean());
            render();
            return new Response();
        }
    }

    public static class Update extends DepartamentoProdutoAction {
        public Update() { super.getFilters().add(new TransactionFilter()); }
        @Override
        public Effect execute() throws Exception {
            proBean().setId_produto(id_produto());
            getFactory().departamento().proModel().update(proBean());
            evalParent(Js.CLOSE_SUB_WINDOWS);
            return new Response();
        }
    }
    // FIM

    public static class Cancelar extends DepartamentoProdutoForm {
        @Override
        public Effect execute() throws Exception {
            evalParent(Js.CLOSE_SUB_WINDOWS);
            return new Response();
        }
    }

    public void render() throws Exception {
        // ... (sem alteração — mesmo código da sequência CREATE)
        XtPage page = new XtPage(getManager());
        if (isAjaxCall()) {
            update(JasapPage.DIV_WINDOW, page.content(window().toHtml()));
            eval(Js.CLOSE_SUB_WINDOWS);
        } else {
            page.getTable().setBorder(4).rowC("100%")
                    .setContent(page.content(window().toHtml()))
                    .setStyle(ui().modalBorder());
            page.setWinTitle("Produto");
            getOutput().write(this, page);
        }
    }

    public Table window() throws Exception {
        // ... (sem alteração)
        Table w = new Table(getManager()).setSize("100%", "100%");
        w.rowC("1%",  JasapPage.DIV_TITLE, ui().title("CADASTRO DE PRODUTO"));
        w.rowC("1%",  null, ui().line());
        w.rowC("auto").setId(JasapPage.DIV_MASTER).setContent(form()).table();
        w.rowC("1%",  null, ui().line());
        w.rowC("1%",  JasapPage.DIV_BOTTOM, br());
        return w;
    }

    // ADICIONAR
    protected Bar br() throws Exception {
        Button salvarInsert = ui().button("  Salvar  ")
                .setCss("btn btn-success btn-lg").setNoSize()
                .setOnClick(submit(Insert.class).validate().toHtml())
                .setVisible(isInsert(FORM));

        Button salvarUpdate = ui().button("  Salvar  ")
                .setCss("btn btn-success btn-lg").setNoSize()
                .setOnClick(submit(Update.class).validate().toHtml())
                .setVisible(isUpdate(FORM));

        Button cancelar = ui().button("  Cancelar  ")
                .setCss("btn btn-primary btn-lg").setNoSize()
                .setOnClick(link(Cancelar.class).ajax());

        Bar bar = ui().bar();
        bar.addRight(cancelar);
        bar.addRight(" ");
        bar.addRight(salvarInsert);
        bar.addRight(salvarUpdate);
        return bar;
    }
    // FIM

    public String form() throws Exception {
        // ... (sem alteração)
        Form frm = ui().form();
        frm.addHidden(DepartamentoProdutoBean.ID_PRODUTO, proBean().getId_produto());

        frm.line().add(nome_produto(), "150");
        frm.line().add(vl_produto(),   "150");
        frm.line().add(qtd_produto(),  "150");
        frm.line().add(obs_produto(),  "150");

        return frm.getTable().toHtml();
    }

    // ... campos nome_produto, vl_produto, qtd_produto, obs_produto (sem alteração)

    public static String FORM = ROOT.concat("__FORM");

}

Mudanças nesta sequência: 2 inner classes novas (ShowUpdate, Update) e br() reescrito com 3 botões. Nenhum import novo. Os campos, o render(), o window(), o form() e as inner classes do CREATE permanecem iguais.

ShowUpdate — carregar registro e abrir preenchido

Executada quando o usuário clica numa linha da lista. Faz quatro coisas antes de montar a tela:

setUpdate(FORM);
proBean().setId_produto(getInput().getInteger(DepartamentoProdutoBean.ID_PRODUTO));
getSession().addInt(ROOT.concat(DepartamentoProdutoBean.ID_PRODUTO), proBean().getId_produto());
getFactory().departamento().proModel().daoSingle(proBean());
  1. setUpdate(FORM) — liga a flag "modo edição" na sessão. É essa flag que o isUpdate(FORM) verifica pra decidir quais botões mostrar (Salvar update). Contraparte do setInsert(FORM) do ShowInsert.
  2. getInput().getInteger(...) — lê o ID do produto que veio no request (passado pelo setOnclick da lista).
  3. getSession().addInt(...) — guarda esse ID na sessão pra uso futuro. Sem isso, o Update não saberia qual registro operar (ele não recebe o ID no request — lê da sessão via id_produto()).
  4. daoSingle(proBean()) — carrega todos os dados do registro do banco e preenche o Bean. Quando o render() montar os campos, cada setValue(proBean().getNome_produto()) já terá o valor real.

Comparação com ShowInsert: o ShowInsert limpa a sessão (remove) e deixa o Bean vazio. O ShowUpdate grava na sessão (addInt) e preenche o Bean com dados do banco. Resultado: o mesmo form, mas com campos preenchidos em vez de vazios.

Herda de DepartamentoProdutoForm — por isso tem acesso a render(), window(), form(), br(), e todos os campos. Mesma lógica do ShowInsert.

Update — gravar alterações com transação

Executada quando o usuário clica "Salvar" no modo edição. Estrutura idêntica ao Insert, com uma diferença crucial:

proBean().setId_produto(id_produto());
getFactory().departamento().proModel().update(proBean());
evalParent(Js.CLOSE_SUB_WINDOWS);

proBean().setId_produto(id_produto()) — o proBean() vem preenchido com os dados do formulário (via getInstance), MAS o id_produto chega como null pelo hidden field em alguns browsers. Pra garantir, seta explicitamente o ID lido da sessão.

Sem essa linha, o update().execute geraria um UPDATE ... WHERE id_produto = null — que não afetaria nenhuma linha. O registro ficaria inalterado sem nenhum erro visível. É um risco silencioso clássico do framework.

TransactionFilter — mesmo mecanismo do Insert. Envolve o execute() numa transação: sucesso → COMMIT, exception → ROLLBACK.

Herda de DepartamentoProdutoAction (não de Form) — mesmo padrão do Insert. Não precisa de render() nem de campos, só do proBean() e da conexão com o banco.

br() — barra de botões atualizada

O br() original (do CREATE) tinha 2 botões. Agora tem 3:

BotãoVisível quandoPosiçãoAção
Salvar (insert)isInsert(FORM)Direitasubmit(Insert.class).validate()
Salvar (update)isUpdate(FORM)Direitasubmit(Update.class).validate()
CancelarSempreDireitalink(Cancelar.class)

No modo inserção, o usuário vê: Cancelar + Salvar (à direita). No modo edição, vê: Cancelar + Salvar (à direita). Visualmente igual — mas por trás, o Salvar aponta pra actions diferentes (Insert vs Update).

Por que dois botões Salvar separados? Porque cada um aponta pra uma action diferente (Insert vs Update). O setVisible garante que só um aparece por vez — nunca os dois ao mesmo tempo.

Fluxo do usuário — editar um produto

O ciclo completo de editar um produto envolve 3 requests (3 agentes distintos):

  1. Clique na linha da lista → request chega → agente vai pro setor ShowUpdate → seta modo edição, guarda ID na sessão, carrega dados do banco → monta o form preenchido → modal abre com campos já preenchidos
  2. Usuário altera dados e clica "Salvar" → request chega com os dados alterados → agente vai pro setor UpdateTransactionFilter abre transação → seta ID da sessão no Bean → model.update(bean) grava → transação fecha → modal fecha
  3. Modal fechasetOnCloseURL dispara refresh → lista atualiza com dados novos

Cada um desses requests é um agente novo, cartão novo, tudo do zero. O encadeamento lógico vive no código (ShowUpdate carrega, Update grava, List atualiza), não na memória de nenhum agente.

O que o Form NÃO tem nesta sequência

O Form agora tem INSERT e UPDATE completos — mas ainda é a versão mínima. Funcionalidades que virão em episódios futuros:

  • Delete pelo formulário — botão Excluir com confirmação (episódio próprio)
  • insert_chk — checkbox "Continuar inserindo" (episódio próprio)
  • Quick Search / Sort / Tabs / Paginação — na List (episódios próprios)
  • Detail — lista filha dentro do form (episódio próprio)
  • LinkBox — seleção de FK com modal de busca (episódio próprio)

Cada feature ganha seu próprio episódio com foco pedagógico claro. O CRUD completo (READ + DELETE + CREATE + UPDATE) está pronto na versão básica.