Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
2
2. OBJETIVOS DEL TRABAJO GUIADO .......................................................... 2
3. TEMAS SELECCIONADOS ........................................................................... 2
4. EQUIPOS ........................................................................................................ 3
5. DESARROLLO DEL TRABAJO GUIADO ..................................................... 4
5.1. SEGUIMIENTO AL PROCESO DE DESARROLLO. ................................... 4
5.2. Etapa 1 – Configuraciones SBT .................................................................... 5
5.2.1. Objetivos de la etapa 1 ............................................................................... 5
5.2.2. Base teórica .................................................................................................. 5
5.2.3. Configuraciones SBT .................................................................................. 5
5.3. Etapa 2 – Desarrollo Scala ........................................................................... 10
5.3.1. Objetivos de la etapa 2 ............................................................................. 10
5.3.2. Base teórica ................................................................................................ 10
5.3.3. Desarrollo Scala ......................................................................................... 10
5.3.3.1. Módulo Activos TI ............................................................................... 10
5.3.3.2. Biblioteca BCB .................................................................................... 13
5.3.3.3. Módulo Casa de cambio .................................................................... 16
5.3.3.4. Módulo Interfaz SWIFT ...................................................................... 19
5.4. Etapa 3 – Desarrollo Liftweb ........................................................................ 21
5.4.1. Objetivos de la etapa 3 ............................................................................. 21
5.4.2. Base teórica ................................................................................................ 21
5.4.3. Desarrollo Liftweb ...................................................................................... 21
5.4.3.1. Modulo Activos TI ............................................................................... 22
5.4.3.2. Módulo Bibliotecas BCB .................................................................... 29
5.4.3.3. Modulo Casa de cambio .................................................................... 37
5.4.3.4. Modulo Interfaz SWIFT ...................................................................... 45
6. RESULTADOS ALCANZADOS ................................................................... 48
7. ANEXOS ....................................................................................................... 49
1
1. INTRODUCCION
El trabajo guiado forma parte imprescindible del curso-taller SBT – Scala – Liftweb,
ya que abarca la puesta en práctica del conocimiento impartido durante 2 semanas,
las cuales implicaron un total de 40 horas.
En base a los objetivos del curso, se pretende que el presente documento, junto al
material bibliográfico constituyan una fuente de consulta para el desarrollo futuro
de aplicaciones web con las tecnologías SBT, Scala y Liftweb.
3. TEMAS SELECCIONADOS
Activos de TI
Actualmente el departamento de TI del BCB gestiona sus activos a traves
de documentos de Excel. Sin embargo, en los últimos meses se procedió a
armar una base de datos Informix. El objetivo del módulo se enmarcó en
crear una aplicación web con conexión a base de datos Informix (que sería
una copia respecto a la estrucutura de la base de datos en producción)
donde se aplique la creación de CRUDs de Activos TI .
2
Biblioteca BCB
Actualmente la biblioteca del BCB cuenta con un sistema obsoleto, basado
en tecnologia DOS. El objetivo del módulo se enmarcó en crear un sistema
web de fácil acceso que gestione el registro de libros, Cds o material
interactivo y préstamos para la biblioteca BCB.
Interfaz SWIFT
Actualmente el BCB cuenta con archivos con extension .dos que contienen
la informacion de depositos internacionales. El objetivo del modulo se
enmarcó en crear una aplicación web que sea capaz de leer esos archivos,
mostrarlos en formato comprensible al usuario final a traves de un
documentos PDF y crear un CRUD de representacion SWIFT.
Casa de cambio
El objetivo del módulo se enmarcó en crear un sistema web para las
actividades de una casa de cambio, donde debía identificarse a un cliente,
realizar el registro del mismo, crear monedas y tipos de cambio asociados
y finalmente, guardar las transacciones de cambio de moneda.
BCB Master
El objetivo de la aplicación web, es brindar los enlaces de conexión
necesarios para acceder a los módulos previamente descritos. Fué
desarrollado como un módulo adicional, con el único fin de interconectar el
resto de los módulos.
4. EQUIPOS
Los equipos fueron conformados por 2 a 4 personas bajo los criterios de afinidad
y perfil profesional. A continuación se describe los nombres de equipos,
integrantes y proyecto desarrollado.
3
Equipo: Fusion
Integrantes:
Chuquimia Arratia Vania Mercedes
Coaquira Quisberth Lizeth Jimena
Garcia Limchs Ana Maria
Mamani Quisberth Reymi Veronica
Módulo: Biblioteca BCB
Equipo: Internacionales
Integrantes:
Illanes Burgoa Gabriel Mauricio
Quispe Catacora Hugo
Tejeda Perez Richard Paolo
Módulo: Interfaz SWIFT
4
Durante cada iteración, la capacitadora, realiza la revisión de los objetivos, antes
de iniciarla. Se registra la hora de inicio de la iteración y se realiza un seguimiento
entre los 15 a 20 minutos de iniciada, para identificar posibles problemas,
desvio de objetivos o soporte.
5
build.sbt de Activos TI
name := "Activos TI"
version := "1.0.0"
organization := "net.liftweb"
scalaVersion := "2.11.2"
6
build.sbt de Biblioteca BCB
name := "Proyecto Biblioteca"
version := "0.1.0"
organization := "bcb.gob.bo"
scalaVersion := "2.11.2"
enablePlugins(JettyPlugin)
libraryDependencies ++= {
val liftVersion = "2.6.3"
Seq(
"net.liftweb" %% "lift-webkit" % liftVersion %
"compile",
"net.liftmodules" %% "lift-jquery-module_3.0" % "2.10",
"net.liftweb" %% "lift-jpa" % liftVersion % "compile"
withSources(),
"ch.qos.logback" % "logback-classic" % "1.2.3",
"org.specs2" %% "specs2-core" % "3.9.4"
% "test",
"org.hibernate" % "hibernate-entitymanager" % "4.2.0.Final",
"org.hibernate" % "hibernate-core" % "4.2.0.Final",
"org.hibernate" % "hibernate-validator" % "4.2.0.Final",
"org.postgresql" % "postgresql" % "42.2.5",
"net.sf.jasperreports" % "jasperreports" % "5.5.0",
"com.lowagie" % "itext" % "2.1.7",
"javax.servlet" % "javax.servlet-api" % "3.0.1"
% "provided",
"org.slf4j" % "slf4j-api" % "1.6.1",
"org.slf4j" % "slf4j-log4j12" % "1.6.1",
"log4j" % "log4j" % "1.2.16"
)
}
7
build.sbt de Casa de cambio
name := "LiftBasicoHQuispe3.0"
version := "0.1.0"
organization := "net.liftweb"
scalaVersion := "2.11.2"
enablePlugins(JettyPlugin)
libraryDependencies ++= {
val liftVersion = "2.6.3"
Seq(
"net.liftweb" %% "lift-webkit" % liftVersion %
"compile",
"net.liftmodules" %% "lift-jquery-module_3.0" % "2.10",
"net.liftweb" %% "lift-jpa" % liftVersion % "compile"
withSources(),
"ch.qos.logback" % "logback-classic" % "1.2.3",
"org.specs2" %% "specs2-core" % "3.9.4"
% "test",
"org.hibernate" % "hibernate-entitymanager" % "4.2.0.Final",
"org.hibernate" % "hibernate-core" % "4.2.0.Final",
"org.hibernate" % "hibernate-validator" % "4.2.0.Final",
"org.postgresql" % "postgresql" % "42.2.5",
"javax.servlet" % "javax.servlet-api" % "3.0.1"
% "provided",
"org.slf4j" % "slf4j-api" % "1.6.1",
"org.slf4j" % "slf4j-log4j12" % "1.6.1",
"log4j" % "log4j" % "1.2.16"
)
}
8
build.sbt de Interfaz SWIFT
name := "Lift 3.0 starter template"
version := "0.1.0"
organization := "net.liftweb"
scalaVersion := "2.11.2"
enablePlugins(JettyPlugin)
libraryDependencies ++= {
val liftVersion = "2.6.3"
Seq(
"net.liftweb" %% "lift-webkit" % liftVersion %
"compile",
"net.liftmodules" %% "lift-jquery-module_3.0" % "2.10",
"net.liftweb" %% "lift-jpa" % liftVersion % "compile"
withSources(),
"ch.qos.logback" % "logback-classic" % "1.2.3",
"org.specs2" %% "specs2-core" % "3.9.4"
% "test",
"org.hibernate" % "hibernate-entitymanager" % "4.2.0.Final",
"org.hibernate" % "hibernate-core" % "4.2.0.Final",
"org.hibernate" % "hibernate-validator" % "4.2.0.Final",
"com.ibm." % "jdbc" % "4.10.8.1",
"net.sf.jasperreports" % "jasperreports" % "5.5.0",
"com.lowagie" % "itext" % "2.1.7",
"javax.servlet" % "javax.servlet-api" % "3.0.1"
% "provided",
"org.slf4j" % "slf4j-api" % "1.6.1",
"org.slf4j" % "slf4j-log4j12" % "1.6.1",
"log4j" % "log4j" % "1.2.16",
"org.apache.httpcomponents" % "httpclient" %
"4.5.6",
"org.apache.commons" % "commons-lang3" %
"3.7",
"com.fasterxml.jackson.core" % "jackson-core" % "2.6.6",
"com.fasterxml.jackson.core" % "jackson-databind" % "2.6.6"
)
}
10
package code
package model
//import net.liftweb.mapper._
import net.liftweb.util._
import net.liftweb.common._
import javax.persistence._
import javax.validation._
import javax.validation.constraints._
import org.hibernate.validator.constraints._
import scala.collection.JavaConversions._
@Entity
@Table(name = "lenguaje_programacion")
class Lenguaje_programacion {
@Id
@NotBlank
var id_lenguaje : Int = _
@NotBlank
@Size(max=60)
var nom_lenguaje: String = ""
@Size(max=2)
var cve_framework : String = ""
}
object Lenguaje_programacion {
def findPage(pageNumber: Int, pageSize: Int): List[Lenguaje_programacion]
= {
JPAUtility.findAll[Lenguaje_programacion]("AllLenguajeProgramacion").toList
}
11
package code.model
//import net.liftweb.mapper._
import net.liftweb.util._
import net.liftweb.common._
import javax.persistence._
import javax.validation._
import javax.validation.constraints._
import org.hibernate.validator.constraints._
import scala.collection.JavaConversions._
@Entity
@Table(name = "servidores")
class Servidores {
@Id
@NotBlank
//@GeneratedValue(generator="id_lenguaje")
var id_servidores : Int = _
//@Column(nullable=false)
@NotBlank
@Size(max=60)
var nom_servidores: String = ""
}
object Servidores {
def findPage(pageNumber: Int, pageSize: Int): List[Servidores] = {
JPAUtility.findAll[Servidores]("AllServidores").toList
}
12
5.3.3.2. Biblioteca BCB
package code.model
//import net.liftweb.mapper._
import net.liftweb.util._
import net.liftweb.common._
import javax.persistence._
import javax.validation._
import javax.validation.constraints._
import org.hibernate.validator.constraints._
import scala.collection.JavaConversions._
@Entity
@Table(name="lector")
class Lector {
@Id
@GeneratedValue(generator = "LectorIdSeq")
var idLector: Long = -1
@Column(nullable = false)
@NotBlank
var nombres: String = ""
@Column(nullable = false)
@NotBlank
var paterno: String = ""
@Column(nullable = false)
@NotBlank
var materno: String = ""
@Column(nullable = false)
@NotBlank
@Size(max = 3)
var cveTipoLector: String = ""
@Column(nullable = false)
@Size(max = 5)
var codEmpleado: String = ""
@Column(nullable = false)
var direccion: String = ""
@Column(nullable = false)
@Size(max = 10)
var telefono: String = ""
@Column(nullable = false)
13
var estado: String = ""
@Column(nullable = false)
@Temporal(TemporalType.DATE)
var fechaRegistro: java.util.Date = null
object Lector {
def findPage(pageNumber: Int, pageSize: Int): List[Lector] = {
JPAUtility
.createNamedQuery("AllLector")
.setFirstResult((pageNumber-1) * pageSize)
.setMaxResults(pageSize)
.findAll
.toList
}
14
package code.model
import javax.persistence._
import javax.validation._
import javax.validation.constraints._
import net.liftweb.common.Box
import net.liftweb.util.Helpers
import org.hibernate.validator.constraints._
import scala.collection.JavaConversions._
@Entity
@Table(name="prestamo")
class Prestamo {
@Id
@GeneratedValue(generator = "PrestamoIdSeq")
var idPrestamo : Long = _
@Temporal(TemporalType.DATE)
var fechaPrestamo : java.util.Date =
java.util.Calendar.getInstance().getTime
@Temporal(TemporalType.DATE)
var fechaDevolucion : java.util.Date =
java.util.Calendar.getInstance().getTime
@Column(nullable=false)
var cveTipoPrestamo: String = ""
@Column(nullable=false)
var estado: String = ""
}
object Prestamo {
}
Figura 8 – Clase Prestamo del módulo Biblioteca BCB
15
Figura 9 – Ejemplo de ejecución de simulación módulo Biblioteca BCB.
package code
package model
//import net.liftweb.mapper._
import net.liftweb.util._
import net.liftweb.common._
import javax.persistence._
import javax.validation._
import javax.validation.constraints._
import org.hibernate.validator.constraints._
import scala.collection.JavaConversions._
@Entity
class Moneda {
@Id
@GeneratedValue(generator="MonedaIdSeq")
var id : Long = _
@Column(nullable=false)
@NotBlank
@Size(max=3)
var codmoneda : String = ""
@Column(nullable=false)
@NotBlank
@Size(max=30)
var nommoneda : String = ""
16
}
object Moneda {
def findPage(pageNumber: Int, pageSize: Int): List[Moneda] = {
JPAUtility
.createNamedQuery("AllMoneda")
.setFirstResult((pageNumber-1) * pageSize)
.setMaxResults(pageSize)
.findAll
.toList
}
17
package code
package model
//import net.liftweb.mapper._
import net.liftweb.util._
import net.liftweb.common._
import javax.persistence._
import javax.validation._
import javax.validation.constraints._
import org.hibernate.validator.constraints._
import scala.collection.JavaConversions._
@Entity
class Transaccion {
@Id
@GeneratedValue(generator="TransaccionIdSeq")
var id : Long = _
@Column(nullable=false)
@Temporal(TemporalType.DATE)
var fecha_trans : java.util.Date = new java.util.Date()
@ManyToOne(optional=false)
var cliente : Cliente = _
@Column(nullable=false)
@NotBlank
@Size(max=80)
var concepto : String = ""
}
object Transaccion {
def findPage(pageNumber: Int, pageSize: Int): List[Transaccion] = {
JPAUtility
.createNamedQuery("AllTransaccion")
.setFirstResult((pageNumber-1) * pageSize)
.setMaxResults(pageSize)
.findAll
.toList
}
18
5.3.3.4. Módulo Interfaz SWIFT
package code.model
@Entity
class Swiftcurso {
@Id
var id : Long = _
@Size(max=32)
var estado : String = ""
@Size(max=500)
var plano : String = ""
}
object Swiftcurso {
def getAll(): List[Swiftcurso] = {
JPAUtility.findAll[Swiftcurso]("AllSwiftcurso").toList
}
def find(id: String): Box[Swiftcurso] = {
for {
id <- Helpers.asLong(id)
org <- JPAUtility.find(classOf[Swiftcurso], id)
} yield org
}
}
Figura 12 - Clase SWIFT del módulo interfaz SWIFT
package dk.nscp.rest_server
import akka.util.Timeout
import scala.concurrent.duration._
import akka.pattern.ask
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.stream.ActorMaterializer
import scala.io.StdIn
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import bcb.cursoscala.servicio.ReporteSwiftServiceRest
import gob.bcb.core.utils.UtilsFile
import spray.json._
import slick.driver.SQLiteDriver.api._
19
import org.sqlite.JDBC
bindingFuture.flatMap(_.unbind())
system.terminate()
}
Figura 13 – Clase Principal donde se ejecuta la lectura de un archivo SWIFT
20
5.4. Etapa 3 – Desarrollo Liftweb
La etapa Liftweb consistió en programar las pantallas web necesarias para cada
módulo. Conocer la arquitectura y beneficios de la biblioteca de Liftweb para el
manejo correcto.
21
5.4.3.1. Modulo Activos TI
package code.snippet
import code.lib.MainMenu
import code.lib.menu.MenuServidor
import code.model.{Servidor, JPAUtility}
import net.liftweb.util.CssSel
import net.liftweb.common.Full
import net.liftweb.http.SHtml
import javax.persistence.EntityManager
import net.liftweb.http.js.JsCmds.RedirectTo
import scala.xml.NodeSeq
import net.liftweb.util.Helpers._
object ServidorSnippet {
def list: CssSel = {
def pageItems = Servidor.findPage(1, 10)
def count = 1 //
JPAUtility.createNativeQuery[java.math.BigInteger]("select count(*)
from customer;").getSingleResult().intValue
22
"data-name=id_log_auditoria" #> SHtml.text("", la =>
servidor.id_log_auditoria = la.toInt)&
"data-name=cve_estado" #> SHtml.text("", cs =>
servidor.cve_estado = cs)&
"type=submit" #>SHtml.ajaxSubmit("Guardar", () => {
JPAUtility.mergeAndFlush(servidor)
RedirectTo( MainMenu.servidor.loc.calcDefaultHref)
})
}
"data-name=id_servidor" #>
SHtml.text(servidor.id_servidor.toString, fn =>(), "disabled" ->
"disabled") &
"data-name=nom_servidor" #> SHtml.text(servidor.nom_servidor,
ln => (), "disabled" -> "disabled") &
"data-name=so_servidor" #> SHtml.text(servidor.so_servidor, lo
=> (), "disabled" -> "disabled")&
"data-name=id_log_auditoria" #>
SHtml.text(servidor.id_log_auditoria.toString, ds => (), "disabled" ->
"disabled")&
"data-name=desc_servidor" #>
SHtml.textarea(servidor.desc_servidor, ds => (), "disabled" ->
"disabled")&
"data-name=cve_estado" #> SHtml.text(servidor.cve_estado, cs =>
(), "disabled" -> "disabled")&
"type=submit" #>SHtml.ajaxSubmit("Eliminar", () => {
23
// ToDo - delete
val removeCustomer = JPAUtility.merge(servidor)
JPAUtility.removeAndFlush(removeCustomer)
RedirectTo(MainMenu.servidor.loc.calcDefaultHref)
})
24
package code.lib.menu
import code.model.Servidor
import net.liftweb.common.{Box, Full}
import net.liftweb.http.{S, Templates}
import net.liftweb.sitemap.Loc.{LocGroup, Template}
import net.liftweb.sitemap.Menu
import scala.xml.NodeSeq
object MenuServidor {
lazy val menuAdd: Menu = Menu("Add Servidor", S ? "Adicionar
Servidor") / "crud" / "servidor" / "add" // >> LocGroup("servidor") //
>> Hidden
25
package report
import java.util
import code.model.Servidor
import net.liftweb.common.Box
import net.liftweb.http.LiftRules
import net.sf.jasperreports.engine._
import net.sf.jasperreports.engine.data.JRTableModelDataSource
import net.sf.jasperreports.engine.export.{JRCsvExporter, JRPdfExporter,
JRXhtmlExporter}
import net.sf.jasperreports.engine.export.ooxml.JRXlsxExporter
import net.sf.jasperreports.engine.fill.JRFileVirtualizer
import collection.JavaConverters
trait ServidorReport {
26
}
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint)
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, out)
exporter.exportReport()
out
}
}
object ServidorSample {
val customer1 = new Servidor
customer1.id_servidor = 1
customer1.nom_servidor = "Power Builder"
customer1.so_servidor = "AIX 7"
customer1.desc_servidor = "IP-Pub:10.2.11.32 - IP-Int:11.1.11.4 - Puerto:1527
"
customer1.id_log_auditoria = 1
customer1.cve_estado = "N"
val customer2 = new Servidor
customer2.id_servidor = 2
customer2.nom_servidor = "GSIS"
customer2.so_servidor = "AIX 6"
customer2.desc_servidor = "IP-Pub:10.2.11.32 - IP-Int:100.10.20.10 -
Puerto:1527 "
customer2.id_log_auditoria = 1
customer2.cve_estado = "V"
val customer3 = new Servidor
customer3.id_servidor = 3
customer3.nom_servidor = "DDS"
customer3.so_servidor = "AIX 7"
customer3.desc_servidor = "IP-Pub:10.11.0.0 - IP-Int:11.1.11.4 - }
def next():Boolean = {
indiceActual = indiceActual + 1
indiceActual < lsBonos.size
}
}
Figura 16 – Reporte de Servidores – Módulo Activos TI
27
package bootstrap.liftweb
import net.liftweb._
import util._
import Helpers._
import common._
import http._
import js.jquery.JQueryArtifacts
import sitemap._
import Loc._
import code.lib.MainMenu
import code.lib.report.ReportRules
import code.model._
import net.liftmodules.JQueryModule
class Boot {
def boot {
LiftRules.addToPackages("code")
JQueryModule.InitParam.JQuery=JQueryModule.JQuery1113
JQueryModule.init()
LiftRules.ajaxStart =
Full(() => LiftRules.jsArtifacts.show("ajax-loader").cmd)
LiftRules.ajaxEnd =
Full(() => LiftRules.jsArtifacts.hide("ajax-loader").cmd)
LiftRules.early.append(_.setCharacterEncoding("UTF-8"))
ReportRules.appendDispatchRules
ReportRules.appendDispatchRules1
}
}
Figura 17 – Configuración del Boot.scala – Módulo Activos TI
28
5.4.3.2. Módulo Bibliotecas BCB
package code.snippet
import java.util.Locale
import code.lib.MainMenu
import code.lib.menu.MenuLector
import code.model.{Lector, JPAUtility}
import net.liftweb.common.Full
import net.liftweb.http.SHtml
import net.liftweb.http.js.JsCmds.RedirectTo
import net.liftweb.util.CssSel
import net.liftweb.util.Helpers._
import scala.xml.NodeSeq
object LectorSnippet {
29
"data-name=tipo" #> SHtml.text("", tipo => lector.cveTipoLector =
tipo) &
"data-name=estado" #> SHtml.text("", estado => lector.estado =
estado) &
"data-name=fecha" #> SHtml.text("", fecha => lector.fechaRegistro =
format.parse(fecha)) &
"type=submit" #>SHtml.ajaxSubmit("Save", () => {
JPAUtility.mergeAndFlush(lector)
RedirectTo( MainMenu.lectores.loc.calcDefaultHref)
})
"type=button" #>SHtml.ajaxButton("Cancelar", () => {
RedirectTo( MainMenu.lectores.loc.calcDefaultHref)
})
}
30
"data-name=tipo" #> SHtml.text(lector.cveTipoLector, tipo
=> lector.cveTipoLector = tipo) &
"data-name=fono" #> SHtml.text(lector.telefono, fono =>
lector.telefono = fono) &
"data-name=estado" #> SHtml.text(lector.estado, estado =>
lector.estado = estado) &
"data-name=fecha" #>
SHtml.text(format.format(lector.fechaRegistro), fecha =>
lector.fechaRegistro = format.parse(fecha)) &
"type=submit" #>SHtml.ajaxSubmit("Delete", () => {
// ToDo - delete
val removeLector = JPAUtility.merge(lector)
JPAUtility.removeAndFlush(removeLector)
RedirectTo(MainMenu.lectores.loc.calcDefaultHref)
})
}).openOr("*" #> NodeSeq.Empty)
}
}
Figura 18 – Snippet Lector – Módulo Bblioteca BCB
31
package code.snippet
object PrestamoSnippet{
def list: CssSel = {
def pageItems = Prestamo.findPage(1, 10)
def count =
JPAUtility.createNativeQuery[java.math.BigInteger]("select count(*)
from prestamo").getSingleResult().intValue
"data-name=list *" #> pageItems.map(prestamo => {
"data-name=code *" #> prestamo.idPrestamo &
"data-name=fechaprestamo *" #> s"${prestamo.fechaPrestamo}" &
"data-name=fechadevolucion *" #> s"${prestamo.fechaDevolucion}" &
"data-name=tipo *" #> s"${prestamo.cveTipoPrestamo}" &
"data-name=estado *" #> s"${prestamo.estado}" &
"data-name=edit [href]" #> MenuPrestamo.locEdit.calcHref(prestamo) &
"data-name=view [href]" #> MenuPrestamo.locView.calcHref(prestamo) &
"data-name=delete [href]" #>
MenuPrestamo.locDelete.calcHref(prestamo)
})
}
def add: CssSel = {
val prestamo = new Prestamo
val format = new java.text.SimpleDateFormat("dd/MM/yyyy")
case class Estado(id: String, descripcion: String) {
override def toString: String = descripcion }
val estados = List(Estado("P","Prestado"),Estado("D","Devuelto"))
32
"data-name=fecha_devolucion" #> SHtml.text("", fechaDevolucion =>
prestamo.fechaDevolucion = format.parse(fechaDevolucion)) &
"data-name=tipo" #> SHtml.text(prestamo.cveTipoPrestamo, fn =>
prestamo.cveTipoPrestamo = fn) &
"data-name=estado" #> SHtml.text(prestamo.estado, ln =>
prestamo.estado = ln) &
"data-name=fecha_devolucion" #>
SHtml.text(format.format(prestamo.fechaDevolucion), fechap =>
prestamo.fechaDevolucion = format.parse(fechap)) &
"type=submit" #>SHtml.ajaxSubmit("Update", () => {
JPAUtility.mergeAndFlush(prestamo)
RedirectTo(MainMenu.prestamos.loc.calcDefaultHref)
})
}).openOr("*" #> NodeSeq.Empty)
}
def view: CssSel = {
(for {
prestamo <- MenuPrestamo.menuView.currentValue
} yield {
val format = new java.text.SimpleDateFormat("dd/MM/yyyy")
"data-name=fecha_prestamo" #>
SHtml.text(format.format(prestamo.fechaPrestamo), fechaPrestamo => (),
"disabled" -> "disabled") &
"data-name=tipo" #> SHtml.text(prestamo.cveTipoPrestamo, fn =>(),
"disabled" -> "disabled") &
"data-name=estado" #> SHtml.text(prestamo.estado, ln => (),
"disabled" -> "disabled") &
"data-name=fecha_devolucion" #>
SHtml.text(format.format(prestamo.fechaDevolucion), fechaDevolucion =>
(), "disabled" -> "disabled") &
"type=submit" #>SHtml.ajaxSubmit("Return", () => {
RedirectTo(MainMenu.prestamos.loc.calcDefaultHref)
})
}).openOr("*" #> NodeSeq.Empty)
}
def delete: CssSel = {
(for {
prestamo <- MenuPrestamo.menuDelete.currentValue
} yield {
val format = new java.text.SimpleDateFormat("dd/MM/yyyy")
"data-name=fecha_prestamo" #>
SHtml.text(format.format(prestamo.fechaPrestamo), fechaPrestamo => (),
"disabled" -> "disabled") &
"data-name=tipo" #> SHtml.text(prestamo.cveTipoPrestamo, fn
=>(), "disabled" -> "disabled") &
"data-name=estado" #> SHtml.text(prestamo.estado, ln => (),
"disabled" -> "disabled") &
"data-name=fecha_devolucion" #>
SHtml.text(format.format(prestamo.fechaDevolucion), fechaDevolucion =>
(), "disabled" -> "disabled") &
"type=submit" #>SHtml.ajaxSubmit("Delete", () => {
// ToDo - delete
val removePrestamo = JPAUtility.merge(prestamo)
JPAUtility.removeAndFlush(removePrestamo)
RedirectTo(MainMenu.prestamos.loc.calcDefaultHref)
})
}).openOr("*" #> NodeSeq.Empty)
}
}
Figura 19 – Snippet Prestamo – Módulo Boblioteca BCB
33
package report
import java.util
import code.model.Customer
import net.liftweb.common.Box
import net.liftweb.http.LiftRules
import net.sf.jasperreports.engine._
import net.sf.jasperreports.engine.data.JRTableModelDataSource
import net.sf.jasperreports.engine.export.{JRCsvExporter, JRPdfExporter,
JRXhtmlExporter}
import net.sf.jasperreports.engine.export.ooxml.JRXlsxExporter
import net.sf.jasperreports.engine.fill.JRFileVirtualizer
import collection.JavaConverters
trait PrestamoReport {
34
case _ => new JRXhtmlExporter
}
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint)
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, out)
exporter.exportReport()
out
}
}
object CustomerSample {
val customer1 = new Customer
customer1.firstname = "Cuentos para niños"
customer1.lastname = "EN SALA"
customer1.email = "PRESTADO"
customer1.birthday = java.util.Calendar.getInstance().getTime
def next():Boolean = {
indiceActual = indiceActual + 1
indiceActual < lsBonos.size
}
}
Figura 20 – Reporte de préstamos – Módulo Biblioteca BCB
35
package bootstrap.liftweb
import net.liftweb._
import util._
import Helpers._
import common._
import http._
import js.jquery.JQueryArtifacts
import sitemap._
import Loc._
import code.lib
import code.lib.MainMenu
import code.lib.report.ReportRules
import code.model._
import net.liftmodules.JQueryModule
class Boot {
def boot {
LiftRules.addToPackages("code")
// Build SiteMap
def sitemap = SiteMap(
(Menu.i("Inicio") / "index"),
Menu(Loc("Static", Link(List("static"), true, "/static/index"),
"Busqueda")),
MainMenu.lectores,
MainMenu.prestamos,
MainMenu.clasificacion,
MainMenu.catalogo,
MainMenu.editorial
)
JQueryModule.InitParam.JQuery=JQueryModule.JQuery1113
JQueryModule.init()
LiftRules.ajaxStart =
Full(() => LiftRules.jsArtifacts.show("ajax-loader").cmd)
LiftRules.ajaxEnd =
Full(() => LiftRules.jsArtifacts.hide("ajax-loader").cmd)
LiftRules.early.append(_.setCharacterEncoding("UTF-8"))
ReportRules.appendDispatchRules
}
}
Figura 21 – Configuración del Boot.scala – Módulo de Biblioteca BCB
36
5.4.3.3. Modulo Casa de cambio
package code.snippet
import code.lib.MainMenu
import code.lib.menu.MenuMoneda
import code.model.Moneda
import code.model.{Cliente, Customer, JPAUtility}
import net.liftweb.common.Full
import net.liftweb.http.SHtml
import net.liftweb.http.js.JsCmds.RedirectTo
import net.liftweb.util.CssSel
import net.liftweb.util.Helpers._
import scala.xml.NodeSeq
object MonedaSnippet {
37
val format = new java.text.SimpleDateFormat("dd/MM/yyyy")
"data-name=codmoneda" #> SHtml.text(moneda.codmoneda, fn =>
moneda.codmoneda = fn) &
"data-name=nommoneda" #> SHtml.text(moneda.nommoneda, ln =>
moneda.nommoneda = ln) &
"type=submit" #>SHtml.ajaxSubmit("Update", () => {
JPAUtility.mergeAndFlush(moneda)
RedirectTo(MainMenu.moneda.loc.calcDefaultHref)
})
}).openOr("*" #> NodeSeq.Empty)
}
}
Figura 22 - Snippet Moneda - Módulo Casa de cambio
38
package code.snippet
object TipoCambioSnippet {
def list: CssSel = {
def pageItems = Tipocambio.findPage(1, 10)
def count =
JPAUtility.createNativeQuery[java.math.BigInteger]("select count(*)
from tipocambio").getSingleResult().intValue
"data-name=list *" #> pageItems.map(tipocambio => {
"data-name=moneda_id *" #> tipocambio.moneda.toString &
"data-name=fecha *" #> s"${tipocambio.fecha} " &
"data-name=factor_oficial *" #>
s"${tipocambio.factor_oficial.toString } " &
"data-name=factor_compra *" #>
s"${tipocambio.factor_compra.toString } " &
"data-name=factor_oficial *" #>
s"${tipocambio.factor_venta.toString } " &
"data-name=view [href]" #>
MenuTipocambio.locView.calcHref(tipocambio) &
"data-name=edit [href]" #>
MenuTipocambio.locEdit.calcHref(tipocambio) &
"data-name=delete [href]" #>
MenuTipocambio.locDelete.calcHref(tipocambio)
}) &
"data-name=add-tipocambio [href]" #>
MenuTipocambio.menuAdd.loc.calcDefaultHref
}
def sumF (a: java.math.BigDecimal, b: java.math.BigDecimal):
java.math.BigDecimal = {
return a.add(b)
}
def add: CssSel = {
val tipocambio = new Tipocambio
val format = new java.text.SimpleDateFormat("dd/MM/yyyy")
val monedas = Moneda.findAll()
var tfc = tipocambio.factor_oficial.add(tipocambio.factor_compra)
39
tfc = sumF(tipocambio.factor_oficial, tipocambio.factor_compra)
}) &
"data-name=factor_venta" #> SHtml.ajaxText(tfc.toString,fc => ()) &
"type=submit" #>SHtml.ajaxSubmit("Save", () => {
JPAUtility.mergeAndFlush(tipocambio)
RedirectTo( MainMenu.tipocambio.loc.calcDefaultHref)
})
}
def edit: CssSel = {
(for {
tipocambio <- MenuTipocambio.menuEdit.currentValue
} yield {
val monedas = Moneda.findAll()
val format = new java.text.SimpleDateFormat("dd/MM/yyyy")
40
package snippet
import net.liftweb._
import http._
import SHtml._
import util._
import Helpers._
import code.model.Moneda
import js._
import js.JsCmds._
import js.jquery._
import net.liftweb.common.Full
import scala.xml.{NodeSeq, Text}
case class Line (guid: String, name: String, price: Double, taxable:
Boolean, descuento: Double)
case class Line (guid: String, name: String, price: Double)
case class NextLine (Canitdad: Double, total: Double)
class InvoiceWiring {
private object Info {
val invoices = ValueCell(List(newLine))
val taxRate = ValueCell(0.50d) // Se define el
valor del TAX
val subtotal = invoices.lift(_.foldLeft(0d)(_ + _.price))
val taxable = invoices.lift(_.filter(_.taxable).
foldLeft(0D)(_ + _.price))
def addLine =
"#det [onclick]" #> ajaxInvoke(() =>
// JqJsCmds.AppendHtml("addLine", renderLine(appendLine)))
JqJsCmds.AppendHtml("invoice_lines", renderLine(appendLine)))
<div id={guid}>
{ajaxSelectElem(monedas, Full(monedas.head))((monselect:Moneda)
=> { mutateLine(guid) {line => line.copy(name=monselect.id.toString)}}
)}
var
41
{ajaxText(price.toString,
(d: Double) => mutateLine(guid) {_.copy(price = d)})}
{ajaxText (descuento.toString,
(d: Double) => mutateLine(guid) {_.copy(descuento = d)})}
{ajaxCheckbox(theLine.taxable,
b => mutateLine(guid) {_.copy(taxable = b)})}
</div>
}
42
package code.snippet
object TransaccionSnippet {
def list: CssSel = {
def pageItems = Transaccion.findPage(1, 10)
def count =
JPAUtility.createNativeQuery[java.math.BigInteger]("select count(*)
from transaccion").getSingleResult().intValue
"data-name=list *" #> pageItems.map(transaccion => {
"data-name=fecha_trans *" #> transaccion.fecha_trans.toString &
"data-name=cliente_id *" #> s"${transaccion.cliente} " &
"data-name=concepto *" #> s"${transaccion.concepto } " &
"data-name=view [href]" #>
MenuTransaccion.locView.calcHref(transaccion) &
"data-name=edit [href]" #>
MenuTransaccion.locEdit.calcHref(transaccion) &
"data-name=delete [href]" #>
MenuTransaccion.locDelete.calcHref(transaccion)
}) &
"data-name=add-transaccion [href]" #>
MenuTransaccion.menuAdd.loc.calcDefaultHref
}
43
} yield {
val clientes = Cliente.findAll()
val format = new java.text.SimpleDateFormat("dd/MM/yyyy")
"data-name=fecha_trans" #>
SHtml.text(format.format(transaccion.fecha_trans), fecha =>
transaccion.fecha_trans = format.parse(fecha)) &
"data-name=cliente_id" #> SHtml.selectElem[Cliente](clientes,
Full(clientes.head))(cli => transaccion.cliente = cli) &
"data-name=concepto" #> SHtml.text(transaccion.concepto, ad =>
transaccion.concepto = ad.trim) &
"type=submit" #>SHtml.ajaxSubmit("Update", () => {
JPAUtility.mergeAndFlush(transaccion)
RedirectTo(MainMenu.transaccion.loc.calcDefaultHref)
})
}).openOr("*" #> NodeSeq.Empty)
}
def delete: CssSel = {
(for {
transaccion <- MenuTransaccion.menuDelete.currentValue
} yield {
val format = new java.text.SimpleDateFormat("dd/MM/yyyy")
"data-name=fecha_trans" #>
SHtml.text(format.format(transaccion.fecha_trans), fecha => (),
"disabled" -> "disabled") &
"data-name=concepto" #> SHtml.text("", con =>
transaccion.concepto = con) &
"type=submit" #>SHtml.ajaxSubmit("Delete", () => {
// ToDo - delete
val removeTransaccion = JPAUtility.merge(transaccion)
JPAUtility.removeAndFlush(removeTransaccion)
RedirectTo(MainMenu.transaccion.loc.calcDefaultHref)
})
}).openOr("*" #> NodeSeq.Empty)
}
"data-name=cliente_id" #>
SHtml.text(transaccion.cliente.toString, mid =>(), "disabled" ->
"disabled") &
"data-name=fecha_trans" #>
SHtml.text(format.format(transaccion.fecha_trans), fecha => (),
"disabled" -> "disabled") &
"data-name=concepto" #> SHtml.text(transaccion.concepto, ad =>
(), "disabled" -> "disabled") &
"type=submit" #>SHtml.ajaxSubmit("Return", () => {
// ToDo - delete
// JPAUtility.mergeAndFlush(tipocambio)
RedirectTo(MainMenu.transaccion.loc.calcDefaultHref)
})
}).openOr("*" #> NodeSeq.Empty)
}
}
Figura 25 – Snippet de transacciones con uso de Wiring - Módulo Casa de
cambio
44
5.4.3.4. Modulo Interfaz SWIFT
package code.snippet
import code.lib.MainMenu
import code.lib.menu.MenuSwift
import code.model.{JPAUtility, Swiftcurso}
import net.liftweb.http.SHtml
import net.liftweb.http.js.JsCmds.RedirectTo
import net.liftweb.util.{CssSel, Html5}
import net.liftweb.util.Helpers._
import report.DownloadReportCustomer
import scala.xml
import scala.xml.NodeSeq
object SwiftSnippet {
def list: CssSel = {
def pageItems = Swiftcurso.getAll()
def count = 1 //
JPAUtility.createNativeQuery[java.math.BigInteger]("select count(*)
from customer;").getSingleResult().intValue
def showPdf = {
/* (for {
swiftcurso <- MenuSwift.menuView.currentValue
} yield {*/
"#viewpdf" #> {
45
}
// }).openOr("*" #> NodeSeq.Empty)
}
}
Figura 26 – Snippet SWIFT – Módulo Interfaz SWIFT
46
package code.lib.menu
import code.model.Swiftcurso
import net.liftweb.common.Box
import net.liftweb.http.{S, Templates}
import net.liftweb.sitemap.Loc.{LocGroup, Template}
import net.liftweb.sitemap.Menu
import scala.xml.NodeSeq
object MenuSwift {
}
Figura 27 – Armado de Menus – Módulo Interfaz SWIFT
47
6. RESULTADOS ALCANZADOS
En base a los objetivos del trabajo guiado, los cuales se encuentran en el alcance
del objetivo del presente curso-taller. Se obtuvieron los siguientes resultados:
48
7. ANEXOS
49