SIGESA: Maestro detalle

  • Aquí vamos a explicar como crear un maestro detalle don de maestro es POAI y productoPOAI es un detalle
  • En BD
  • Actualmente el maestro POAI es esta en funcionamiento solo le agregamos su hijo

Domain: ProductoPOAI

/*
 * Copyright (c) 2022.
 *
 * Centro de Gestion Informatica
 * Direccion de Tecnologias de la Informacion y Comunicacion
 * Universidad Nacional - Costa Rica
 * http://www.una.ac.cr
 *
 */
package cr.ac.una.cgi.sigesa.ppi.ppo.domain;

import java.util.List;

import javax.persistence.AttributeOverride;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import cr.ac.una.cgi.sdkuna.domain.CampoConfigurable;
import cr.ac.una.cgi.sdkuna.domain.Usuario;
import cr.ac.una.cgi.sdkuna.generic.BaseEntity;
import cr.ac.una.cgi.sigesa.epf.cpr.domain.ProgramaPresupuestario;

/**
 * Entity para la administración de la entidad {@link ProductoPOAI}
 *
 * @author Gustavo Matamoros González´
 * @version 0.0.1
 * @since 13/05/2024
 */
@Entity
@Table(name = "PRODUCTO_POAI")
@AttributeOverride(name = "id", column
        = @Column(name = "ID_PRODUCTO_POAI"))
@SequenceGenerator(name = "sequence", sequenceName = "SQ_PRODUCTO_POAI", allocationSize = 1)
public class ProductoPOAI extends BaseEntity<Usuario, CampoConfigurable> {

    public ProductoPOAI() {
    }

    @ManyToOne
    @JoinColumn(name = "PLAN_OPERATIVO_ANUAL_INST")
    private PlanOperativoAnualInstitucional planOperativoAnualInstitucional;

    @ManyToOne
    @JoinColumn(name = "PROGRAMA_PRESUPUESTARIO")
    private ProgramaPresupuestario programaPresupuestario;
    
    @Column(name = "CODIGO")
    private Integer codigo;
    
    @Column(name = "DESCRIPCION")
    private String descripcion;  
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "PRODUCTO_POAI_ORIGEN")
    private ProductoPOAI productoPOAIOrigen; 
    
    public PlanOperativoAnualInstitucional getPlanOperativoAnualInstitucional() {
        return planOperativoAnualInstitucional;
    }

    public void setPlanOperativoAnualInstitucional(PlanOperativoAnualInstitucional planOperativoAnualInstitucional) {
        this.planOperativoAnualInstitucional = planOperativoAnualInstitucional;
    }

    public ProgramaPresupuestario getProgramaPresupuestario() {
        return programaPresupuestario;
    }

    public void setProgramaPresupuestario(ProgramaPresupuestario programaPresupuestario) {
        this.programaPresupuestario = programaPresupuestario;
    }

    public Integer getCodigo() {
        return codigo;
    }

    public void setCodigo(Integer codigo) {
        this.codigo = codigo;
    }

    public String getDescripcion() {
        return descripcion;
    }

    public void setDescripcion(String descripcion) {
        this.descripcion = descripcion;
    }

    public ProductoPOAI getProductoPOAIOrigen() {
        return productoPOAIOrigen;
    }

    public void setProductoPOAIOrigen(ProductoPOAI productoPOAIOrigen) {
        this.productoPOAIOrigen = productoPOAIOrigen;
    }

}

Repository: ProductoPOAIRepository

/*
 * Copyright (c) 2022.
 *
 * Centro de Gestion Informatica
 * Direccion de Tecnologias de la Informacion y Comunicacion
 * Universidad Nacional - Costa Rica
 * http://www.una.ac.cr
 *
 */
package cr.ac.una.cgi.sigesa.ppi.ppo.repository;

import org.springframework.stereotype.Repository;
import cr.ac.una.cgi.sdkuna.generic.GenericRepository;
import cr.ac.una.cgi.sigesa.ppi.ppo.domain.ProductoPOAI;

/**
 * Repository para la administración de la entidad {@link ProductoPOAI}
 *
 * @author Gustavo Matamoros González
 * @version 0.0.1
 * @since 13/05/2024
 */
@Repository
public interface ProductoPOAIRepository extends GenericRepository<ProductoPOAI> {

}

Service: ProductoService

/*
 * Copyright (c) 2022.
 *
 * Centro de Gestion Informatica
 * Direccion de Tecnologias de la Informacion y Comunicacion
 * Universidad Nacional - Costa Rica
 * http://www.una.ac.cr
 *
 */
package cr.ac.una.cgi.sigesa.ppi.ppo.service;

import java.util.List;

import cr.ac.una.cgi.sdkuna.api.service.EntityService;
import cr.ac.una.cgi.sigesa.ppi.ppo.domain.ProductoPOAI;

/**
 * Interface para la administración de la entidad {@link ProductoPOAI}
 *
 * @author Gustavo Matamoros González
 * @version 0.0.1
 * @since 13/05/2024
 */
public interface ProductoPOAIService extends EntityService<ProductoPOAI> {
    public List<ProductoPOAI> ordenaProductoPOAIByCodigo(List<ProductoPOAI> listaProductoPOAI);
}

ServiceImpl: ProductoServiceImpl

/*
 * Copyright (c) 2022.
 *
 * Centro de Gestion Informatica
 * Direccion de Tecnologias de la Informacion y Comunicacion
 * Universidad Nacional - Costa Rica
 * http://www.una.ac.cr
 *
 */
package cr.ac.una.cgi.sigesa.ppi.ppo.service;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import cr.ac.una.cgi.sdkuna.api.service.EntityServiceImpl;
import cr.ac.una.cgi.sigesa.ppi.ppo.domain.ProductoPOAI;
import cr.ac.una.cgi.sigesa.ppi.ppo.repository.ProductoPOAIRepository;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * Clase que implementa el servicio {@link ProductoPOAIService} para la entidad
 * {@link ProductoPOAI}
 *
 * @author Gustavo Matamoros González
 * @version 0.0.1
 * @since 13/05/2024
 */
@Service
@Transactional
public class ProductoPOAIServiceImpl extends EntityServiceImpl<ProductoPOAI, ProductoPOAIRepository> implements ProductoPOAIService {

    @Override
    public List<ProductoPOAI> ordenaProductoPOAIByCodigo(List<ProductoPOAI> listaProductoPOAI) {
        Collections.sort(listaProductoPOAI, new Comparator<ProductoPOAI>() {

            @Override
            public int compare(ProductoPOAI op1, ProductoPOAI op2) {
                return op1.getCodigo().compareTo(op2.getCodigo());
            }
        });
        return listaProductoPOAI;
    }
}

Bean ASER: ProductoPOAIBean

  • Es de tipo ASER por que es un hijo y no un CRUD
/*
 * Copyright (C) 2021.
 *
 * Centro de Gestion Informatica
 * Direccion de Tecnologias de la Informacion y Comunicacion
 * Universidad Nacional - Costa Rica
 * http://www.una.ac.cr
 * 
 */
package cr.ac.una.cgi.sigesa.ppi.ppo.view.model;

import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import cr.ac.una.cgi.sdkuna.view.commons.ASER;
import cr.ac.una.cgi.sdkuna.view.commons.ASERColumn;
import cr.ac.una.cgi.sdkuna.view.commons.ASERImpl;
import cr.ac.una.cgi.sigesa.ppi.ppo.domain.ProductoPOAI;

/**
 * Spring Bean Session para la administración de la entidad {@link ProductoPOAI}
 *
 * @author Gustavo Matamoros González
 * @version 0.0.1
 * @since 13/05/2024
 */
@Component
@Scope("session")
public class ProductoPOAIBean extends ASERImpl<ProductoPOAI> implements ASER {

    public ProductoPOAIBean() {
    }

    @PostConstruct
    public void init() {

        List<ASERColumn> columns = new ArrayList<>();
        
        
        columns.add(new ASERColumn("codigo", getI18n("productoPOAI_codigo_label"), true));
        columns.add(new ASERColumn("descripcion", getI18n("productoPOAI_descripcion_label"), true));

        this.setColumnsDetails(columns);
    }

    public void initProperties() {

        if (!isPostBack()) {

        }
    }
}

Crear relación maestro detalle

  • Lo primero que debemos hacer es crear una lista de los hijos dentro del domain del maestro

Domain: POAI

# Creamos la lista
@OneToMany(fetch = FetchType.LAZY, mappedBy = "planOperativoAnualInstitucional")
    private List<ProductoPOAI> listaProductosPOAI;

# GET y SET
public List<ProductoPOAI> getListaProductosPOAI() {
        return listaProductosPOAI;
    }

    public void setListaProductosPOAI(List<ProductoPOAI> listaProductosPOAI) {
        this.listaProductosPOAI = listaProductosPOAI;
    }
  • Donde mappedBy = «planOperativoAnualInstitucional» es el nombre de campo donde productoPOAI relaciona el POAI
  • En la clase
  • Ahora los productos tienen que venir ordenados por código, por eso en el service de Porducto esta esta función que ordena
public List<ProductoPOAI> ordenaProductoPOAIByCodigo(List<ProductoPOAI> listaProductoPOAI);

Service Maestro: POAI

  • Agregamos el metodo que ordena
# import
import cr.ac.una.cgi.sigesa.ppi.ppo.domain.ProductoPOAI;

/**
         * Retorna una lista de Produtos POAI Ordenados
         * 
         * @author Gustavo Matamoros González
         * @issue PPI-500 
         * @since 14/05/2024
         * @param listaProductoPOAI
         */
        public List<ProductoPOAI> ordenaProductoPOAIByCodigo(List<ProductoPOAI> listaProductoPOAI);

ServiceImpl: POAI

  • Creamos el metodo
# import
import cr.ac.una.cgi.sigesa.ppi.ppo.domain.ProductoPOAI;

# Autowired
@Autowired
    ProductoPOAIService productoPOAIService;

# metodo
@Override
    public List<ProductoPOAI> ordenaProductoPOAIByCodigo(List<ProductoPOAI> listaProductoPOAI){
            return productoPOAIService.ordenaProductoPOAIByCodigo(listaProductoPOAI);
    }

Bean: POAI

  • Ahora hacemos los cambios necesarios para que POAI cargue los ProductosPOAI
#import
import cr.ac.una.cgi.sigesa.ppi.ppo.domain.ProductoPOAI;

# autowired del bean
@Autowired
    ProductoPOAIBean productoPOAIBean;

# listas para obtener los Productos y filtrarlo
 private List<ProductoPOAI> productoPOAIList = new ArrayList<>();
    private List<ProductoPOAI> productoPOAIFilteredList = new ArrayList<>();

  • # initProperties() : indicamos que si es nuevo el POAI cree una lista vacia de productos
this.getEntity().setListaProductosPOAI(new ArrayList());
  • Asi
public void initProperties() {
        if (!isPostBack()) {
   
            
            if (this.getEntity().getId() != null) {
             
            } else {
                this.getEntity().setListaObjetivosPOAI(new ArrayList());
                this.getEntity().setListaProductosPOAI(new ArrayList());
            }
                     
        }

    }
  • Ahora en initDetails mandamos a cargar la lista con los datos de la entidad y inicializamos el bean
// Cargar Productos
            this.getEntity().setListaProductosPOAI(productoPOAIBean.setDetails(this.getEntity().getListaProductosPOAI()));            
            this.productoPOAIList.addAll(this.getEntity().getListaProductosPOAI());          
            productoPOAIBean.init();
  • ASí
public void initDetails() {
        if (!isPostBack()) {
            

            // Cargar Productos
            this.getEntity().setListaProductosPOAI(productoPOAIBean.setDetails(this.getEntity().getListaProductosPOAI()));            
            this.productoPOAIList.addAll(this.getEntity().getListaProductosPOAI());          
            productoPOAIBean.init();
            
            
        }
       
    }
  • Ahora por la forma que esta programado donde el usuario puede cambiar de programa presupuestario
  • Debemos crear un metodo que actualice la lista para el evento onChange
  • Creamos el metodo
public void actualizaProgramaPresupuestarioProductoFiltro() {

        this.productoPOAIFilteredList.clear();
        this.getEntity().getListaProductosPOAI().clear();

        for (ProductoPOAI producto : this.productoPOAIList) {
            if (producto.getProgramaPresupuestario().getId().equals(this.getProgramaPresupuestario().getId())) {
                productoPOAIFilteredList.add(producto);
            }
        }

        this.getEntity().setListaProductosPOAI(productoPOAIBean.setDetails(service.ordenaProductoPOAIByCodigo(productoPOAIFilteredList)));            
        productoPOAIBean.init();
        
    }
  • Ahora modificamos el EditForm para agregar el tab del Hijo (Producto)
  • Tenemos este tabView
<p:tabView id="planOperativoAnualInstitucionalTabView">
                <p:ajax event="tabChange" process="@this" />
  • Y le agregamos el tab nuevo del hijo
<!-- TAB: PRODUCTOS-->
                <p:tab title="#{i18n.planOperativoAnualInstitucionalBean_productos_tab}">
                    <p:panelGrid columns="1" styleClass="una-panelgrid una-width-100">

                        <p:outputPanel id="programasPresupuestariosProductosOutputPanel">
                            <p:selectOneRadio value="#{planOperativoAnualInstitucionalBean.programaPresupuestario}"
                                disabled="#{false}" id="selectOneProgramaPresupuestarioProducto"
                                onchange="#{planOperativoAnualInstitucionalBean.actualizaProgramaPresupuestarioProductoFiltro()}"
                                converter="#{programaPresupuestarioBean.converter}">
                                <f:selectItems
                                    value="#{planOperativoAnualInstitucionalBean.getListaProgramasPresupuestarios()}"
                                    var="prg" itemLabel="#{prg.nombre}" itemValue="#{prg}" />
                                <p:ajax process="@this" 
                                    update="@this, :formMantenimiento:planOperativoAnualInstitucionalTabView:productosPOAINoEditTable:dataTable" />
                            </p:selectOneRadio>

                        </p:outputPanel>

                        <p:outputPanel id="productosPOAIOutputPanel">
                            <components:detailNoEditTableHorizontal id="productosPOAINoEditTable"
                                                            bean="#{productoPOAIBean}"
                                                            masterBean="#{planOperativoAnualInstitucionalBean}"
                                                            container="planOperativoAnualInstitucionalTabView:"
                                                            showNewButton="#{true}"
                                                            editForm="productoEditForm"                                                            
                                                            header="#{i18n.planOperativoAnualInstitucional_productos_lista_label}" 
                                                            showDeleteButton ="#{true}"/>

                        </p:outputPanel>

                    </p:panelGrid>
                </p:tab>