pedido_view_model.dart 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. import 'package:flutter/material.dart';
  2. import 'package:intl/intl.dart';
  3. import 'package:sqflite/sqflite.dart';
  4. import '../data/api_response.dart';
  5. import '../models/models.dart';
  6. import '../services/services.dart';
  7. class PedidoViewModel extends ChangeNotifier {
  8. String _busqueda = "";
  9. String get busqueda => _busqueda;
  10. List<Pedido> _pedidos = [];
  11. Pedido? _selectedPedido;
  12. bool _isLoading = false;
  13. int _currentPage = 1;
  14. int _totalPedidos = 0;
  15. int _limit = 10;
  16. int get currentPage => _currentPage;
  17. int get totalPedidos => _totalPedidos;
  18. int get totalPages => (_totalPedidos / _limit).ceil();
  19. List<Pedido> get pedidos => _pedidos;
  20. Pedido? get selectedPedido => _selectedPedido;
  21. bool get isLoading => _isLoading;
  22. void setIsLoading(bool loading) {
  23. _isLoading = loading;
  24. notifyListeners();
  25. }
  26. Future<bool> guardarPedidoLocal({required Pedido pedido}) async {
  27. RepoService<Pedido> repoPedido = RepoService<Pedido>();
  28. if (pedido.id == null || pedido.id == 0) {
  29. int nextFolio = await repoPedido.obtenerProximoFolio();
  30. pedido.folio = nextFolio;
  31. }
  32. try {
  33. // Verifica si el pedido ya existe en la base de datos
  34. Pedido? pedidoExistente = await repoPedido.obtenerPorId(pedido.id!);
  35. if (pedidoExistente != null) {
  36. // Si existe, actualiza
  37. await repoPedido.guardar(pedido);
  38. } else {
  39. // Si no existe, inserta como nuevo
  40. int idPedido = await repoPedido.guardarLocal(pedido);
  41. pedido.id = idPedido;
  42. }
  43. RepoService<PedidoProducto> repoPedidoProducto =
  44. RepoService<PedidoProducto>();
  45. RepoService<PedidoProductoTopping> repoPedidoProductoTopping =
  46. RepoService<PedidoProductoTopping>();
  47. // Manejo de productos asociados al pedido
  48. for (var producto in pedido.productos) {
  49. PedidoProducto pedidoProducto = PedidoProducto(
  50. idPedido: pedido.id,
  51. idProducto: producto.idProducto,
  52. cantidad: producto.cantidad,
  53. costoUnitario: producto.costoUnitario,
  54. comentario: producto.comentario,
  55. );
  56. if (producto.id != null && producto.id! > 0) {
  57. await repoPedidoProducto.guardarLocal(pedidoProducto);
  58. } else {
  59. int idPedidoProducto =
  60. await repoPedidoProducto.guardarLocal(pedidoProducto);
  61. for (var topping in producto.toppings) {
  62. PedidoProductoTopping pedidoProductoTopping = PedidoProductoTopping(
  63. idPedidoProducto: idPedidoProducto,
  64. idTopping: topping.idTopping,
  65. idCategoria: topping.idCategoria,
  66. );
  67. await repoPedidoProductoTopping.guardarLocal(pedidoProductoTopping);
  68. }
  69. }
  70. }
  71. notifyListeners();
  72. return true;
  73. } catch (e) {
  74. print('Error al guardar el pedido: $e');
  75. return false;
  76. }
  77. }
  78. Future<void> fetchLocalPedidos({int page = 1}) async {
  79. _isLoading = true;
  80. _currentPage = page;
  81. notifyListeners();
  82. RepoService<Pedido> repoPedido = RepoService<Pedido>();
  83. _totalPedidos = await repoPedido.contarPedidos();
  84. int offset = (_limit * (page - 1));
  85. List<Pedido> paginatedPedidos =
  86. await repoPedido.obtenerPedidosPaginados(_limit, offset);
  87. _pedidos = paginatedPedidos;
  88. _isLoading = false;
  89. notifyListeners();
  90. }
  91. void nextPage() {
  92. if (_currentPage < totalPages) {
  93. fetchLocalPedidosForScreen(page: _currentPage + 1);
  94. }
  95. }
  96. void previousPage() {
  97. if (_currentPage > 1) {
  98. fetchLocalPedidosForScreen(page: _currentPage - 1);
  99. }
  100. }
  101. Future<void> fetchLocalPedidosForScreen({int page = 1}) async {
  102. setIsLoading(true);
  103. RepoService<Pedido> repoPedido = RepoService<Pedido>();
  104. _currentPage = page;
  105. var db = await RepoService().db;
  106. int? count = Sqflite.firstIntValue(
  107. await db!.rawQuery('SELECT COUNT(*) FROM Pedido'));
  108. _totalPedidos = count ?? 0;
  109. int offset = (_limit * (page - 1));
  110. List<Pedido> localPedidos =
  111. await repoPedido.obtenerPedidosPaginados(_limit, offset);
  112. _pedidos = localPedidos;
  113. setIsLoading(false);
  114. notifyListeners();
  115. }
  116. Future<List<Pedido>> fetchAllLocalPedidos() async {
  117. setIsLoading(true);
  118. RepoService<Pedido> repoPedido = RepoService<Pedido>();
  119. List<Pedido> allPedidos = await repoPedido.obtenerTodos();
  120. setIsLoading(false);
  121. return allPedidos;
  122. }
  123. Future<List<Pedido>> fetchPedidosPorFechaSinLimit(
  124. DateTime startDate, DateTime endDate) async {
  125. setIsLoading(true);
  126. RepoService<Pedido> repoPedido = RepoService<Pedido>();
  127. List<Pedido> pedidos = await repoPedido.buscarPorFecha(startDate, endDate);
  128. setIsLoading(false);
  129. return pedidos;
  130. }
  131. Future<Pedido?> fetchPedidoConProductos(int idPedido) async {
  132. RepoService<Pedido> repoPedido = RepoService<Pedido>();
  133. Pedido? pedido = await repoPedido.obtenerPorId(idPedido);
  134. if (pedido != null) {
  135. RepoService<PedidoProducto> repoProducto = RepoService<PedidoProducto>();
  136. RepoService<Producto> repoProductoInfo = RepoService<Producto>();
  137. List<PedidoProducto> productos =
  138. await repoProducto.obtenerPorIdPedido(idPedido);
  139. for (var producto in productos) {
  140. Producto? prodInfo =
  141. await repoProductoInfo.obtenerProductoPorId(producto.idProducto!);
  142. if (prodInfo != null) {
  143. producto.producto = prodInfo;
  144. }
  145. RepoService<PedidoProductoTopping> repoTopping =
  146. RepoService<PedidoProductoTopping>();
  147. List<PedidoProductoTopping> toppings =
  148. await repoTopping.obtenerToppingsPorPedidoProducto(producto.id!);
  149. for (var topping in toppings) {
  150. Producto? toppingInfo =
  151. await repoProductoInfo.obtenerProductoPorId(topping.idTopping!);
  152. if (toppingInfo != null) {
  153. topping.topping = toppingInfo;
  154. }
  155. }
  156. producto.toppings = toppings;
  157. }
  158. pedido.productos = productos;
  159. }
  160. return pedido;
  161. }
  162. Future<void> buscarPedidosPorFolio(String folio) async {
  163. setIsLoading(true);
  164. RepoService<Pedido> repoPedido = RepoService<Pedido>();
  165. List<Pedido> localPedidos = await repoPedido.buscarPorFolio(folio);
  166. _pedidos = localPedidos;
  167. setIsLoading(false);
  168. notifyListeners();
  169. }
  170. Future<void> buscarPedidosPorFecha(
  171. DateTime startDate, DateTime endDate) async {
  172. setIsLoading(true);
  173. RepoService<Pedido> repoPedido = RepoService<Pedido>();
  174. List<Pedido> localPedidos =
  175. await repoPedido.buscarPorFecha(startDate, endDate);
  176. _pedidos = localPedidos;
  177. setIsLoading(false);
  178. notifyListeners();
  179. }
  180. Future<List<Pedido>> buscarPorFecha(
  181. DateTime startDate, DateTime endDate) async {
  182. setIsLoading(true);
  183. RepoService<Pedido> repoPedido = RepoService<Pedido>();
  184. print('Consulta SQL de pedidos desde: $startDate hasta: $endDate');
  185. List<Pedido> pedidos = await repoPedido.buscarPorFecha(startDate, endDate);
  186. print('Pedidos obtenidos desde la base de datos: ${pedidos.length}');
  187. pedidos.forEach((pedido) => print(
  188. 'Pedido Folio: ${pedido.folio}, Estatus: ${pedido.estatus}, Total: ${pedido.totalPedido}'));
  189. setIsLoading(false);
  190. notifyListeners();
  191. return pedidos;
  192. }
  193. Future<void> cancelarPedido(int idPedido) async {
  194. var db = await RepoService().db;
  195. await db?.update(
  196. 'Pedido',
  197. {
  198. 'estatus': 'CANCELADO',
  199. 'sincronizado': null,
  200. },
  201. where: 'id = ?',
  202. whereArgs: [idPedido],
  203. );
  204. fetchLocalPedidosForScreen();
  205. }
  206. Future<bool> sincronizarPedidos() async {
  207. List<Pedido> pedidosNoSincronizados =
  208. await fetchAllLocalPedidosOrdenadosPorFecha();
  209. if (pedidosNoSincronizados.isNotEmpty) {
  210. Pedido pedidoNoSincronizado = pedidosNoSincronizados.first;
  211. if (pedidoNoSincronizado.productos.isEmpty) {
  212. pedidoNoSincronizado =
  213. await fetchPedidoConProductos(pedidoNoSincronizado.id) ??
  214. pedidoNoSincronizado;
  215. }
  216. Map<String, dynamic> pedidoJson =
  217. await prepararPedidoParaApi(pedidoNoSincronizado);
  218. print('JSON enviado: $pedidoJson');
  219. var response = ApiResponse(await BaseService()
  220. .post('/pos/pedido/sincronizar', body: pedidoJson));
  221. if (response.isOk && response.detalle != null) {
  222. int idWeb = response.detalle!['id'];
  223. String sincronizado = response.detalle!['sincronizado'];
  224. await actualizarPedidoSincronizado(
  225. pedidoNoSincronizado.id!, idWeb, sincronizado);
  226. return true;
  227. } else {
  228. print('Error en la sincronización del pedido: ${response.mensaje}');
  229. return true;
  230. }
  231. } else {
  232. print('No se encontraron pedidos no sincronizados.');
  233. return false;
  234. }
  235. }
  236. Future<void> actualizarPedidoSincronizado(
  237. int idPedido, int idWeb, String sincronizado) async {
  238. var db = await RepoService().db;
  239. await db!.update(
  240. 'Pedido',
  241. {
  242. 'idWeb': idWeb,
  243. 'sincronizado': sincronizado,
  244. },
  245. where: 'id = ?',
  246. whereArgs: [idPedido],
  247. );
  248. }
  249. Future<List<Pedido>> fetchAllLocalPedidosOrdenadosPorFecha() async {
  250. setIsLoading(true);
  251. RepoService<Pedido> repoPedido = RepoService<Pedido>();
  252. List<Pedido> allPedidos =
  253. await repoPedido.obtenerPedidosOrdenadosPorFecha();
  254. setIsLoading(false);
  255. return allPedidos;
  256. }
  257. }
  258. Future<Map<String, dynamic>> prepararPedidoParaApi(Pedido pedido) async {
  259. String? claveSucursal =
  260. await RepoService().obtenerClaveSucursalSeleccionada();
  261. Map<String, dynamic> apiMap = pedido.toApi();
  262. apiMap['claveSucursal'] = claveSucursal;
  263. if (pedido.idWeb != null && pedido.idWeb! > 0) {
  264. apiMap['idWeb'] = pedido.idWeb;
  265. }
  266. return apiMap;
  267. }