diff --git a/pom.xml b/pom.xml
index c01ae2fdc..83ac60dea 100644
--- a/pom.xml
+++ b/pom.xml
@@ -212,7 +212,18 @@
nimbus-jose-jwt
jdk16
4.11.2
-
+
+
+ br.com.rjconsultores
+ Auditador
+ 0.0.1-SNAPSHOT
+
+
+ commons-lang
+ commons-lang
+
+
+
${project.artifactId}
@@ -243,6 +254,7 @@
@{artifactId}@.@{extension}@
+
diff --git a/src/java/com/rjconsultores/Teste.java b/src/java/com/rjconsultores/Teste.java
new file mode 100644
index 000000000..95894e1d1
--- /dev/null
+++ b/src/java/com/rjconsultores/Teste.java
@@ -0,0 +1,45 @@
+package com.rjconsultores;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Map;
+
+import com.rjconsultores.ventaboletos.entidad.Tarifa;
+
+import br.com.rjconsultores.auditador.annotations.AuditarClasse;
+
+public class Teste {
+
+ public static void main(String[] args) {
+ try {
+ Tarifa tarifa = new Tarifa();
+ AuditarClasse classe = tarifa.getClass().getAnnotation(AuditarClasse.class);
+ Object obj = Proxy.getInvocationHandler(classe);
+ System.out.println(classe.tela());
+ Field campo = obj.getClass().getDeclaredField("memberValues");
+ if(campo != null ) {
+ campo.setAccessible(true);
+ }
+ Map memberValues = (Map) campo.get(obj);
+ Object tela = memberValues.get("tela");
+ if(tela != null) {
+ memberValues.put("tela", "Teste2");
+ }
+ System.out.println(classe.tela());
+
+// for (Method metodo : classe.getClass().getDeclaredField("memberValues")) {
+// metodo.setAccessible(true);
+// if(metodo.getName().equals("tela")) {
+// metodo.invoke(classe);
+// break;
+// }
+// }
+// classe = tarifa.getClass().getAnnotation(AuditarClasse.class);
+// System.out.println(classe.tela());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/src/java/com/rjconsultores/ventaboletos/web/gui/controladores/esquemaoperacional/EditarCorridaAsientoController.java b/src/java/com/rjconsultores/ventaboletos/web/gui/controladores/esquemaoperacional/EditarCorridaAsientoController.java
index 8dda9d2b4..f87771405 100644
--- a/src/java/com/rjconsultores/ventaboletos/web/gui/controladores/esquemaoperacional/EditarCorridaAsientoController.java
+++ b/src/java/com/rjconsultores/ventaboletos/web/gui/controladores/esquemaoperacional/EditarCorridaAsientoController.java
@@ -424,6 +424,10 @@ public class EditarCorridaAsientoController extends MyGenericForwardComposer {
esquemaAsientoService.borrar(esquemaAsientoBusqueda);
lsAsientos.add(esquemaAsientoBusqueda);
+
+ if(esquemaCorrida.getEsquemaAsientoList().indexOf(esquemaAsientoBusqueda) != -1) {
+ esquemaCorrida.getEsquemaAsientoList().set(esquemaCorrida.getEsquemaAsientoList().indexOf(esquemaAsientoBusqueda), esquemaAsientoBusqueda);
+ }
}
}
diff --git a/src/java/com/rjconsultores/ventaboletos/web/gui/controladores/seguridad/BusquedaLogAuditoriaController.java b/src/java/com/rjconsultores/ventaboletos/web/gui/controladores/seguridad/BusquedaLogAuditoriaController.java
new file mode 100644
index 000000000..307c56694
--- /dev/null
+++ b/src/java/com/rjconsultores/ventaboletos/web/gui/controladores/seguridad/BusquedaLogAuditoriaController.java
@@ -0,0 +1,162 @@
+package com.rjconsultores.ventaboletos.web.gui.controladores.seguridad;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Controller;
+import org.zkoss.util.resource.Labels;
+import org.zkoss.zhtml.Messagebox;
+import org.zkoss.zk.ui.Component;
+import org.zkoss.zk.ui.event.Event;
+import org.zkoss.zul.Datebox;
+import org.zkoss.zul.Longbox;
+import org.zkoss.zul.Paging;
+
+import com.rjconsultores.ventaboletos.entidad.Empresa;
+import com.rjconsultores.ventaboletos.entidad.LogAuditoria;
+import com.rjconsultores.ventaboletos.service.LogAuditoriaService;
+import com.rjconsultores.ventaboletos.utilerias.DateUtil;
+import com.rjconsultores.ventaboletos.utilerias.UsuarioLogado;
+import com.rjconsultores.ventaboletos.web.utilerias.MyComboboxEstandar;
+import com.rjconsultores.ventaboletos.web.utilerias.MyGenericForwardComposer;
+import com.rjconsultores.ventaboletos.web.utilerias.MyListbox;
+import com.rjconsultores.ventaboletos.web.utilerias.MyTextbox;
+import com.rjconsultores.ventaboletos.web.utilerias.paginacion.HibernateSearchObject;
+import com.rjconsultores.ventaboletos.web.utilerias.paginacion.PagedListWrapper;
+import com.rjconsultores.ventaboletos.web.utilerias.render.RenderLogAuditoria;
+import com.trg.search.Filter;
+
+import br.com.rjconsultores.auditador.enums.AuditadorTipoAlteracao;
+
+@Controller("busquedaLogAuditoriaController")
+@Scope("prototype")
+public class BusquedaLogAuditoriaController extends MyGenericForwardComposer {
+
+ private static final long serialVersionUID = 1L;
+ private static Logger log = Logger.getLogger(BusquedaLogAuditoriaController.class);
+
+ @Autowired
+ private LogAuditoriaService logAuditoriaService;
+
+ @Autowired
+ private transient PagedListWrapper plwLogAuditoria;
+
+ private MyListbox logAuditoriaList;
+ private Paging pagingLogAuditoria;
+
+ private List lsEmpresa;
+ private List lsTela;
+
+ private MyComboboxEstandar cmbEmpresa;
+ private MyComboboxEstandar cmbTela;
+ private MyComboboxEstandar cmbTipoAlteracao;
+
+ private Datebox dtInicio;
+ private Datebox dtFim;
+
+ private MyTextbox txtCampoAlterado;
+ private MyTextbox txtCveUsuario;
+ private MyTextbox txtValorNovo;
+ private MyTextbox txtValorAnterior;
+ private Longbox txtIdAuditado;
+
+ @Override
+ public void doAfterCompose(Component comp) throws Exception {
+ lsEmpresa = new ArrayList();
+ lsEmpresa.add(new Empresa(-1, "TODAS"));
+ lsEmpresa.addAll(UsuarioLogado.getUsuarioLogado().getEmpresa());
+ lsTela = logAuditoriaService.listarTodasAsTelas();
+ super.doAfterCompose(comp);
+
+ logAuditoriaList.setItemRenderer(new RenderLogAuditoria());
+ }
+
+ public List getLsEmpresa() {
+ return lsEmpresa;
+ }
+
+ private void refreshLista() {
+ HibernateSearchObject sistemaBusqueda = new HibernateSearchObject(LogAuditoria.class, pagingLogAuditoria.getPageSize());
+
+ Date dataInicio = dtInicio.getValue();
+ Date dataFim = dtFim.getValue();
+
+ sistemaBusqueda.addFilterGreaterOrEqual("fecmodif", DateUtil.inicioFecha(dataInicio));
+ sistemaBusqueda.addFilterLessOrEqual("fecmodif", DateUtil.fimFecha(dataFim));
+
+ String campoAlterado = txtCampoAlterado.getText();
+ if (StringUtils.isNotBlank(campoAlterado)) {
+ sistemaBusqueda.addFilterLike("campoAlterado", "%" + campoAlterado.trim().concat("%"));
+ }
+
+ String valorNovo = txtValorNovo.getText();
+ if (StringUtils.isNotBlank(valorNovo)) {
+ sistemaBusqueda.addFilterLike("valorNovo", "%" + valorNovo.trim().concat("%"));
+ }
+
+ String valorAnterior = txtValorAnterior.getText();
+ if (StringUtils.isNotBlank(valorAnterior)) {
+ sistemaBusqueda.addFilterLike("valorAnterior", "%" + valorAnterior.trim().concat("%"));
+ }
+
+ Long idAuditado = txtIdAuditado.getValue();
+ if (idAuditado != null) {
+ sistemaBusqueda.addFilterEqual("idAuditado", idAuditado);
+ }
+
+ String cveUsuario = txtCveUsuario.getText();
+ if (StringUtils.isNotBlank(cveUsuario)) {
+ sistemaBusqueda.addFilterLike("usuario.claveUsuario", "%" + cveUsuario.trim().concat("%"));
+ }
+
+ Empresa empresa = cmbEmpresa.getSelectedItem() != null ? (Empresa) cmbEmpresa.getSelectedItem().getValue() : null;
+ if(empresa != null && empresa.getEmpresaId() > -1) {
+ sistemaBusqueda.addFilterEqual("empresa.empresaId", empresa.getEmpresaId());
+ } else {
+ sistemaBusqueda.addFilterOr(Filter.in("empresa", lsEmpresa), Filter.isNull("empresa"));
+ }
+
+ String tela = cmbTela.getSelectedItem() != null ? cmbTela.getSelectedItem().getValue().toString() : null;
+ if(tela != null) {
+ sistemaBusqueda.addFilterEqual("tela", tela);
+ }
+
+ AuditadorTipoAlteracao tipoAlteracao = cmbTipoAlteracao.getSelectedItem() != null ? (AuditadorTipoAlteracao) cmbTipoAlteracao.getSelectedItem().getValue() : null;
+ if(tipoAlteracao != null) {
+ sistemaBusqueda.addFilterEqual("tipoAlteracao", tipoAlteracao.toString());
+ }
+
+ sistemaBusqueda.addSortAsc("fecmodif");
+ sistemaBusqueda.addFilterEqual("activo", Boolean.TRUE);
+
+ plwLogAuditoria.init(sistemaBusqueda, logAuditoriaList, pagingLogAuditoria);
+ if (logAuditoriaList.getData().length == 0) {
+ try {
+ Messagebox.show(Labels.getLabel("MSG.ningunRegistro"),
+ Labels.getLabel("busquedaLogAuditoriaController.window.title"),
+ Messagebox.OK, Messagebox.INFORMATION);
+ } catch (InterruptedException ex) {
+ log.error("", ex);
+ }
+ }
+
+ }
+
+ public void onClick$btnPesquisa(Event ev) {
+ refreshLista();
+ }
+
+ public List getTipoAlteracaoList() {
+ return AuditadorTipoAlteracao.getList();
+ }
+
+ public List getLsTela() {
+ return lsTela;
+ }
+
+}
diff --git a/src/java/com/rjconsultores/ventaboletos/web/gui/controladores/tarifas/ModificacionMasivaTarifasUploadController.java b/src/java/com/rjconsultores/ventaboletos/web/gui/controladores/tarifas/ModificacionMasivaTarifasUploadController.java
index fe6b7ca6c..7ac273eee 100644
--- a/src/java/com/rjconsultores/ventaboletos/web/gui/controladores/tarifas/ModificacionMasivaTarifasUploadController.java
+++ b/src/java/com/rjconsultores/ventaboletos/web/gui/controladores/tarifas/ModificacionMasivaTarifasUploadController.java
@@ -195,6 +195,7 @@ public class ModificacionMasivaTarifasUploadController extends MyGenericForwardC
Tarifa tarifa = tarifaService.obtenerID(idTarifa);
if (tarifa != null) {
+ alterarDescricaoTelaAuditoria(tarifa);
contador = gerarComponeneteTarifa(tarifa, row, salvarNuevos, contador, strDuplicidade, strTarifaMinima, strErrorTarifa, strMercadoCompetido);
}
}
@@ -437,6 +438,8 @@ public class ModificacionMasivaTarifasUploadController extends MyGenericForwardC
nuevaVigencia = (VigenciaTarifa) cbiVt.getValue();
Tarifa tarifaNueva= tarifaService.buscar(tarifa.getTramo(), tarifa.getMarca(), tarifa.getClaseServicio(), nuevaVigencia, tarifa.getMoneda(), tarifa.getRuta());
+ tarifaNueva.clonar();
+ alterarDescricaoTelaAuditoria(tarifaNueva);
boolean existeTarifa = tarifaNueva != null && tarifaNueva.getTarifaId() != null;
if(!existeTarifa) {
@@ -591,7 +594,7 @@ public class ModificacionMasivaTarifasUploadController extends MyGenericForwardC
strTarifaMinima = strTarifaMinima + strTmpTarifaMinima;
}
- } catch (IllegalStateException ex) {
+ } catch (Exception ex) {
String strTmpErrorTarifa = "ERROR: formato nuevo precio." + ex + "\n"
+ "Tarifa: " + tarifa.getTarifaId() + "; \n"
+ "Tramo: " + tramo.getDesctramo() + "; \n"
@@ -620,6 +623,10 @@ public class ModificacionMasivaTarifasUploadController extends MyGenericForwardC
return contador;
}
+ private void alterarDescricaoTelaAuditoria(Tarifa tarifa) {
+ tarifa.setTelaAlternativa("Modificação Massiva de Preços");
+ }
+
private boolean validarComponenteEspecifico(Row row) {
if (componentePreco.equals(EnumTarifaPedagio.TARIFA.getDescricao())){
if (row.getCell(CELL_NOVO_PRECIO) == null) {
diff --git a/src/java/com/rjconsultores/ventaboletos/web/utilerias/menu/item/seguridad/ItemMenuLogAuditoria.java b/src/java/com/rjconsultores/ventaboletos/web/utilerias/menu/item/seguridad/ItemMenuLogAuditoria.java
new file mode 100644
index 000000000..e0c2f7c6f
--- /dev/null
+++ b/src/java/com/rjconsultores/ventaboletos/web/utilerias/menu/item/seguridad/ItemMenuLogAuditoria.java
@@ -0,0 +1,26 @@
+package com.rjconsultores.ventaboletos.web.utilerias.menu.item.seguridad;
+
+import org.zkoss.util.resource.Labels;
+
+import com.rjconsultores.ventaboletos.web.utilerias.PantallaUtileria;
+import com.rjconsultores.ventaboletos.web.utilerias.menu.DefaultItemMenuSistema;
+
+public class ItemMenuLogAuditoria extends DefaultItemMenuSistema {
+
+ public ItemMenuLogAuditoria() {
+ super("indexController.mniLogAuditoria.label");
+ }
+
+ @Override
+ public String getClaveMenu() {
+ return "COM.RJCONSULTORES.ADMINISTRACION.GUI.SEGURIDAD.MENU.LOGAUDITORIA";
+ }
+
+ @Override
+ public void ejecutar() {
+ PantallaUtileria.openWindow("/gui/seguridad/busquedaLogAuditoria.zul",
+ Labels.getLabel("busquedaLogAuditoriaController.window.title"), getArgs(), desktop);
+
+ }
+
+}
diff --git a/src/java/com/rjconsultores/ventaboletos/web/utilerias/menu/menu_original.properties b/src/java/com/rjconsultores/ventaboletos/web/utilerias/menu/menu_original.properties
index 8c102ad8b..c35b4b47e 100644
--- a/src/java/com/rjconsultores/ventaboletos/web/utilerias/menu/menu_original.properties
+++ b/src/java/com/rjconsultores/ventaboletos/web/utilerias/menu/menu_original.properties
@@ -284,6 +284,7 @@ seguridad.contingencia=com.rjconsultores.ventaboletos.web.utilerias.menu.item.se
seguridad.reenvioBpe=com.rjconsultores.ventaboletos.web.utilerias.menu.item.seguridad.ItemMenuReenvioBPe
seguridad.reenvioBpe=com.rjconsultores.ventaboletos.web.utilerias.menu.item.seguridad.ItemMenuExtrairBPeXml
seguridad.limparCacheLocalidadesAPI=com.rjconsultores.ventaboletos.web.utilerias.menu.item.seguridad.ItemMenuLimparCacheLocalidadesAPI
+seguridad.logAuditoria=com.rjconsultores.ventaboletos.web.utilerias.menu.item.seguridad.ItemMenuLogAuditoria
pasajerofrecuente=com.rjconsultores.ventaboletos.web.utilerias.menu.item.pasajerofrecuente.MenuPasajeroFrecuente
pasajerofrecuente.cliente=com.rjconsultores.ventaboletos.web.utilerias.menu.item.pasajerofrecuente.ItemMenuCliente
pasajerofrecuente.importarClientes=com.rjconsultores.ventaboletos.web.utilerias.menu.item.pasajerofrecuente.ItemMenuImportarClientes
diff --git a/src/java/com/rjconsultores/ventaboletos/web/utilerias/render/RenderLogAuditoria.java b/src/java/com/rjconsultores/ventaboletos/web/utilerias/render/RenderLogAuditoria.java
new file mode 100644
index 000000000..ffed1a4aa
--- /dev/null
+++ b/src/java/com/rjconsultores/ventaboletos/web/utilerias/render/RenderLogAuditoria.java
@@ -0,0 +1,51 @@
+package com.rjconsultores.ventaboletos.web.utilerias.render;
+
+import org.zkoss.zul.Listcell;
+import org.zkoss.zul.Listitem;
+import org.zkoss.zul.ListitemRenderer;
+
+import com.rjconsultores.ventaboletos.entidad.LogAuditoria;
+import com.rjconsultores.ventaboletos.utilerias.DateUtil;
+
+public class RenderLogAuditoria implements ListitemRenderer {
+
+ public void render(Listitem lstm, Object o) throws Exception {
+ LogAuditoria logAuditoria = (LogAuditoria) o;
+
+ Listcell lc = new Listcell(DateUtil.getStringDate(logAuditoria.getFecmodif(), "dd/MM/yyyy HH:mm"));
+ lc.setParent(lstm);
+
+ lc = new Listcell(logAuditoria.getIdAuditado() != null ? logAuditoria.getIdAuditado().toString() : "");
+ lc.setParent(lstm);
+
+ lc = new Listcell(logAuditoria.getEmpresa() != null ? logAuditoria.getEmpresa().getNombempresa() : "");
+ lc.setParent(lstm);
+
+ lc = new Listcell(String.format("%s - %s", logAuditoria.getUsuario().getClaveUsuario(), logAuditoria.getUsuario().getNombusuario()));
+ lc.setParent(lstm);
+
+ lc = new Listcell(logAuditoria.getTipoAlteracao());
+ lc.setParent(lstm);
+
+ lc = new Listcell(logAuditoria.getTela());
+ lc.setParent(lstm);
+
+ lc = new Listcell(logAuditoria.getCampoAlterado());
+ lc.setParent(lstm);
+
+ lc = new Listcell(logAuditoria.getValorNovo());
+ lc.setParent(lstm);
+
+ lc = new Listcell(logAuditoria.getValorAnterior());
+ lc.setParent(lstm);
+
+ lc = new Listcell(logAuditoria.getClasseAlterada());
+ lc.setParent(lstm);
+
+ lc = new Listcell(logAuditoria.getClassePrincipal());
+ lc.setParent(lstm);
+
+ lstm.setAttribute("data", logAuditoria);
+ }
+
+}
diff --git a/src/java/spring-config.xml b/src/java/spring-config.xml
index cd8178f58..0f9f00e24 100644
--- a/src/java/spring-config.xml
+++ b/src/java/spring-config.xml
@@ -499,6 +499,7 @@
com.rjconsultores.ventaboletos.entidad.ConfRestricaoOrgaoConcedente
com.rjconsultores.ventaboletos.entidad.ConfRestricaoRutas
com.rjconsultores.ventaboletos.entidad.ConfRestricaoTramoOC
+ com.rjconsultores.ventaboletos.entidad.LogAuditoria
diff --git a/web/WEB-INF/i3-label_es_MX.label b/web/WEB-INF/i3-label_es_MX.label
index 6bed98683..933819866 100644
--- a/web/WEB-INF/i3-label_es_MX.label
+++ b/web/WEB-INF/i3-label_es_MX.label
@@ -192,6 +192,7 @@ indexController.mniConfiguracionServicio.label = Configuración de producto o se
indexController.mniPricingEspecifico.label = Pricing especÃfico
indexController.mnSeguridad.label = Seguridad
indexController.mniPerfil.label = Perfil
+indexController.mniLogAuditoria.label = Log Auditoria
indexController.mniPainelEcf.label = Painel ECF
indexController.mniPermisos.label = Permiso
indexController.mniMenus.label = Menu
@@ -8821,3 +8822,14 @@ painelVendaEmbarcadaController.msg.confirmacaoaltecaourl = Tem certeza que desej
painelVendaEmbarcadaController.msg.urlformatoinvalido = URL tem formato formato inválido.
painelVendaEmbarcadaController.msg.scusso = URL atualizada com sucesso
+#Log Auditoria
+busquedaLogAuditoriaController.window.title = Registro de auditorÃa
+busquedaLogAuditoriaController.lblDtAlteracao = Cambiar fecha
+busquedaLogAuditoriaController.lblTipoAlteracao = Tipo de cambio
+busquedaLogAuditoriaController.lblTela = Pantalla
+busquedaLogAuditoriaController.lblCampoAlterado = Campo cambiado
+busquedaLogAuditoriaController.lblValorNovo = Valor actual
+busquedaLogAuditoriaController.lblValorAnterior = Valor Anterior
+busquedaLogAuditoriaController.lblClasseAlterada = Clase cambiada
+busquedaLogAuditoriaController.lblClassePrincipal = Clase Principal
+busquedaLogAuditoriaController.lblIdAuditado = ID Auditado
\ No newline at end of file
diff --git a/web/WEB-INF/i3-label_pt_BR.label b/web/WEB-INF/i3-label_pt_BR.label
index a53c530a8..aa58574d1 100644
--- a/web/WEB-INF/i3-label_pt_BR.label
+++ b/web/WEB-INF/i3-label_pt_BR.label
@@ -196,6 +196,7 @@ indexController.mniConfiguracionServicio.label = Configuração de Produto ou Se
indexController.mniPricingEspecifico.label = Pricing EspecÃfico
indexController.mnSeguridad.label = Segurança
indexController.mniPerfil.label = Perfil
+indexController.mniLogAuditoria.label = Log Auditoria
indexController.mniPainelEcf.label = Painel ECF
indexController.mniPermisos.label = Permissão
indexController.mniMenus.label = Menu
@@ -9332,4 +9333,16 @@ relatorioMmphDerController.MSG.dataInicialMaiorFinal = Data inicial maior que fi
relatorioCaixaOrgaoConcedenteController.window.title=Relatório Caixa por Órgão Concedente
relatorioCaixaOrgaoConcedenteController.lbDataInicio.value=Data Inicio
relatorioCaixaOrgaoConcedenteController.lbDataFinal.value=Data Final
-relatorioCaixaOrgaoConcedenteController.lb.nomeBilheteiro.value = Nome Bilheteiro
\ No newline at end of file
+relatorioCaixaOrgaoConcedenteController.lb.nomeBilheteiro.value = Nome Bilheteiro
+
+#Log Auditoria
+busquedaLogAuditoriaController.window.title = Log Auditoria
+busquedaLogAuditoriaController.lblDtAlteracao = Data Alteração
+busquedaLogAuditoriaController.lblTipoAlteracao = Tipo Alteração
+busquedaLogAuditoriaController.lblTela = Tela
+busquedaLogAuditoriaController.lblCampoAlterado = Campo Alterado
+busquedaLogAuditoriaController.lblValorNovo = Valor Atual
+busquedaLogAuditoriaController.lblValorAnterior = Valor Anterior
+busquedaLogAuditoriaController.lblClasseAlterada = Classe Alterada
+busquedaLogAuditoriaController.lblClassePrincipal = Classe Principal
+busquedaLogAuditoriaController.lblIdAuditado = ID Auditado
\ No newline at end of file
diff --git a/web/gui/seguridad/busquedaLogAuditoria.zul b/web/gui/seguridad/busquedaLogAuditoria.zul
new file mode 100644
index 000000000..2f112d9a2
--- /dev/null
+++ b/web/gui/seguridad/busquedaLogAuditoria.zul
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file