|
@@ -3,10 +3,13 @@ import 'package:intl/intl.dart';
|
|
|
import 'package:path/path.dart';
|
|
|
import 'package:path_provider/path_provider.dart';
|
|
|
import 'package:sqflite/sqflite.dart';
|
|
|
+import '../data/api_response.dart';
|
|
|
import '../models/models.dart';
|
|
|
+import '../views/producto/producto_imagen.dart';
|
|
|
+import 'base_service.dart';
|
|
|
|
|
|
class RepoService<T> {
|
|
|
- static int dbVersion = 14;
|
|
|
+ static int dbVersion = 23;
|
|
|
static String dbName = 'conalepPos7.db';
|
|
|
static const String id = Basico.identificadorWeb;
|
|
|
static const String idLocal = Basico.identificadorLocal;
|
|
@@ -117,6 +120,33 @@ class RepoService<T> {
|
|
|
eliminado TEXT
|
|
|
)
|
|
|
''');
|
|
|
+
|
|
|
+ await db.insert('Variable', {
|
|
|
+ 'nombre': 'Imprimir Ticket Cocina',
|
|
|
+ 'clave': 'ticket_cocina',
|
|
|
+ 'descripcion':
|
|
|
+ 'Variable para imprimir ticket de cocina automaticamente al momento de generar un pedido',
|
|
|
+ 'activo': 1,
|
|
|
+ 'idLocal': -1,
|
|
|
+ });
|
|
|
+
|
|
|
+ await db.insert('Variable', {
|
|
|
+ 'nombre': 'Imprimir Ticket Venta',
|
|
|
+ 'clave': 'ticket_venta',
|
|
|
+ 'descripcion':
|
|
|
+ 'Variable para imprimir ticket de venta automaticamente al momento de generar un pedido',
|
|
|
+ 'activo': 0,
|
|
|
+ 'idLocal': -1,
|
|
|
+ });
|
|
|
+
|
|
|
+ await db.insert('Variable', {
|
|
|
+ 'nombre': 'Imprimir ticket PC/Tablet',
|
|
|
+ 'clave': 'ticket_pc',
|
|
|
+ 'descripcion':
|
|
|
+ 'Al estar activo imprime ticket para pc, el estar desactivado imprime ticket para tablet',
|
|
|
+ 'activo': 1,
|
|
|
+ 'idLocal': -1,
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
/// Actualiza la version de la base de datos
|
|
@@ -125,13 +155,13 @@ class RepoService<T> {
|
|
|
switch (oldVersion) {
|
|
|
case 1:
|
|
|
await db.execute(
|
|
|
- "ALTER TABLE CategoriaProducto ADD COLUMN IF NOT EXISTS esToping INTEGER DEFAULT 0");
|
|
|
+ "ALTER TABLE CategoriaProducto ADD COLUMN esToping INTEGER DEFAULT 0");
|
|
|
|
|
|
await db.execute(
|
|
|
- "ALTER TABLE CategoriaProducto ADD COLUMN IF NOT EXISTS descripcion TEXT DEFAULT ''");
|
|
|
+ "ALTER TABLE CategoriaProducto ADD COLUMN descripcion TEXT DEFAULT ''");
|
|
|
|
|
|
await db.execute(
|
|
|
- "ALTER TABLE CategoriaProducto ADD COLUMN IF NOT EXISTS maximo INTEGER");
|
|
|
+ "ALTER TABLE CategoriaProducto ADD COLUMN maximo INTEGER");
|
|
|
|
|
|
break;
|
|
|
|
|
@@ -184,16 +214,16 @@ class RepoService<T> {
|
|
|
|
|
|
case 6:
|
|
|
await db.execute('''
|
|
|
- ALTER TABLE Pedido ADD COLUMN IF NOT EXISTS tipoPago TEXT DEFAULT '';
|
|
|
+ ALTER TABLE Pedido ADD COLUMN tipoPago TEXT DEFAULT '';
|
|
|
''');
|
|
|
await db.execute('''
|
|
|
- ALTER TABLE Pedido ADD COLUMN IF NOT EXISTS cantEfectivo REAL DEFAULT 0;
|
|
|
+ ALTER TABLE Pedido ADD COLUMN cantEfectivo REAL DEFAULT 0;
|
|
|
''');
|
|
|
await db.execute('''
|
|
|
- ALTER TABLE Pedido ADD COLUMN IF NOT EXISTS cantTarjeta REAL DEFAULT 0;
|
|
|
+ ALTER TABLE Pedido ADD COLUMN cantTarjeta REAL DEFAULT 0;
|
|
|
''');
|
|
|
await db.execute('''
|
|
|
- ALTER TABLE Pedido ADD COLUMN IF NOT EXISTS cantTransferencia REAL DEFAULT 0;
|
|
|
+ ALTER TABLE Pedido ADD COLUMN cantTransferencia REAL DEFAULT 0;
|
|
|
''');
|
|
|
break;
|
|
|
|
|
@@ -213,7 +243,7 @@ class RepoService<T> {
|
|
|
|
|
|
case 8:
|
|
|
await db.execute('''
|
|
|
- ALTER TABLE Producto ADD COLUMN IF NOT EXISTS toping INTEGER DEFAULT 0;
|
|
|
+ ALTER TABLE Producto ADD COLUMN toping INTEGER DEFAULT 0;
|
|
|
''');
|
|
|
break;
|
|
|
|
|
@@ -310,6 +340,249 @@ class RepoService<T> {
|
|
|
''');
|
|
|
|
|
|
break;
|
|
|
+
|
|
|
+ case 14:
|
|
|
+ await db.execute('''
|
|
|
+ ALTER TABLE Producto ADD COLUMN activo INTEGER;
|
|
|
+ ''');
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 16:
|
|
|
+ await db.execute('''
|
|
|
+ ALTER TABLE ProductoTopping ADD COLUMN idCategoria INTEGER;
|
|
|
+ ''');
|
|
|
+ await db.execute('''
|
|
|
+ ALTER TABLE ProductoTopping ADD COLUMN creado text;
|
|
|
+ ''');
|
|
|
+ await db.execute('''
|
|
|
+ ALTER TABLE ProductoTopping ADD COLUMN modificado text;
|
|
|
+ ''');
|
|
|
+ await db.execute('''
|
|
|
+ ALTER TABLE ProductoTopping ADD COLUMN eliminado text;
|
|
|
+ ''');
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 17:
|
|
|
+ await db.execute('''
|
|
|
+ CREATE TABLE Sucursal (
|
|
|
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
|
+ nombre TEXT,
|
|
|
+ descripcion TEXT,
|
|
|
+ direccion TEXT,
|
|
|
+ ciudad TEXT,
|
|
|
+ activo INTEGER,
|
|
|
+ clave TEXT,
|
|
|
+ eliminado TEXT,
|
|
|
+ creado TEXT,
|
|
|
+ modificado TEXT,
|
|
|
+ idLocal INTEGER,
|
|
|
+ seleccionado INTEGER
|
|
|
+ )
|
|
|
+ ''');
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 18:
|
|
|
+ await db.execute('''
|
|
|
+ CREATE TABLE Usuario (
|
|
|
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
|
+ nombre TEXT,
|
|
|
+ apellidos TEXT,
|
|
|
+ correo TEXT,
|
|
|
+ celular TEXT,
|
|
|
+ celularPersonal TEXT,
|
|
|
+ rol INTEGER,
|
|
|
+ genero BOOLEAN,
|
|
|
+ estatus INTEGER,
|
|
|
+ imagen TEXT,
|
|
|
+ rfc TEXT,
|
|
|
+ razonSocial TEXT,
|
|
|
+ calle TEXT,
|
|
|
+ numeroExterior TEXT,
|
|
|
+ colonia TEXT,
|
|
|
+ codigoPostal TEXT,
|
|
|
+ idCiudad INTEGER,
|
|
|
+ idEstado INTEGER,
|
|
|
+ idSucursal INTEGER,
|
|
|
+ turno TEXT,
|
|
|
+ eliminado TEXT,
|
|
|
+ creado TEXT,
|
|
|
+ modificado TEXT,
|
|
|
+ idLocal INTEGER
|
|
|
+ )
|
|
|
+ ''');
|
|
|
+
|
|
|
+ await db.execute('''
|
|
|
+ CREATE TABLE Permiso (
|
|
|
+ id TEXT PRIMARY KEY,
|
|
|
+ idModulo TEXT,
|
|
|
+ nombre TEXT,
|
|
|
+ descripcion TEXT,
|
|
|
+ eliminado TEXT,
|
|
|
+ creado TEXT,
|
|
|
+ modificado TEXT
|
|
|
+ )
|
|
|
+ ''');
|
|
|
+
|
|
|
+ await db.execute('''
|
|
|
+ CREATE TABLE UsuarioPermiso (
|
|
|
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
|
+ idUsuario INTEGER,
|
|
|
+ idPermiso TEXT,
|
|
|
+ asignado TEXT,
|
|
|
+ modificado TEXT,
|
|
|
+ eliminado TEXT,
|
|
|
+ idLocal INTEGER
|
|
|
+ )
|
|
|
+ ''');
|
|
|
+
|
|
|
+ await db.execute('''
|
|
|
+ ALTER TABLE ProductoTopping ADD COLUMN idLocal INTEGER;
|
|
|
+ ''');
|
|
|
+
|
|
|
+ await db.execute('''
|
|
|
+ ALTER TABLE PedidoProductoTopping ADD COLUMN idLocal INTEGER;
|
|
|
+ ''');
|
|
|
+
|
|
|
+ await db.execute('''
|
|
|
+ ALTER TABLE PedidoProductoTopping ADD COLUMN idCategoria INTEGER;
|
|
|
+ ''');
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 19:
|
|
|
+ await db.execute('''
|
|
|
+ ALTER TABLE CategoriaProducto ADD COLUMN minimo INTEGER;
|
|
|
+ ''');
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 20:
|
|
|
+ await db.execute('''
|
|
|
+ ALTER TABLE Usuario ADD COLUMN clave TEXT;
|
|
|
+ ''');
|
|
|
+
|
|
|
+ await db.insert('Variable', {
|
|
|
+ 'nombre': 'Imprimir ticket PC/Tablet',
|
|
|
+ 'clave': 'ticket_pc',
|
|
|
+ 'descripcion':
|
|
|
+ 'Al estar activo imprime ticket para pc, el estar desactivado imprime ticket para tablet',
|
|
|
+ 'activo': 1,
|
|
|
+ 'idLocal': -1,
|
|
|
+ });
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 21:
|
|
|
+ await db.execute('DROP TABLE CorteCaja');
|
|
|
+ await db.execute('DROP TABLE Deposito');
|
|
|
+ await db.execute('DROP TABLE Gasto');
|
|
|
+
|
|
|
+ await db.execute('''
|
|
|
+ CREATE TABLE CorteCaja (
|
|
|
+ id TEXT PRIMARY KEY,
|
|
|
+ fechaApertura TEXT,
|
|
|
+ fechaCorte TEXT,
|
|
|
+ idUsuario INTEGER,
|
|
|
+ idSucursal INTEGER,
|
|
|
+ fondo REAL,
|
|
|
+ fondoDiaSig REAL,
|
|
|
+ ventaPuntos REAL,
|
|
|
+ ventaEfe REAL,
|
|
|
+ ventaTrans REAL,
|
|
|
+ ventaTarj REAL,
|
|
|
+ gasto REAL,
|
|
|
+ retiro REAL,
|
|
|
+ corteFinal REAL,
|
|
|
+ creado TEXT,
|
|
|
+ modificado TEXT,
|
|
|
+ eliminado TEXT
|
|
|
+ )
|
|
|
+ ''');
|
|
|
+
|
|
|
+ await db.execute('''
|
|
|
+ CREATE TABLE Deposito (
|
|
|
+ id TEXT PRIMARY KEY,
|
|
|
+ idCorteCaja TEXT,
|
|
|
+ idSucursal INTEGER,
|
|
|
+ idUsuario INTEGER,
|
|
|
+ fechaDeposito TEXT,
|
|
|
+ monto REAL,
|
|
|
+ persona TEXT,
|
|
|
+ descripcion TEXT,
|
|
|
+ creado TEXT,
|
|
|
+ modificado TEXT,
|
|
|
+ eliminado TEXT
|
|
|
+ )
|
|
|
+ ''');
|
|
|
+
|
|
|
+ await db.execute('''
|
|
|
+ CREATE TABLE Retiro (
|
|
|
+ id TEXT PRIMARY KEY,
|
|
|
+ idCorteCaja TEXT,
|
|
|
+ idSucursal INTEGER,
|
|
|
+ idUsuario INTEGER,
|
|
|
+ fechaRetiro TEXT,
|
|
|
+ monto REAL,
|
|
|
+ persona TEXT,
|
|
|
+ descripcion TEXT,
|
|
|
+ creado TEXT,
|
|
|
+ modificado TEXT,
|
|
|
+ eliminado TEXT
|
|
|
+ )
|
|
|
+ ''');
|
|
|
+
|
|
|
+ await db.execute('''
|
|
|
+ CREATE TABLE Gasto (
|
|
|
+ id TEXT PRIMARY KEY,
|
|
|
+ idCorteCaja TEXT,
|
|
|
+ idSucursal INTEGER,
|
|
|
+ idUsuario INTEGER,
|
|
|
+ fechaGasto TEXT,
|
|
|
+ monto REAL,
|
|
|
+ persona TEXT,
|
|
|
+ descripcion TEXT,
|
|
|
+ creado TEXT,
|
|
|
+ modificado TEXT,
|
|
|
+ eliminado TEXT
|
|
|
+ )
|
|
|
+ ''');
|
|
|
+
|
|
|
+ await db.execute('''
|
|
|
+ update Pedido set sincronizado = null where estatus = 'CANCELADO'
|
|
|
+ ''');
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 22:
|
|
|
+ await db.execute('''
|
|
|
+ ALTER TABLE CorteCaja ADD COLUMN deposito REAL;
|
|
|
+ ''');
|
|
|
+ await db.execute('''
|
|
|
+ ALTER TABLE CorteCaja ADD COLUMN idWeb TEXT;
|
|
|
+ ''');
|
|
|
+ await db.execute('''
|
|
|
+ ALTER TABLE CorteCaja ADD COLUMN sincronizado TEXT;
|
|
|
+ ''');
|
|
|
+ await db.execute('''
|
|
|
+ ALTER TABLE Gasto ADD COLUMN idWeb TEXT;
|
|
|
+ ''');
|
|
|
+ await db.execute('''
|
|
|
+ ALTER TABLE Gasto ADD COLUMN sincronizado TEXT;
|
|
|
+ ''');
|
|
|
+ await db.execute('''
|
|
|
+ ALTER TABLE Retiro ADD COLUMN idWeb TEXT;
|
|
|
+ ''');
|
|
|
+ await db.execute('''
|
|
|
+ ALTER TABLE Retiro ADD COLUMN sincronizado TEXT;
|
|
|
+ ''');
|
|
|
+ await db.execute('''
|
|
|
+ ALTER TABLE Deposito ADD COLUMN idWeb TEXT;
|
|
|
+ ''');
|
|
|
+ await db.execute('''
|
|
|
+ ALTER TABLE Deposito ADD COLUMN sincronizado TEXT;
|
|
|
+ ''');
|
|
|
}
|
|
|
oldVersion++;
|
|
|
}
|
|
@@ -317,47 +590,85 @@ class RepoService<T> {
|
|
|
|
|
|
Future<int> guardar(T model) async {
|
|
|
try {
|
|
|
- print("Guardando modelo en la base de datos: ${model.runtimeType}");
|
|
|
-
|
|
|
+ // Convert the model to JSON for the database
|
|
|
String modelo = json.encode(model, toEncodable: toEncodable);
|
|
|
- print("Modelo convertido a JSON: $modelo");
|
|
|
-
|
|
|
Map<String, dynamic> modelMap = json.decode(modelo);
|
|
|
var dbClient = await db;
|
|
|
String nombreTabla = model.runtimeType.toString();
|
|
|
|
|
|
- // Verificar si el modelo tiene ID asignado
|
|
|
- int? id = modelMap['id'];
|
|
|
-
|
|
|
- // Eliminar el campo 'id' si es 0 o null para permitir autoincremento
|
|
|
- if (id == null || id == 0) {
|
|
|
- modelMap.remove('id');
|
|
|
- }
|
|
|
+ // Check if the model has a String ID or an int ID
|
|
|
+ dynamic id = modelMap['id'];
|
|
|
+ bool isStringId = id is String;
|
|
|
+ bool isIntId = id is int;
|
|
|
|
|
|
- List<Map> existing = id != null && id > 0
|
|
|
- ? await dbClient!.query(nombreTabla, where: 'id = ?', whereArgs: [id])
|
|
|
- : [];
|
|
|
+ // If id is of type String (e.g., Permiso)
|
|
|
+ if (isStringId) {
|
|
|
+ if (id == null || (id as String).isEmpty) {
|
|
|
+ throw Exception('El ID del modelo no puede ser nulo o vacío');
|
|
|
+ }
|
|
|
|
|
|
- if (existing.isNotEmpty) {
|
|
|
- print("Actualizando registro existente con ID: $id");
|
|
|
- await dbClient!.update(
|
|
|
+ // Check for existing record with the String ID
|
|
|
+ List<Map> existing = await dbClient!.query(
|
|
|
nombreTabla,
|
|
|
- modelMap,
|
|
|
where: 'id = ?',
|
|
|
whereArgs: [id],
|
|
|
);
|
|
|
+
|
|
|
+ if (existing.isNotEmpty) {
|
|
|
+ await dbClient.update(
|
|
|
+ nombreTabla,
|
|
|
+ modelMap,
|
|
|
+ where: 'id = ?',
|
|
|
+ whereArgs: [id],
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ print(
|
|
|
+ "Insertando nuevo registro en la tabla $nombreTabla con ID: $id");
|
|
|
+ await dbClient.insert(nombreTabla, modelMap);
|
|
|
+ }
|
|
|
+ return 1;
|
|
|
+ } else if (isIntId) {
|
|
|
+ // If id is of type int (e.g., other models)
|
|
|
+ if (id == null || id == 0) {
|
|
|
+ modelMap
|
|
|
+ .remove('id'); // Remove id if it's null or 0 for auto-increment
|
|
|
+ }
|
|
|
+
|
|
|
+ List<Map> existing = (id != null && id > 0)
|
|
|
+ ? await dbClient!
|
|
|
+ .query(nombreTabla, where: 'id = ?', whereArgs: [id])
|
|
|
+ : [];
|
|
|
+
|
|
|
+ if (existing.isNotEmpty) {
|
|
|
+ print("Actualizando registro existente con ID: $id");
|
|
|
+ await dbClient!.update(
|
|
|
+ nombreTabla,
|
|
|
+ modelMap,
|
|
|
+ where: 'id = ?',
|
|
|
+ whereArgs: [id],
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ print("Insertando nuevo registro en la tabla $nombreTabla");
|
|
|
+ id = await dbClient!.insert(nombreTabla, modelMap);
|
|
|
+ }
|
|
|
+ return id as int;
|
|
|
} else {
|
|
|
- print("Insertando nuevo registro en la tabla $nombreTabla");
|
|
|
- id = await dbClient!.insert(nombreTabla, modelMap);
|
|
|
+ throw Exception('Tipo de ID no soportado');
|
|
|
}
|
|
|
-
|
|
|
- return id!;
|
|
|
} catch (e) {
|
|
|
print('Error al guardar en dynamic: $e');
|
|
|
return 0;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ void asignarFechasLocalmente(Basico model) {
|
|
|
+ DateTime ahora = DateTime.now();
|
|
|
+ if (model.creado == null) {
|
|
|
+ model.creado = ahora.toUtc();
|
|
|
+ }
|
|
|
+ model.modificado = ahora.toUtc();
|
|
|
+ }
|
|
|
+
|
|
|
Future<void> _guardarToppings(
|
|
|
Database db, int idProducto, List<Producto>? topings) async {
|
|
|
await db.delete('ProductoTopping',
|
|
@@ -420,23 +731,7 @@ class RepoService<T> {
|
|
|
}
|
|
|
|
|
|
dynamic toEncodable(dynamic item) {
|
|
|
- if (item is Pedido) {
|
|
|
- return item.toJson();
|
|
|
- } else if (item is PedidoProducto) {
|
|
|
- return item.toJson();
|
|
|
- } else if (item is PedidoProductoTopping) {
|
|
|
- return item.toJson();
|
|
|
- } else if (item is Producto) {
|
|
|
- print("Convirtiendo Producto a JSON para guardar");
|
|
|
- return item.toJson();
|
|
|
- } else if (item is CategoriaProducto) {
|
|
|
- print("Convirtiendo CategoriaProducto a JSON para guardar");
|
|
|
- return item.toJson();
|
|
|
- } else if (item is Variable) {
|
|
|
- return item.toJson();
|
|
|
- }
|
|
|
- throw UnsupportedError(
|
|
|
- 'Type not supported for serialization: ${item.runtimeType}');
|
|
|
+ return item.toJson();
|
|
|
}
|
|
|
|
|
|
Future<List<T>> obtenerTodos({String orderBy = 'id DESC'}) async {
|
|
@@ -453,6 +748,10 @@ class RepoService<T> {
|
|
|
return Pedido.fromJson(map) as T;
|
|
|
case Producto:
|
|
|
return Producto.fromJson(map) as T;
|
|
|
+ case Usuario:
|
|
|
+ return Usuario.fromJson(map) as T;
|
|
|
+ case CorteCaja:
|
|
|
+ return CorteCaja.fromJson(map) as T;
|
|
|
default:
|
|
|
throw Exception('Tipo no soportado');
|
|
|
}
|
|
@@ -477,21 +776,34 @@ class RepoService<T> {
|
|
|
.toList();
|
|
|
}
|
|
|
|
|
|
- Future<List<Deposito>> obtenerDepositosPorIdCorteCaja(int idCorteCaja) async {
|
|
|
+ //CORTE CAJA
|
|
|
+
|
|
|
+ Future<List<Deposito>> obtenerDepositosPorIdCorteCaja(
|
|
|
+ String idCorteCaja) async {
|
|
|
var dbClient = await db;
|
|
|
List<Map<String, dynamic>> maps = await dbClient!.query(
|
|
|
'Deposito',
|
|
|
- where: 'idCorteCaja = ?',
|
|
|
+ where: 'idCorteCaja = ? AND eliminado IS NULL',
|
|
|
whereArgs: [idCorteCaja],
|
|
|
);
|
|
|
return maps.map((map) => Deposito.fromJson(map)).toList();
|
|
|
}
|
|
|
|
|
|
- Future<List<Gasto>> obtenerGastosPorIdCorteCaja(int idCorteCaja) async {
|
|
|
+ Future<List<Retiro>> obtenerRetirosPorIdCorteCaja(String idCorteCaja) async {
|
|
|
+ var dbClient = await db;
|
|
|
+ List<Map<String, dynamic>> maps = await dbClient!.query(
|
|
|
+ 'Retiro',
|
|
|
+ where: 'idCorteCaja = ? AND eliminado IS NULL',
|
|
|
+ whereArgs: [idCorteCaja],
|
|
|
+ );
|
|
|
+ return maps.map((map) => Retiro.fromJson(map)).toList();
|
|
|
+ }
|
|
|
+
|
|
|
+ Future<List<Gasto>> obtenerGastosPorIdCorteCaja(String idCorteCaja) async {
|
|
|
var dbClient = await db;
|
|
|
List<Map<String, dynamic>> maps = await dbClient!.query(
|
|
|
'Gasto',
|
|
|
- where: 'idCorteCaja = ?',
|
|
|
+ where: 'idCorteCaja = ? AND eliminado IS NULL',
|
|
|
whereArgs: [idCorteCaja],
|
|
|
);
|
|
|
return maps.map((map) => Gasto.fromJson(map)).toList();
|
|
@@ -503,6 +815,21 @@ class RepoService<T> {
|
|
|
return Sqflite.firstIntValue(result) ?? 0;
|
|
|
}
|
|
|
|
|
|
+ Future<double?> obtenerFondoDiaSigDelUltimoCorte() async {
|
|
|
+ var dbClient = await db;
|
|
|
+ List<Map<String, dynamic>> result = await dbClient!.query(
|
|
|
+ 'CorteCaja',
|
|
|
+ orderBy: 'fechaApertura DESC',
|
|
|
+ limit: 1,
|
|
|
+ );
|
|
|
+
|
|
|
+ if (result.isNotEmpty) {
|
|
|
+ return result.first['fondoDiaSig'] as double?;
|
|
|
+ }
|
|
|
+
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
Future<List<Pedido>> obtenerPedidosPaginados(int limit, int offset) async {
|
|
|
Database? dbClient = await db;
|
|
|
List<Map<String, dynamic>> result = await dbClient!
|
|
@@ -661,8 +988,8 @@ class RepoService<T> {
|
|
|
return result.map((map) => Pedido.fromJson(map)).toList();
|
|
|
}
|
|
|
|
|
|
- Future<void> sincronizarCategorias(
|
|
|
- List<CategoriaProducto> categoriasApi) async {
|
|
|
+ Future<void> sincronizarCategorias(List<CategoriaProducto> categoriasApi,
|
|
|
+ {bool forzar = false}) async {
|
|
|
var db = await RepoService().db;
|
|
|
|
|
|
var categoriasLocalesQuery = await db!.query('CategoriaProducto');
|
|
@@ -676,10 +1003,12 @@ class RepoService<T> {
|
|
|
orElse: () => CategoriaProducto(),
|
|
|
);
|
|
|
|
|
|
- if (categoriaLocal.id != 0 &&
|
|
|
- categoriaApi.modificado != null &&
|
|
|
- categoriaLocal.modificado != null &&
|
|
|
- categoriaApi.modificado!.isAfter(categoriaLocal.modificado!)) {
|
|
|
+ if (forzar ||
|
|
|
+ categoriaLocal.id != 0 &&
|
|
|
+ categoriaApi.modificado != null &&
|
|
|
+ (categoriaLocal.modificado == null ||
|
|
|
+ categoriaApi.modificado!
|
|
|
+ .isAfter(categoriaLocal.modificado!))) {
|
|
|
await RepoService().guardar(categoriaApi);
|
|
|
} else if (categoriaLocal.id == 0) {
|
|
|
await RepoService().guardar(categoriaApi);
|
|
@@ -687,27 +1016,372 @@ class RepoService<T> {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- Future<void> sincronizarProductos(List<Producto> productosApi) async {
|
|
|
+ Future<void> sincronizarProductos(List<Producto> productosApi,
|
|
|
+ {bool forzar = false}) async {
|
|
|
var db = await RepoService().db;
|
|
|
|
|
|
+ // // Print del JSON recibido
|
|
|
+ // print(
|
|
|
+ // "Productos API recibidos: ${productosApi.map((e) => e.toJson()).toList()}");
|
|
|
+
|
|
|
var productosLocalesQuery = await db!.query('Producto');
|
|
|
List<Producto> productosLocales =
|
|
|
productosLocalesQuery.map((e) => Producto.fromJson(e)).toList();
|
|
|
|
|
|
for (var productoApi in productosApi) {
|
|
|
+ // Validar que el ID del producto no sea nulo
|
|
|
+ if (productoApi.id == null) {
|
|
|
+ print("Producto con ID nulo, se omite: ${productoApi.nombre}");
|
|
|
+ continue; // Ignorar productos sin ID
|
|
|
+ }
|
|
|
+
|
|
|
+ // Buscar el producto localmente
|
|
|
var productoLocal = productosLocales.firstWhere(
|
|
|
(producto) => producto.id == productoApi.id,
|
|
|
- orElse: () => Producto(),
|
|
|
+ orElse: () =>
|
|
|
+ Producto(), // Si no existe el producto, devolver uno nuevo con id 0
|
|
|
);
|
|
|
|
|
|
- if (productoLocal.id != 0 &&
|
|
|
- productoApi.modificado != null &&
|
|
|
- productoLocal.modificado != null &&
|
|
|
- productoApi.modificado!.isAfter(productoLocal.modificado!)) {
|
|
|
+ if (productoLocal.id == 0) {
|
|
|
+ print("Insertando nuevo producto: ${productoApi.nombre}");
|
|
|
await RepoService().guardar(productoApi);
|
|
|
- } else if (productoLocal.id == 0) {
|
|
|
+ } else if (forzar ||
|
|
|
+ productoApi.modificado != null &&
|
|
|
+ (productoLocal.modificado == null ||
|
|
|
+ productoApi.modificado!.isAfter(productoLocal.modificado!))) {
|
|
|
+ print("Actualizando producto: ${productoApi.nombre}");
|
|
|
await RepoService().guardar(productoApi);
|
|
|
+ } else {
|
|
|
+ // Producto sin cambios
|
|
|
+ // print(
|
|
|
+ // "Producto sin cambios o datos insuficientes: ${productoApi.nombre}");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Future<void> sincronizarProductoTopping(
|
|
|
+ List<ProductoTopping> toppingsApi) async {
|
|
|
+ var db = await RepoService().db;
|
|
|
+
|
|
|
+ await db!.delete('ProductoTopping');
|
|
|
+
|
|
|
+ for (var toppingApi in toppingsApi) {
|
|
|
+ await RepoService().guardar(toppingApi);
|
|
|
+ }
|
|
|
+
|
|
|
+ print("Todos los registros de ProductoTopping han sido sincronizados.");
|
|
|
+ }
|
|
|
+
|
|
|
+ Future<void> sincronizarSucursales(List<Sucursal> sucursalesApi,
|
|
|
+ {bool forzar = false}) async {
|
|
|
+ var db = await RepoService().db;
|
|
|
+
|
|
|
+ int? idSucursalSeleccionada = await obtenerIdSucursalSeleccionada();
|
|
|
+
|
|
|
+ var sucursalesLocalesQuery = await db!.query('Sucursal');
|
|
|
+ List<Sucursal> sucursalesLocales =
|
|
|
+ sucursalesLocalesQuery.map((e) => Sucursal.fromJson(e)).toList();
|
|
|
+
|
|
|
+ for (var sucursalApi in sucursalesApi) {
|
|
|
+ var sucursalLocal = sucursalesLocales.firstWhere(
|
|
|
+ (sucursal) => sucursal.id == sucursalApi.id,
|
|
|
+ orElse: () => Sucursal(),
|
|
|
+ );
|
|
|
+
|
|
|
+ sucursalApi.seleccionado =
|
|
|
+ (sucursalApi.id == idSucursalSeleccionada) ? 1 : 0;
|
|
|
+ if (forzar ||
|
|
|
+ sucursalLocal.id != 0 &&
|
|
|
+ sucursalApi.modificado != null &&
|
|
|
+ (sucursalLocal.modificado == null ||
|
|
|
+ sucursalApi.modificado!.isAfter(sucursalLocal.modificado!))) {
|
|
|
+ await RepoService().guardar(sucursalApi);
|
|
|
+ } else if (sucursalLocal.id == 0) {
|
|
|
+ await RepoService().guardar(sucursalApi);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Future<void> sincronizarPermisos(List<Permiso> permisosApi,
|
|
|
+ {bool forzar = false}) async {
|
|
|
+ var db = await RepoService().db;
|
|
|
+ var permisosLocalesQuery = await db!.query('Permiso');
|
|
|
+ List<Permiso> permisosLocales =
|
|
|
+ permisosLocalesQuery.map((e) => Permiso.fromJson(e)).toList();
|
|
|
+
|
|
|
+ for (var permisoApi in permisosApi) {
|
|
|
+ var permisoLocal = permisosLocales.firstWhere(
|
|
|
+ (permiso) => permiso.id == permisoApi.id,
|
|
|
+ orElse: () => Permiso(),
|
|
|
+ );
|
|
|
+
|
|
|
+ if (forzar ||
|
|
|
+ permisoLocal.id != null &&
|
|
|
+ permisoApi.modificado != null &&
|
|
|
+ (permisoLocal.modificado == null ||
|
|
|
+ permisoApi.modificado!.isAfter(permisoLocal.modificado!))) {
|
|
|
+ print('Actualizando permiso con ID: ${permisoApi.id}');
|
|
|
+ await RepoService().guardar(permisoApi);
|
|
|
+ } else if (permisoLocal.id == null) {
|
|
|
+ print('Insertando nuevo permiso con ID: ${permisoApi.id}');
|
|
|
+ await RepoService().guardar(permisoApi);
|
|
|
+ } else {
|
|
|
+ //print('Permiso sin cambios: ${permisoApi.id}');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Future<void> sincronizarUsuarios(List<Usuario> usuariosApi,
|
|
|
+ {bool forzar = false}) async {
|
|
|
+ var db = await RepoService().db;
|
|
|
+
|
|
|
+ var usuariosLocalesQuery = await db!.query('Usuario');
|
|
|
+ List<Usuario> usuariosLocales =
|
|
|
+ usuariosLocalesQuery.map((e) => Usuario.fromJson(e)).toList();
|
|
|
+
|
|
|
+ for (var usuarioApi in usuariosApi) {
|
|
|
+ var usuarioLocal = usuariosLocales.firstWhere(
|
|
|
+ (usuario) => usuario.id == usuarioApi.id,
|
|
|
+ orElse: () => Usuario(),
|
|
|
+ );
|
|
|
+
|
|
|
+ // Comprobar si realmente se necesita actualizar el usuario basado en la fecha de modificado
|
|
|
+ if (forzar ||
|
|
|
+ usuarioLocal.id != 0 &&
|
|
|
+ usuarioApi.modificado != null &&
|
|
|
+ (usuarioLocal.modificado == null ||
|
|
|
+ usuarioApi.modificado!.isAfter(usuarioLocal.modificado!))) {
|
|
|
+ print('Actualizando usuario con ID: ${usuarioApi.id}');
|
|
|
+ await RepoService().guardar(usuarioApi);
|
|
|
+
|
|
|
+ // Comparar permisos antes de actualizarlos
|
|
|
+ await _actualizarPermisosUsuario(
|
|
|
+ db, usuarioApi.id!, usuarioApi.permisos!);
|
|
|
+ } else if (usuarioLocal.id == 0) {
|
|
|
+ print('Insertando nuevo usuario con ID: ${usuarioApi.id}');
|
|
|
+ await RepoService().guardar(usuarioApi);
|
|
|
+
|
|
|
+ // Insertar los permisos correspondientes
|
|
|
+ await _guardarPermisosUsuario(db, usuarioApi.id!, usuarioApi.permisos!);
|
|
|
+ } else {
|
|
|
+ //print('Usuario sin cambios: ${usuarioApi.id}');
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ Future<void> _actualizarPermisosUsuario(
|
|
|
+ Database db, int idUsuario, List<String> permisosApi) async {
|
|
|
+ // Obtener los permisos actuales del usuario
|
|
|
+ var permisosLocalesQuery = await db.query(
|
|
|
+ 'UsuarioPermiso',
|
|
|
+ where: 'idUsuario = ?',
|
|
|
+ whereArgs: [idUsuario],
|
|
|
+ );
|
|
|
+ List<String> permisosLocales = permisosLocalesQuery
|
|
|
+ .map((permiso) => permiso['idPermiso'] as String)
|
|
|
+ .toList();
|
|
|
+
|
|
|
+ // Comparar los permisos del API con los locales
|
|
|
+ bool sonIguales = _listasIguales(permisosLocales, permisosApi);
|
|
|
+
|
|
|
+ if (!sonIguales) {
|
|
|
+ // Si los permisos no son iguales, actualizarlos
|
|
|
+ print('Actualizando permisos del usuario con ID: $idUsuario');
|
|
|
+ await _guardarPermisosUsuario(db, idUsuario, permisosApi);
|
|
|
+ } else {
|
|
|
+ print('Permisos del usuario con ID: $idUsuario no han cambiado.');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Future<void> _guardarPermisosUsuario(
|
|
|
+ Database db, int idUsuario, List<String> permisos) async {
|
|
|
+ // Eliminar los permisos actuales solo si hay cambios
|
|
|
+ await db.delete('UsuarioPermiso',
|
|
|
+ where: 'idUsuario = ?', whereArgs: [idUsuario]);
|
|
|
+
|
|
|
+ // Insertar los nuevos permisos
|
|
|
+ for (var idPermiso in permisos) {
|
|
|
+ await db.insert('UsuarioPermiso', {
|
|
|
+ 'idUsuario': idUsuario,
|
|
|
+ 'idPermiso': idPermiso,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ bool _listasIguales(List<String> lista1, List<String> lista2) {
|
|
|
+ if (lista1.length != lista2.length) return false;
|
|
|
+ lista1.sort();
|
|
|
+ lista2.sort();
|
|
|
+ for (int i = 0; i < lista1.length; i++) {
|
|
|
+ if (lista1[i] != lista2[i]) return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ Future<String?> obtenerClaveSucursalSeleccionada() async {
|
|
|
+ var db = await this.db;
|
|
|
+ List<Map<String, dynamic>> queryResult = await db!.query(
|
|
|
+ 'Sucursal',
|
|
|
+ where: 'seleccionado = ? AND eliminado IS NULL',
|
|
|
+ whereArgs: [1],
|
|
|
+ limit: 1,
|
|
|
+ );
|
|
|
+
|
|
|
+ if (queryResult.isNotEmpty) {
|
|
|
+ Sucursal sucursalSeleccionada = Sucursal.fromJson(queryResult.first);
|
|
|
+ return sucursalSeleccionada.clave;
|
|
|
+ }
|
|
|
+
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ Future<int?> obtenerIdSucursalSeleccionada() async {
|
|
|
+ var db = await this.db;
|
|
|
+ List<Map<String, dynamic>> queryResult = await db!.query(
|
|
|
+ 'Sucursal',
|
|
|
+ where: 'seleccionado = ? AND eliminado IS NULL',
|
|
|
+ whereArgs: [1],
|
|
|
+ limit: 1,
|
|
|
+ );
|
|
|
+
|
|
|
+ if (queryResult.isNotEmpty) {
|
|
|
+ return Sucursal.fromJson(queryResult.first).id;
|
|
|
+ }
|
|
|
+
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ Future<void> forzarSincronizacion() async {
|
|
|
+ String? claveSucursal = await obtenerClaveSucursalSeleccionada();
|
|
|
+
|
|
|
+ try {
|
|
|
+ // Sincronizar categorías
|
|
|
+ await sincronizarCategorias(
|
|
|
+ await fetchCategoriasApi(claveSucursal: claveSucursal),
|
|
|
+ forzar: true);
|
|
|
+
|
|
|
+ // Sincronizar productos
|
|
|
+ await sincronizarProductos(
|
|
|
+ await fetchProductosApi(claveSucursal: claveSucursal),
|
|
|
+ forzar: true);
|
|
|
+
|
|
|
+ // Sincronizar toppings de producto
|
|
|
+ await sincronizarProductoTopping(
|
|
|
+ await fetchProductoToppingApi(claveSucursal: claveSucursal));
|
|
|
+
|
|
|
+ // Sincronizar sucursales
|
|
|
+ await sincronizarSucursales(await fetchSucursalesApi(), forzar: true);
|
|
|
+
|
|
|
+ // Sincronizar permisos
|
|
|
+ await sincronizarPermisos(await fetchPermisosApi(), forzar: true);
|
|
|
+
|
|
|
+ // Sincronizar usuarios
|
|
|
+ await sincronizarUsuarios(await fetchUsuariosApi(), forzar: true);
|
|
|
+
|
|
|
+ print('Sincronización forzosa completada.');
|
|
|
+ } catch (e) {
|
|
|
+ print('Error en la sincronización forzosa: $e');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Future<List<CategoriaProducto>> fetchCategoriasApi(
|
|
|
+ {String? claveSucursal}) async {
|
|
|
+ Map<String, String> parametros = {
|
|
|
+ "claveSucursal": claveSucursal!,
|
|
|
+ "limite": "-1"
|
|
|
+ };
|
|
|
+ final response = ApiResponse(
|
|
|
+ await BaseService().get('/pos/categoria', queryParameters: parametros));
|
|
|
+ return response.isOk && response.resultados != null
|
|
|
+ ? response.resultados!
|
|
|
+ .map((json) => CategoriaProducto.fromApi(json))
|
|
|
+ .toList()
|
|
|
+ : [];
|
|
|
+ }
|
|
|
+
|
|
|
+ Future<List<Producto>> fetchProductosApi({String? claveSucursal}) async {
|
|
|
+ Map<String, String> parametros = {
|
|
|
+ "limite": "-1",
|
|
|
+ "claveSucursal": claveSucursal!,
|
|
|
+ "expand": "media"
|
|
|
+ };
|
|
|
+
|
|
|
+ final response = ApiResponse(
|
|
|
+ await BaseService().get('/pos/producto', queryParameters: parametros));
|
|
|
+
|
|
|
+ if (response.isOk && response.resultados != null) {
|
|
|
+ List<Producto> productosApi =
|
|
|
+ response.resultados!.map((json) => Producto.fromApi(json)).toList();
|
|
|
+
|
|
|
+ // Descargar y almacenar cada imagen de producto
|
|
|
+ for (var productoApi in productosApi) {
|
|
|
+ if (productoApi.media != null && productoApi.media!.isNotEmpty) {
|
|
|
+ for (var media in productoApi.media!) {
|
|
|
+ // Descargar y guardar la imagen localmente
|
|
|
+ String? localImagePath = await downloadAndStoreImage(
|
|
|
+ media.ruta!, productoApi.id!, media.nombre!);
|
|
|
+
|
|
|
+ if (localImagePath != null) {
|
|
|
+ productoApi.imagen = localImagePath;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return productosApi;
|
|
|
+ }
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+
|
|
|
+ Future<List<ProductoTopping>> fetchProductoToppingApi(
|
|
|
+ {String? claveSucursal}) async {
|
|
|
+ Map<String, String> parametros = {
|
|
|
+ "limite": "-1",
|
|
|
+ "claveSucursal": claveSucursal!,
|
|
|
+ };
|
|
|
+
|
|
|
+ final response = ApiResponse(await BaseService()
|
|
|
+ .get('/pos/producto-topping', queryParameters: parametros));
|
|
|
+ return response.isOk && response.resultados != null
|
|
|
+ ? response.resultados!
|
|
|
+ .map((json) => ProductoTopping.fromApi(json))
|
|
|
+ .toList()
|
|
|
+ : [];
|
|
|
+ }
|
|
|
+
|
|
|
+ Future<List<Sucursal>> fetchSucursalesApi() async {
|
|
|
+ Map<String, String> parametros = {
|
|
|
+ "limite": "-1",
|
|
|
+ };
|
|
|
+
|
|
|
+ final response = ApiResponse(
|
|
|
+ await BaseService().get('/pos/sucursal', queryParameters: parametros));
|
|
|
+ return response.isOk && response.resultados != null
|
|
|
+ ? response.resultados!.map((json) => Sucursal.fromApi(json)).toList()
|
|
|
+ : [];
|
|
|
+ }
|
|
|
+
|
|
|
+ Future<List<Permiso>> fetchPermisosApi() async {
|
|
|
+ Map<String, String> parametros = {
|
|
|
+ "limite": "-1",
|
|
|
+ };
|
|
|
+
|
|
|
+ final response = ApiResponse(
|
|
|
+ await BaseService().get('/pos/permiso', queryParameters: parametros));
|
|
|
+ return response.isOk && response.resultados != null
|
|
|
+ ? response.resultados!.map((json) => Permiso.fromJson(json)).toList()
|
|
|
+ : [];
|
|
|
+ }
|
|
|
+
|
|
|
+ Future<List<Usuario>> fetchUsuariosApi() async {
|
|
|
+ Map<String, String> parametros = {
|
|
|
+ "limite": "-1",
|
|
|
+ "expand": "permisos",
|
|
|
+ };
|
|
|
+
|
|
|
+ final response = ApiResponse(
|
|
|
+ await BaseService().get('/pos/usuario', queryParameters: parametros));
|
|
|
+ return response.isOk && response.resultados != null
|
|
|
+ ? response.resultados!.map((json) => Usuario.fromApi(json)).toList()
|
|
|
+ : [];
|
|
|
+ }
|
|
|
}
|