repo_service.dart 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675
  1. import 'dart:convert';
  2. import 'package:intl/intl.dart';
  3. import 'package:path/path.dart';
  4. import 'package:path_provider/path_provider.dart';
  5. import 'package:sqflite/sqflite.dart';
  6. import '../models/models.dart';
  7. class RepoService<T> {
  8. static int dbVersion = 13;
  9. static String dbName = 'olivamiapos01.db';
  10. static const String id = Basico.identificadorWeb;
  11. static const String idLocal = Basico.identificadorLocal;
  12. static Database? _db;
  13. final Map<String, dynamic> contexto = {
  14. 'Categoria': CategoriaProducto(),
  15. 'Producto': Producto(),
  16. 'Pedido': Pedido(productos: []),
  17. 'PedidoProducto': PedidoProducto(),
  18. 'Gasto': Gasto(),
  19. 'Deposito': Deposito(),
  20. 'CorteCaja': CorteCaja(),
  21. };
  22. Future<Database?> get db async {
  23. if (_db != null) return _db;
  24. _db = await databaseInit();
  25. return _db;
  26. }
  27. Future<Database> databaseInit() async {
  28. String dir = (await getApplicationDocumentsDirectory()).path;
  29. String path = join(dir, dbName);
  30. return await openDatabase(
  31. path,
  32. version: dbVersion,
  33. onCreate: _onCreate,
  34. onUpgrade: _onUpgrade,
  35. );
  36. }
  37. _onCreate(Database db, int version) async {
  38. contexto.forEach((String nombre, dynamic modelo) async {
  39. Map<String, dynamic> model = json.decode(json.encode(modelo.toJson()));
  40. String sql =
  41. "CREATE TABLE ${modelo.runtimeType.toString()} (id INTEGER PRIMARY KEY AUTOINCREMENT";
  42. model.forEach((String key, dynamic value) {
  43. if (key != "id") {
  44. String tipo = value.runtimeType.toString();
  45. String sqlType = "";
  46. if (equals(tipo, 'int')) {
  47. sqlType = "INTEGER";
  48. } else if (equals(tipo, 'double')) {
  49. sqlType = "REAL";
  50. } else if (equals(tipo, 'bool')) {
  51. sqlType = "BOOLEAN";
  52. } else {
  53. sqlType = "TEXT";
  54. }
  55. sql += ", $key $sqlType";
  56. }
  57. });
  58. sql += ")";
  59. await db.execute(sql);
  60. await db.execute('''
  61. CREATE TABLE PedidoProductoTopping (
  62. id INTEGER PRIMARY KEY AUTOINCREMENT,
  63. idPedidoProducto INTEGER,
  64. idTopping INTEGER,
  65. FOREIGN KEY (idPedidoProducto) REFERENCES PedidoProducto(id),
  66. FOREIGN KEY (idTopping) REFERENCES Producto(id)
  67. )
  68. ''');
  69. if (modelo.runtimeType.toString() == 'Pedido') {
  70. await db.execute(
  71. 'ALTER TABLE Pedido ADD COLUMN descuento INTEGER DEFAULT 0');
  72. }
  73. await db.execute('''
  74. CREATE TABLE Descuento (
  75. id INTEGER PRIMARY KEY AUTOINCREMENT,
  76. porcentaje INTEGER
  77. )
  78. ''');
  79. await db.insert('Descuento', {'porcentaje': 0});
  80. await db.insert('Descuento', {'porcentaje': 5});
  81. await db.insert('Descuento', {'porcentaje': 10});
  82. await db.insert('Descuento', {'porcentaje': 15});
  83. await db.insert('Descuento', {'porcentaje': 20});
  84. await db.insert('Descuento', {'porcentaje': 25});
  85. await db.insert('Descuento', {'porcentaje': 30});
  86. });
  87. await db.execute('''
  88. CREATE TABLE ProductoTopping (
  89. id INTEGER PRIMARY KEY AUTOINCREMENT,
  90. idProducto INTEGER,
  91. idTopping INTEGER,
  92. FOREIGN KEY (idProducto) REFERENCES Producto(id),
  93. FOREIGN KEY (idTopping) REFERENCES Producto(id)
  94. )
  95. ''');
  96. await db.execute('''
  97. CREATE TABLE Variable (
  98. id INTEGER PRIMARY KEY AUTOINCREMENT,
  99. nombre TEXT,
  100. clave TEXT,
  101. descripcion TEXT,
  102. activo BOOLEAN,
  103. idLocal INTEGER,
  104. eliminado TEXT
  105. )
  106. ''');
  107. }
  108. void _onUpgrade(Database db, int oldVersion, int newVersion) async {
  109. while (oldVersion < newVersion) {
  110. switch (oldVersion) {
  111. case 1:
  112. await db.execute(
  113. "ALTER TABLE CategoriaProducto ADD COLUMN esToping INTEGER DEFAULT 0");
  114. await db.execute(
  115. "ALTER TABLE CategoriaProducto ADD COLUMN descripcion TEXT DEFAULT ''");
  116. await db.execute(
  117. "ALTER TABLE CategoriaProducto ADD COLUMN maximo INTEGER");
  118. break;
  119. case 2:
  120. await db.execute('''
  121. CREATE TABLE ProductoTopping (
  122. id INTEGER PRIMARY KEY AUTOINCREMENT,
  123. idProducto INTEGER,
  124. idTopping INTEGER,
  125. FOREIGN KEY (idProducto) REFERENCES Producto(id),
  126. FOREIGN KEY (idTopping) REFERENCES Producto(id)
  127. )
  128. ''');
  129. break;
  130. case 3:
  131. await db.execute('''
  132. CREATE TABLE PedidoProductoTopping (
  133. id INTEGER PRIMARY KEY AUTOINCREMENT,
  134. idPedidoProducto INTEGER,
  135. idTopping INTEGER,
  136. FOREIGN KEY (idPedidoProducto) REFERENCES PedidoProducto(id),
  137. FOREIGN KEY (idTopping) REFERENCES Producto(id)
  138. )
  139. ''');
  140. break;
  141. case 4:
  142. await db.execute('''
  143. ALTER TABLE Pedido ADD COLUMN descuento INTEGER DEFAULT 0
  144. ''');
  145. break;
  146. case 5:
  147. await db.execute('''
  148. CREATE TABLE IF NOT EXISTS Descuento (
  149. id INTEGER PRIMARY KEY AUTOINCREMENT,
  150. porcentaje INTEGER
  151. )
  152. ''');
  153. await db.insert('Descuento', {'porcentaje': 0});
  154. await db.insert('Descuento', {'porcentaje': 5});
  155. await db.insert('Descuento', {'porcentaje': 10});
  156. await db.insert('Descuento', {'porcentaje': 15});
  157. await db.insert('Descuento', {'porcentaje': 20});
  158. await db.insert('Descuento', {'porcentaje': 25});
  159. await db.insert('Descuento', {'porcentaje': 30});
  160. break;
  161. case 6:
  162. await db.execute('''
  163. ALTER TABLE Pedido ADD COLUMN tipoPago TEXT DEFAULT '';
  164. ''');
  165. await db.execute('''
  166. ALTER TABLE Pedido ADD COLUMN cantEfectivo REAL DEFAULT 0;
  167. ''');
  168. await db.execute('''
  169. ALTER TABLE Pedido ADD COLUMN cantTarjeta REAL DEFAULT 0;
  170. ''');
  171. await db.execute('''
  172. ALTER TABLE Pedido ADD COLUMN cantTransferencia REAL DEFAULT 0;
  173. ''');
  174. break;
  175. case 7:
  176. await db.execute('''
  177. CREATE TABLE Variable (
  178. id INTEGER PRIMARY KEY AUTOINCREMENT,
  179. nombre TEXT,
  180. clave TEXT,
  181. descripcion TEXT,
  182. activo BOOLEAN,
  183. idLocal INTEGER,
  184. eliminado TEXT
  185. )
  186. ''');
  187. break;
  188. case 9:
  189. await db.execute('''
  190. ALTER TABLE Pedido ADD COLUMN idWeb INTEGER;
  191. ''');
  192. await db.execute('''
  193. ALTER TABLE Pedido ADD COLUMN sincronizado TEXT;
  194. ''');
  195. await db.execute('''
  196. ALTER TABLE PedidoProducto ADD COLUMN idWeb INTEGER;
  197. ''');
  198. await db.execute('''
  199. ALTER TABLE PedidoProducto ADD COLUMN sincronizado TEXT;
  200. ''');
  201. break;
  202. case 10:
  203. await db.execute('''
  204. update Pedido set sincronizado = null, peticion = strftime('%Y-%m-%dT%H:%M:%S',
  205. datetime(substr(peticion, 7, 4) || '-' ||
  206. substr(peticion, 4, 2) || '-' ||
  207. substr(peticion, 1, 2) || ' ' ||
  208. substr(peticion, 12, 8) || ' -07:00', 'localtime', '+07:00'))
  209. WHERE strftime('%Y-%m-%dT%H:%M:%S',
  210. datetime(substr(peticion, 7, 4) || '-' ||
  211. substr(peticion, 4, 2) || '-' ||
  212. substr(peticion, 1, 2) || ' ' ||
  213. substr(peticion, 12, 8) || ' -07:00', 'localtime', '+07:00')) is not null
  214. ''');
  215. break;
  216. case 12:
  217. await db.execute('''
  218. ALTER TABLE CategoriaProducto ADD COLUMN creado TEXT;
  219. ''');
  220. await db.execute('''
  221. ALTER TABLE CategoriaProducto ADD COLUMN modificado TEXT;
  222. ''');
  223. await db.execute('''
  224. ALTER TABLE Producto ADD COLUMN creado TEXT;
  225. ''');
  226. await db.execute('''
  227. ALTER TABLE Producto ADD COLUMN modificado TEXT;
  228. ''');
  229. await db.execute('''
  230. ALTER TABLE Producto ADD COLUMN activo INTEGER;
  231. ''');
  232. break;
  233. }
  234. oldVersion++;
  235. }
  236. }
  237. Future<int> guardar(T model) async {
  238. try {
  239. print("Guardando modelo en la base de datos: ${model.runtimeType}");
  240. // Comprobar si es un modelo que obtiene las fechas del servidor (Producto o CategoriaProducto)
  241. if (model is Producto || model is CategoriaProducto) {
  242. // No hacer nada, las fechas vienen del servidor
  243. print("Usando fechas del servidor para ${model.runtimeType}");
  244. } else if (model is Basico) {
  245. // Generar las fechas localmente para otros modelos
  246. asignarFechasLocalmente(model);
  247. }
  248. // Convertir el modelo a JSON para la base de datos
  249. String modelo = json.encode(model, toEncodable: toEncodable);
  250. print("Modelo convertido a JSON: $modelo");
  251. Map<String, dynamic> modelMap = json.decode(modelo);
  252. var dbClient = await db;
  253. String nombreTabla = model.runtimeType.toString();
  254. int? id = modelMap['id'];
  255. if (id == null || id == 0) {
  256. modelMap.remove('id');
  257. }
  258. List<Map> existing = id != null && id > 0
  259. ? await dbClient!.query(nombreTabla, where: 'id = ?', whereArgs: [id])
  260. : [];
  261. if (existing.isNotEmpty) {
  262. print("Actualizando registro existente con ID: $id");
  263. await dbClient!.update(
  264. nombreTabla,
  265. modelMap,
  266. where: 'id = ?',
  267. whereArgs: [id],
  268. );
  269. } else {
  270. print("Insertando nuevo registro en la tabla $nombreTabla");
  271. id = await dbClient!.insert(nombreTabla, modelMap);
  272. }
  273. return id!;
  274. } catch (e) {
  275. print('Error al guardar en dynamic: $e');
  276. return 0;
  277. }
  278. }
  279. void asignarFechasLocalmente(Basico model) {
  280. DateTime ahora = DateTime.now();
  281. if (model.creado == null) {
  282. model.creado = ahora.toUtc();
  283. }
  284. model.modificado = ahora.toUtc();
  285. }
  286. Future<void> _guardarToppings(
  287. Database db, int idProducto, List<Producto>? topings) async {
  288. await db.delete('ProductoTopping',
  289. where: 'idProducto = ?', whereArgs: [idProducto]);
  290. if (topings != null) {
  291. for (var topping in topings) {
  292. await db.insert('ProductoTopping', {
  293. 'idProducto': idProducto,
  294. 'idTopping': topping.id,
  295. });
  296. }
  297. }
  298. }
  299. Future<int> guardarLocal(T model) async {
  300. var dbClient = await db;
  301. String nombreTabla = model.runtimeType.toString();
  302. String modelo = json.encode(model, toEncodable: toEncodable);
  303. Map<String, dynamic> modelMap = json.decode(modelo);
  304. if (nombreTabla == "PedidoProductoTopping") {
  305. modelMap.remove('idLocal');
  306. modelMap.remove('eliminado');
  307. }
  308. if (modelMap['id'] == null || modelMap['id'] == 0) {
  309. modelMap.remove('id');
  310. }
  311. int resultado;
  312. int? identificadorLocal = modelMap[Basico.identificadorLocal];
  313. if (identificadorLocal != null && identificadorLocal > 0) {
  314. resultado = await dbClient!.update(
  315. nombreTabla,
  316. modelMap,
  317. where: "$idLocal = ?",
  318. whereArgs: [identificadorLocal],
  319. );
  320. } else {
  321. resultado = await dbClient!.insert(nombreTabla, modelMap);
  322. var rawQuery =
  323. await dbClient.rawQuery("SELECT last_insert_rowid() as id");
  324. if (rawQuery.isNotEmpty) {
  325. resultado = int.parse(rawQuery.first["id"].toString());
  326. modelMap[Basico.identificadorLocal] = resultado;
  327. }
  328. }
  329. if (model is Pedido) {
  330. model.id = resultado;
  331. }
  332. if (model is Producto) {
  333. await _guardarToppings(dbClient!, model.id!, model.topings);
  334. }
  335. return resultado;
  336. }
  337. dynamic toEncodable(dynamic item) {
  338. print("Serializando objeto: $item");
  339. if (item is Pedido) {
  340. return item.toJson();
  341. } else if (item is PedidoProducto) {
  342. return item.toJson();
  343. } else if (item is PedidoProductoTopping) {
  344. return item.toJson();
  345. } else if (item is Producto) {
  346. return item.toJson();
  347. } else if (item is CategoriaProducto) {
  348. return item.toJson();
  349. } else if (item is Variable) {
  350. return item.toJson();
  351. }
  352. throw UnsupportedError(
  353. 'Type not supported for serialization: ${item.runtimeType}');
  354. }
  355. Future<List<T>> obtenerTodos({String orderBy = 'id DESC'}) async {
  356. var db = await this.db;
  357. String tableName = T.toString();
  358. var result = await db!
  359. .query(tableName, where: 'eliminado IS NULL', orderBy: orderBy);
  360. return result.map((map) => fromMap<T>(map)).toList();
  361. }
  362. T fromMap<T>(Map<String, dynamic> map) {
  363. switch (T) {
  364. case Pedido:
  365. return Pedido.fromJson(map) as T;
  366. case Producto:
  367. return Producto.fromJson(map) as T;
  368. default:
  369. throw Exception('Tipo no soportado');
  370. }
  371. }
  372. Future<Pedido?> obtenerPorId(int id) async {
  373. Database? dbClient = await db;
  374. List<Map> maps =
  375. await dbClient!.query('Pedido', where: 'id = ?', whereArgs: [id]);
  376. if (maps.isNotEmpty) {
  377. return Pedido.fromJson(Map<String, dynamic>.from(maps.first));
  378. }
  379. return null;
  380. }
  381. Future<List<PedidoProducto>> obtenerPorIdPedido(int idPedido) async {
  382. Database? dbClient = await db;
  383. List<Map> maps = await dbClient!
  384. .query('PedidoProducto', where: 'idPedido = ?', whereArgs: [idPedido]);
  385. return maps
  386. .map((map) => PedidoProducto.fromJson(Map<String, dynamic>.from(map)))
  387. .toList();
  388. }
  389. Future<List<Deposito>> obtenerDepositosPorIdCorteCaja(int idCorteCaja) async {
  390. var dbClient = await db;
  391. List<Map<String, dynamic>> maps = await dbClient!.query(
  392. 'Deposito',
  393. where: 'idCorteCaja = ?',
  394. whereArgs: [idCorteCaja],
  395. );
  396. return maps.map((map) => Deposito.fromJson(map)).toList();
  397. }
  398. Future<List<Gasto>> obtenerGastosPorIdCorteCaja(int idCorteCaja) async {
  399. var dbClient = await db;
  400. List<Map<String, dynamic>> maps = await dbClient!.query(
  401. 'Gasto',
  402. where: 'idCorteCaja = ?',
  403. whereArgs: [idCorteCaja],
  404. );
  405. return maps.map((map) => Gasto.fromJson(map)).toList();
  406. }
  407. Future<int> contarPedidos() async {
  408. Database? dbClient = await db;
  409. var result = await dbClient!.rawQuery('SELECT COUNT(*) FROM Pedido');
  410. return Sqflite.firstIntValue(result) ?? 0;
  411. }
  412. Future<List<Pedido>> obtenerPedidosPaginados(int limit, int offset) async {
  413. Database? dbClient = await db;
  414. List<Map<String, dynamic>> result = await dbClient!
  415. .query('Pedido', limit: limit, offset: offset, orderBy: 'id DESC');
  416. return result.map((map) => Pedido.fromJson(map)).toList();
  417. }
  418. Future<Producto?> obtenerProductoPorId(int idProducto) async {
  419. Database? dbClient = await db;
  420. List<Map> maps = await dbClient!
  421. .query('Producto', where: 'id = ?', whereArgs: [idProducto]);
  422. if (maps.isNotEmpty) {
  423. return Producto.fromJson(Map<String, dynamic>.from(maps.first));
  424. }
  425. return null;
  426. }
  427. Future<List<int>> obtenerToppingsPorProducto(int idProducto) async {
  428. var dbClient = await db;
  429. var result = await dbClient!.query(
  430. 'ProductoTopping',
  431. where: 'idProducto = ?',
  432. whereArgs: [idProducto],
  433. );
  434. return result.map((map) => map['idTopping'] as int).toList();
  435. }
  436. Future<List<PedidoProductoTopping>> obtenerToppingsPorPedidoProducto(
  437. int idPedidoProducto) async {
  438. var dbClient = await db;
  439. List<Map> maps = await dbClient!.query('PedidoProductoTopping',
  440. where: 'idPedidoProducto = ?', whereArgs: [idPedidoProducto]);
  441. if (maps.isNotEmpty) {
  442. return maps
  443. .map((map) =>
  444. PedidoProductoTopping.fromJson(Map<String, dynamic>.from(map)))
  445. .toList();
  446. }
  447. return [];
  448. }
  449. Future<int> obtenerProximoFolio() async {
  450. var dbClient = await db;
  451. var result = await dbClient!.rawQuery(
  452. 'SELECT MAX(CAST(folio AS INTEGER)) as last_folio FROM Pedido');
  453. if (result.isNotEmpty && result.first["last_folio"] != null) {
  454. return int.tryParse(result.first["last_folio"].toString())! + 1;
  455. }
  456. return 1;
  457. }
  458. Future<List<T>> buscarPorFolio(String folio) async {
  459. var dbClient = await db;
  460. List<Map<String, dynamic>> maps = await dbClient!.query(
  461. 'Pedido',
  462. where: 'folio LIKE ?',
  463. whereArgs: ['%$folio%'],
  464. );
  465. return maps.map((map) => fromMap<T>(map)).toList();
  466. }
  467. Future<List<Pedido>> buscarPorFecha(
  468. DateTime startDate, DateTime endDate) async {
  469. var dbClient = await db;
  470. String startDateString = startDate.toIso8601String();
  471. String endDateString = endDate.toIso8601String();
  472. print(
  473. 'Ejecutando consulta: SELECT * FROM Pedido WHERE peticion BETWEEN $startDateString AND $endDateString');
  474. List<Map<String, dynamic>> maps = await dbClient!.rawQuery('''
  475. SELECT * FROM Pedido
  476. WHERE peticion BETWEEN ? AND ?
  477. ''', [startDateString, endDateString]);
  478. print('Resultado de la consulta: ${maps.length} pedidos encontrados.');
  479. return maps.map((map) => Pedido.fromJson(map)).toList();
  480. }
  481. Future<List<CorteCaja>> buscarPorFechaCorte(
  482. DateTime startDate, DateTime endDate) async {
  483. var dbClient = await db;
  484. String startDateString = DateFormat('dd-MM-yyyy').format(startDate);
  485. String endDateString = DateFormat('dd-MM-yyyy 23:59:59').format(endDate);
  486. List<Map<String, dynamic>> maps = await dbClient!.query(
  487. 'CorteCaja',
  488. where: 'fecha BETWEEN ? AND ?',
  489. whereArgs: [startDateString, endDateString],
  490. );
  491. return maps.map((map) => CorteCaja.fromJson(map)).toList();
  492. }
  493. Future<void> eliminar<T>(int id) async {
  494. var dbClient = await db;
  495. String tableName = T.toString();
  496. await dbClient!.delete(tableName, where: 'id = ?', whereArgs: [id]);
  497. }
  498. Future<List<Descuento>> obtenerTodosDescuentos() async {
  499. var dbClient = await db;
  500. var result = await dbClient!.query('Descuento', orderBy: 'porcentaje ASC');
  501. return result.map((map) => Descuento.fromJson(map)).toList();
  502. }
  503. Future<int> guardarDescuento(Descuento descuento) async {
  504. var dbClient = await db;
  505. if (descuento.id != null && descuento.id! > 0) {
  506. return await dbClient!.update(
  507. 'Descuento',
  508. descuento.toJson(),
  509. where: 'id = ?',
  510. whereArgs: [descuento.id],
  511. );
  512. } else {
  513. return await dbClient!.insert('Descuento', descuento.toJson());
  514. }
  515. }
  516. Future<int> eliminarDescuento(int id) async {
  517. var dbClient = await db;
  518. return await dbClient!
  519. .delete('Descuento', where: 'id = ?', whereArgs: [id]);
  520. }
  521. Future<Variable?> obtenerPorNombre(String nombre) async {
  522. var dbClient = await db;
  523. List<Map<String, dynamic>> maps = await dbClient!.query(
  524. 'Variable',
  525. where: 'nombre = ?',
  526. whereArgs: [nombre],
  527. );
  528. if (maps.isNotEmpty) {
  529. return Variable.fromJson(Map<String, dynamic>.from(maps.first));
  530. }
  531. return null;
  532. }
  533. Future<List<Pedido>> obtenerPedidosOrdenadosPorFecha() async {
  534. var dbClient = await db;
  535. String orderBy =
  536. "datetime(substr(peticion, 7, 4) || '-' || substr(peticion, 4, 2) || '-' || substr(peticion, 1, 2) || ' ' || substr(peticion, 12)) ASC";
  537. List<Map<String, dynamic>> result = await dbClient!.query(
  538. 'Pedido',
  539. where: 'sincronizado IS NULL',
  540. orderBy: orderBy,
  541. );
  542. return result.map((map) => Pedido.fromJson(map)).toList();
  543. }
  544. Future<void> sincronizarCategorias(
  545. List<CategoriaProducto> categoriasApi) async {
  546. var db = await RepoService().db;
  547. var categoriasLocalesQuery = await db!.query('CategoriaProducto');
  548. List<CategoriaProducto> categoriasLocales = categoriasLocalesQuery
  549. .map((e) => CategoriaProducto.fromJson(e))
  550. .toList();
  551. for (var categoriaApi in categoriasApi) {
  552. var categoriaLocal = categoriasLocales.firstWhere(
  553. (categoria) => categoria.id == categoriaApi.id,
  554. orElse: () => CategoriaProducto(),
  555. );
  556. if (categoriaLocal.id != 0 &&
  557. categoriaApi.modificado != null &&
  558. (categoriaLocal.modificado == null ||
  559. categoriaApi.modificado!.isAfter(categoriaLocal.modificado!))) {
  560. await RepoService().guardar(categoriaApi);
  561. } else if (categoriaLocal.id == 0) {
  562. await RepoService().guardar(categoriaApi);
  563. }
  564. }
  565. }
  566. Future<void> sincronizarProductos(List<Producto> productosApi) async {
  567. var db = await RepoService().db;
  568. var productosLocalesQuery = await db!.query('Producto');
  569. List<Producto> productosLocales =
  570. productosLocalesQuery.map((e) => Producto.fromJson(e)).toList();
  571. for (var productoApi in productosApi) {
  572. var productoLocal = productosLocales.firstWhere(
  573. (producto) => producto.id == productoApi.id,
  574. orElse: () => Producto(),
  575. );
  576. if (productoLocal.id != 0 &&
  577. productoApi.modificado != null &&
  578. productoApi.modificado!.isAfter(productoLocal.modificado!)) {
  579. await RepoService().guardar(productoApi);
  580. } else if (productoLocal.id == 0) {
  581. await RepoService().guardar(productoApi);
  582. }
  583. }
  584. }
  585. }