sábado, 20 de mayo de 2023

Creación de relaciones entre tablas

 Solo puse claves foraneas en las tablas pedidos (para referencias al cliente y a los prodcutos) y en factura (para referenciar a pedidos que ya referencia a los clientes y productos)


private const val PEDIDOS_SQL_CREATE_ENTRIES =
"CREATE TABLE IF NOT EXISTS ${FerreteriaContract.PedidoEntry.TABLE_NAME} (" +
"${FerreteriaContract.PedidoEntry.COLUMN_NAME_CODIGO} INTEGER PRIMARY KEY AUTOINCREMENT," +
"${FerreteriaContract.PedidoEntry.COLUMN_NAME_DESCRIPCION} TEXT,"+
"${FerreteriaContract.PedidoEntry.COLUMN_NAME_FECHA} DATE,"+
"${FerreteriaContract.PedidoEntry.COLUMN_NAME_COD_CLIENTE} INTEGER, "+
"FOREIGN KEY (${FerreteriaContract.PedidoEntry.COLUMN_NAME_COD_CLIENTE}) "+
"REFERENCES ${FerreteriaContract.ClienteEntry.TABLE_NAME} " +
" (${FerreteriaContract.ClienteEntry.COLUMN_NAME_CODIGO}))"


private const val FACTURAS_SQL_CREATE_ENTRIES =
"CREATE TABLE IF NOT EXISTS ${FerreteriaContract.FacturaEntry.TABLE_NAME} (" +
"${FerreteriaContract.FacturaEntry.COLUMN_NAME_CODIGO} INTEGER PRIMARY KEY AUTOINCREMENT," +
"${FerreteriaContract.FacturaEntry.COLUMN_NAME_FECHA} DATE,"+
"${FerreteriaContract.FacturaEntry.COLUMN_NAME_VALOR} DECIMAL,"+
"${FerreteriaContract.FacturaEntry.COLUMN_NAME_COD_PEDIDO} INTEGER, "+
"FOREIGN KEY (${FerreteriaContract.FacturaEntry.COLUMN_NAME_COD_PEDIDO}) " +
"REFERENCES ${FerreteriaContract.PedidoEntry.TABLE_NAME} " +
"(${FerreteriaContract.PedidoEntry.COLUMN_NAME_CODIGO}));"




Tabla intermedia entre pedidos y productos

private const val PEDIDO_PRDUCTO_SQL_CREATE_ENTRIES =
"CREATE TABLE IF NOT EXISTS pedidos_productos("+
"id INTEGER PRIMARY KEY AUTOINCREMENT,"+
"cod_pedido INTEGER,"+
"cod_producto INTEGER, "+
"FOREIGN KEY (cod_pedido) " +
"REFERENCES ${FerreteriaContract.PedidoEntry.TABLE_NAME} " +
"(${FerreteriaContract.PedidoEntry.COLUMN_NAME_CODIGO}),"+
"FOREIGN KEY (cod_producto)" +
"REFERENCES ${FerreteriaContract.ProductoEntry.TABLE_NAME} " +
"(${FerreteriaContract.ProductoEntry.COLUMN_NAME_CODIGO}))"

Creación de una base de datos

Al declarara un clase que implemente el SQLiteOpenHelper de la siguiente manera ya crea la base de datos (Kotlin)

class FerreteriaDBHelper(context: Context) : SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) {

detalle de las variables

donde el contexto es la actividad que se esta ejecutando y

const val DATABASE_VERSION = 1
const val DATABASE_NAME = "Ferreteria.db"

Creación de Tablas

 En la implementación de SQLiteOpeneHelper se ejecutan las queries de creación de las tablas

override fun onCreate(db: SQLiteDatabase) {
db.execSQL(Companion.CLIENTES_SQL_CREATE_ENTRIES)
db.execSQL(Companion.PEDIDOS_SQL_CREATE_ENTRIES)
db.execSQL(Companion.PRODUCTOS_SQL_CREATE_ENTRIES)
db.execSQL(Companion.FACTURAS_SQL_CREATE_ENTRIES)
db.execSQL(Companion.PEDIDO_PRDUCTO_SQL_CREATE_ENTRIES)

}

Para el caso de practica prouesto las queries fueron las siguientes

private const val CLIENTES_SQL_CREATE_ENTRIES =
"CREATE TABLE IF NOT EXISTS ${FerreteriaContract.ClienteEntry.TABLE_NAME} (" +
"${FerreteriaContract.ClienteEntry.COLUMN_NAME_CODIGO} INTEGER PRIMARY KEY AUTOINCREMENT," +
"${FerreteriaContract.ClienteEntry.COLUMN_NAME_NOMBRE} TEXT,"+
"${FerreteriaContract.ClienteEntry.COLUMN_NAME_DIRECCION} TEXT,"+
"${FerreteriaContract.ClienteEntry.COLUMN_NAME_TELEFONO} INTEGER )"


private const val PRODUCTOS_SQL_CREATE_ENTRIES =
"CREATE TABLE IF NOT EXISTS ${FerreteriaContract.ProductoEntry.TABLE_NAME} (" +
"${FerreteriaContract.ProductoEntry.COLUMN_NAME_CODIGO} INTEGER PRIMARY KEY AUTOINCREMENT," +
"${FerreteriaContract.ProductoEntry.COLUMN_NAME_FABRICANTE} TEXT,"+
"${FerreteriaContract.ProductoEntry.COLUMN_NAME_VALOR} DECIMAL,"+
"${FerreteriaContract.ProductoEntry.COLUMN_NAME_COD_PEDIDO} INTEGER)"


private const val PEDIDOS_SQL_CREATE_ENTRIES =
"CREATE TABLE IF NOT EXISTS ${FerreteriaContract.PedidoEntry.TABLE_NAME} (" +
"${FerreteriaContract.PedidoEntry.COLUMN_NAME_CODIGO} INTEGER PRIMARY KEY AUTOINCREMENT," +
"${FerreteriaContract.PedidoEntry.COLUMN_NAME_DESCRIPCION} TEXT,"+
"${FerreteriaContract.PedidoEntry.COLUMN_NAME_FECHA} DATE,"+
"${FerreteriaContract.PedidoEntry.COLUMN_NAME_COD_CLIENTE} INTEGER, "+
"FOREIGN KEY (${FerreteriaContract.PedidoEntry.COLUMN_NAME_COD_CLIENTE}) "+
"REFERENCES ${FerreteriaContract.ClienteEntry.TABLE_NAME} " +
" (${FerreteriaContract.ClienteEntry.COLUMN_NAME_CODIGO}))"


private const val FACTURAS_SQL_CREATE_ENTRIES =
"CREATE TABLE IF NOT EXISTS ${FerreteriaContract.FacturaEntry.TABLE_NAME} (" +
"${FerreteriaContract.FacturaEntry.COLUMN_NAME_CODIGO} INTEGER PRIMARY KEY AUTOINCREMENT," +
"${FerreteriaContract.FacturaEntry.COLUMN_NAME_FECHA} DATE,"+
"${FerreteriaContract.FacturaEntry.COLUMN_NAME_VALOR} DECIMAL,"+
"${FerreteriaContract.FacturaEntry.COLUMN_NAME_COD_PEDIDO} INTEGER, "+
"FOREIGN KEY (${FerreteriaContract.FacturaEntry.COLUMN_NAME_COD_PEDIDO}) " +
"REFERENCES ${FerreteriaContract.PedidoEntry.TABLE_NAME} " +
"(${FerreteriaContract.PedidoEntry.COLUMN_NAME_CODIGO}));"

Conexión de bases de datos en dispositivos móviles

 Esto se realiza a través de la creación de una clase que implemente

class FerreteriaDBHelper(context: Context) : 
SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) {
override fun onCreate(db: SQLiteDatabase)
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int)


y luego en la actividad donde se requiera se llama a

val dbHelper = FerreteriaDBHelper(this)

Implementación de métodos

 fun insertar (view: View){


val vdocumento = documento.text.toString();
val vnombre = nombre.text.toString();
val vtelefono = telefono.text.toString();
val vdireccion = direccion.text.toString();

if(vdocumento.isNotBlank() && vdocumento.isNotEmpty()
&& vnombre.isNotBlank() && vnombre.isNotEmpty()
&& vtelefono.isNotBlank() && vtelefono.isNotEmpty()
&& vdireccion.isNotBlank() && vdireccion.isNotEmpty()
){
val db = dbHelper.writableDatabase

var values = ContentValues().apply {
put(FerreteriaContract.ClienteEntry.COLUMN_NAME_CODIGO, vdocumento)
put(FerreteriaContract.ClienteEntry.COLUMN_NAME_NOMBRE, vnombre)
put(FerreteriaContract.ClienteEntry.COLUMN_NAME_DIRECCION, vdireccion)
put(FerreteriaContract.ClienteEntry.COLUMN_NAME_TELEFONO, vtelefono)
}

val newRowId = db?.insert(FerreteriaContract.ClienteEntry.TABLE_NAME, null, values)
db.close()

if (newRowId == null) {
Toast.makeText(this, "No se creo el registro", Toast.LENGTH_LONG).show();
}


documento.text = ""
nombre.text= ""
telefono.text= ""
direccion.text = ""
Toast.makeText(this, "Nuevo cleinte creado exitosamente", Toast.LENGTH_LONG).show();

} else {
Toast.makeText(this, "Todos los campos son obligaotrios", Toast.LENGTH_LONG).show();
}
}

fun buscar(view: View){

val vdocumento = documento.text.toString();

if(vdocumento.isNotBlank() && vdocumento.isNotEmpty()) {
val db = dbHelper.readableDatabase
var cursor = db.query(
FerreteriaContract.ClienteEntry.TABLE_NAME,
null,
FerreteriaContract.ClienteEntry.COLUMN_NAME_CODIGO + "=" + vdocumento,
null,
null,
null,
null
)


if (cursor.moveToNext()) {
nombre.text =
cursor.getString(cursor.getColumnIndexOrThrow(FerreteriaContract.ClienteEntry.COLUMN_NAME_NOMBRE))
telefono.text =
cursor.getString(cursor.getColumnIndexOrThrow(FerreteriaContract.ClienteEntry.COLUMN_NAME_TELEFONO))
direccion.text =
cursor.getString(cursor.getColumnIndexOrThrow(FerreteriaContract.ClienteEntry.COLUMN_NAME_DIRECCION))
} else {
Toast.makeText(this, "No se encontro el usuario", Toast.LENGTH_LONG).show();
}
cursor.close()
db.close()
}else{
Toast.makeText(this, "el documento es requierido", Toast.LENGTH_LONG).show();
}
}

fun actualizar(view: View){

val vdocumento = documento.text.toString();
val vnombre = nombre.text.toString();
val vtelefono = telefono.text.toString();
val vdireccion = direccion.text.toString();

if(vdocumento.isNotBlank() && vdocumento.isNotEmpty()
&& vnombre.isNotBlank() && vnombre.isNotEmpty()
&& vtelefono.isNotBlank() && vtelefono.isNotEmpty()
&& vdireccion.isNotBlank() && vdireccion.isNotEmpty()
){
val db = dbHelper.writableDatabase
var values = ContentValues().apply {
put(FerreteriaContract.ClienteEntry.COLUMN_NAME_CODIGO, vdocumento)
put(FerreteriaContract.ClienteEntry.COLUMN_NAME_NOMBRE, vnombre)
put(FerreteriaContract.ClienteEntry.COLUMN_NAME_DIRECCION, vdireccion)
put(FerreteriaContract.ClienteEntry.COLUMN_NAME_TELEFONO, vtelefono)
}

val newRowId = db?.update(FerreteriaContract.ClienteEntry.TABLE_NAME, values,FerreteriaContract.ClienteEntry.COLUMN_NAME_CODIGO+"="+vdocumento,null )
db.close()

if(newRowId != 1){
Toast.makeText(this,"La persona no existe",Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this,"Persona modificada correctamente",Toast.LENGTH_LONG).show();
}


} else {
Toast.makeText(this, "Todos los campos son obligatorios", Toast.LENGTH_LONG).show();
}

}


fun borrar(view: View){

val vdocumento = documento.text.toString();

if(vdocumento.isNotBlank() && vdocumento.isNotEmpty()) {
val db = dbHelper.writableDatabase

val newRowId = db?.delete(FerreteriaContract.ClienteEntry.TABLE_NAME,FerreteriaContract.ClienteEntry.COLUMN_NAME_CODIGO+"="+vdocumento,null)
db.close()
documento.text = ""
nombre.text= ""
telefono.text= ""
direccion.text = ""

if ( newRowId != 0 ){
Toast.makeText(this,"Se ha eliminado un registro",Toast.LENGTH_LONG).show();
}

} else {
Toast.makeText(this, "el documento es requierido", Toast.LENGTH_LONG).show();

}

martes, 16 de mayo de 2023

Gestión de información por medio de bases de datos

Una base de datos local, como SQLlite, permite que aplicaciones sean más receptivas y menos dependientes de la conectividad de la red.

Son importante para el manejo de una cantidad de datos intermedia, que no quepan en el SharedPreferences pero si se requiere mayor cantidad de memoria hará falta recurrir a una base de datos que este alojada en un servidor  y de conexión a internet.

Mas allá de la cantidad de datos o el SGDB que se utilice, una base de datos nos permite almacenar la información que deseemos y mantenerla actualizada. Para el caso de los dispositivos móviles, la información guardada locamente es importante para indicar preferencias del usuario o guardar información particular que sea solo del usuario del dispositivo.

Ventajas de SQLite

 Es estable, multiplataforma y compatible con versiones anteriores y su código es de dominio público y gratuito.

Esto se debe a que funciona de forma independiente y que esta basado en archivos, por lo tanto no necesita un servidor. 

Como no necesita un servidor, no requiere instalación o configuración, pero Mantiene sintaxis SQL estándar con pequeñas modificaciones, lo que facilita su uso.

Es portátil, ya que al estar basado en archivos no permite almacenar grandes cantidades de información aunque no tiene incompatibilidades con los tiempos de datos

Casos en los que se recomienda el almacenamiento a través de la clase Sharedpreferences.

Cuando tenemos que almacenar una cantidad limitada de datos

Cuando lo datos que vamos a guardar son primitivos

Cuando queremos que los datos se mantengan hasta que se desinstala la aplicación.

Desventajas del trabajo con vectores.

Tienen un tamaño fijo que se determina en el momento de la creación. Esto significa que si es necesario aumentar el tamaño, se debe crear una nueva y copiar los datos de la anterior a la nueva, lo que puede consumir mucho tiempo y memoria.

La inserción o eliminación de un elemento puede ser ineficiente y llevar mucho tiempo porque todos los elementos después del punto de inserción o eliminación deben cambiarse para acomodar el cambio.

El tamaño fijo y el soporte limitado para tipos de datos complejos pueden hacer que las matrices sean inflexibles en comparación con otras estructuras de datos.

Ventajas del trabajo con vectores

Son Fácil de implementar,

Los arreglos permiten el acceso directo y eficiente a cualquier elemento..

Se pueden usar para almacenar una diferentes de tipos de datos como: números enteros, números de coma flotante, caracteres e incluso estructuras de datos complejas, como objetos.

Creación de relaciones entre tablas

 Solo puse claves foraneas en las tablas pedidos (para referencias al cliente y a los prodcutos) y en factura (para referenciar a pedidos qu...