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

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...