pedido_view_model.dart 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  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. int nextFolio = await repoPedido.obtenerProximoFolio();
  29. pedido.folio = nextFolio;
  30. int idPedido = await repoPedido.guardarLocal(pedido);
  31. if (idPedido > 0) {
  32. pedido.id = idPedido;
  33. RepoService<PedidoProducto> repoPedidoProducto =
  34. RepoService<PedidoProducto>();
  35. RepoService<PedidoProductoTopping> repoPedidoProductoTopping =
  36. RepoService<PedidoProductoTopping>();
  37. for (var producto in pedido.productos) {
  38. PedidoProducto pedidoProducto = PedidoProducto(
  39. idPedido: idPedido,
  40. idProducto: producto.idProducto,
  41. cantidad: producto.cantidad,
  42. costoUnitario: producto.costoUnitario,
  43. comentario: producto.comentario,
  44. );
  45. int idPedidoProducto =
  46. await repoPedidoProducto.guardarLocal(pedidoProducto);
  47. for (var topping in producto.toppings) {
  48. PedidoProductoTopping pedidoProductoTopping = PedidoProductoTopping(
  49. idPedidoProducto: idPedidoProducto,
  50. idTopping: topping.idTopping,
  51. );
  52. await repoPedidoProductoTopping.guardarLocal(pedidoProductoTopping);
  53. // Recuperar detalles completos del topping
  54. Producto? toppingInfo = await RepoService<Producto>()
  55. .obtenerProductoPorId(topping.idTopping!);
  56. if (toppingInfo != null) {
  57. topping.topping = toppingInfo;
  58. }
  59. }
  60. }
  61. notifyListeners();
  62. return true;
  63. } else {
  64. return false;
  65. }
  66. }
  67. Future<void> fetchLocalPedidos({int page = 1}) async {
  68. _isLoading = true;
  69. _currentPage = page;
  70. notifyListeners();
  71. RepoService<Pedido> repoPedido = RepoService<Pedido>();
  72. _totalPedidos = await repoPedido.contarPedidos();
  73. int offset = (_limit * (page - 1));
  74. List<Pedido> paginatedPedidos =
  75. await repoPedido.obtenerPedidosPaginados(_limit, offset);
  76. _pedidos = paginatedPedidos;
  77. _isLoading = false;
  78. notifyListeners();
  79. }
  80. Future<void> fetchLocalMesaPedidos({int page = 1}) async {
  81. _isLoading = true;
  82. _currentPage = page;
  83. notifyListeners();
  84. RepoService<Pedido> repoPedido = RepoService<Pedido>();
  85. _totalPedidos = await repoPedido.contarPedidos();
  86. int offset = (_limit * (page - 1));
  87. List<Pedido> paginatedPedidos =
  88. await repoPedido.obtenerMesaPedidosPaginados(_limit, offset);
  89. _pedidos = paginatedPedidos;
  90. _isLoading = false;
  91. notifyListeners();
  92. }
  93. void nextPage() {
  94. if (_currentPage < totalPages) {
  95. fetchLocalPedidosForScreen(page: _currentPage + 1);
  96. }
  97. }
  98. void previousPage() {
  99. if (_currentPage > 1) {
  100. fetchLocalPedidosForScreen(page: _currentPage - 1);
  101. }
  102. }
  103. Future<void> fetchLocalPedidosForScreen({int page = 1}) async {
  104. setIsLoading(true);
  105. RepoService<Pedido> repoPedido = RepoService<Pedido>();
  106. _currentPage = page;
  107. var db = await RepoService().db;
  108. int? count = Sqflite.firstIntValue(
  109. await db!.rawQuery('SELECT COUNT(*) FROM Pedido'));
  110. _totalPedidos = count ?? 0;
  111. int offset = (_limit * (page - 1));
  112. List<Pedido> localPedidos =
  113. await repoPedido.obtenerPedidosPaginados(_limit, offset);
  114. _pedidos = localPedidos;
  115. setIsLoading(false);
  116. notifyListeners();
  117. }
  118. Future<void> fetchLocalMesaPedidosForScreen({int page = 1}) async {
  119. setIsLoading(true);
  120. RepoService<Pedido> repoPedido = RepoService<Pedido>();
  121. _currentPage = page;
  122. var db = await RepoService().db;
  123. int? count = Sqflite.firstIntValue(
  124. await db!.rawQuery('SELECT COUNT(*) FROM Pedido'));
  125. _totalPedidos = count ?? 0;
  126. int offset = (_limit * (page - 1));
  127. List<Pedido> localPedidos =
  128. await repoPedido.obtenerMesaPedidosPaginados(_limit, offset);
  129. // List<Pedido> localPedidos =
  130. // await repoPedido.obtenerPedidosPaginados(_limit, offset);
  131. _pedidos = localPedidos;
  132. setIsLoading(false);
  133. notifyListeners();
  134. }
  135. Future<List<Pedido>> fetchAllLocalPedidos() async {
  136. setIsLoading(true);
  137. RepoService<Pedido> repoPedido = RepoService<Pedido>();
  138. List<Pedido> allPedidos = await repoPedido.obtenerTodos();
  139. setIsLoading(false);
  140. return allPedidos;
  141. }
  142. Future<List<Pedido>> fetchPedidosPorFechaSinLimit(
  143. DateTime startDate, DateTime endDate) async {
  144. setIsLoading(true);
  145. RepoService<Pedido> repoPedido = RepoService<Pedido>();
  146. List<Pedido> pedidos = await repoPedido.buscarPorFecha(startDate, endDate);
  147. setIsLoading(false);
  148. return pedidos;
  149. }
  150. Future<Pedido?> fetchPedidoConProductos(int idPedido) async {
  151. RepoService<Pedido> repoPedido = RepoService<Pedido>();
  152. Pedido? pedido = await repoPedido.obtenerPorId(idPedido);
  153. if (pedido != null) {
  154. RepoService<PedidoProducto> repoProducto = RepoService<PedidoProducto>();
  155. RepoService<Producto> repoProductoInfo = RepoService<Producto>();
  156. List<PedidoProducto> productos =
  157. await repoProducto.obtenerPorIdPedido(idPedido);
  158. for (var producto in productos) {
  159. Producto? prodInfo =
  160. await repoProductoInfo.obtenerProductoPorId(producto.idProducto!);
  161. if (prodInfo != null) {
  162. producto.producto = prodInfo;
  163. }
  164. RepoService<PedidoProductoTopping> repoTopping =
  165. RepoService<PedidoProductoTopping>();
  166. List<PedidoProductoTopping> toppings =
  167. await repoTopping.obtenerToppingsPorPedidoProducto(producto.id!);
  168. for (var topping in toppings) {
  169. Producto? toppingInfo =
  170. await repoProductoInfo.obtenerProductoPorId(topping.idTopping!);
  171. if (toppingInfo != null) {
  172. topping.topping = toppingInfo;
  173. }
  174. }
  175. producto.toppings = toppings;
  176. }
  177. pedido.productos = productos;
  178. }
  179. return pedido;
  180. }
  181. Future<void> buscarPedidosPorFolio(String folio) async {
  182. setIsLoading(true);
  183. RepoService<Pedido> repoPedido = RepoService<Pedido>();
  184. List<Pedido> localPedidos = await repoPedido.buscarPorFolio(folio);
  185. _pedidos = localPedidos;
  186. setIsLoading(false);
  187. notifyListeners();
  188. }
  189. Future<void> buscarPedidosPorFecha(
  190. DateTime startDate, DateTime endDate) async {
  191. setIsLoading(true);
  192. RepoService<Pedido> repoPedido = RepoService<Pedido>();
  193. List<Pedido> localPedidos =
  194. await repoPedido.buscarPorFecha(startDate, endDate);
  195. _pedidos = localPedidos;
  196. setIsLoading(false);
  197. notifyListeners();
  198. }
  199. Future<void> buscarPedidosPorMesa(int idMesa) async {
  200. setIsLoading(true);
  201. RepoService<Pedido> repoPedido = RepoService<Pedido>();
  202. var dbClient = await repoPedido.db;
  203. print(
  204. 'Ejecutando consulta: SELECT * FROM Pedido WHERE "idMesa" = $idMesa');
  205. List<Map<String, dynamic>> maps = await dbClient!.rawQuery('''
  206. SELECT * FROM Pedido
  207. WHERE idMesa = ?
  208. ''', [idMesa]);
  209. print('Resultado de la consulta: ${maps.length} pedidos encontrados.');
  210. List<Pedido> localPedidos = maps.map((map) => Pedido.fromJson(map)).toList();;
  211. _pedidos = localPedidos;
  212. setIsLoading(false);
  213. notifyListeners();
  214. }
  215. Future<List<Pedido>> buscarPorFecha(
  216. DateTime startDate, DateTime endDate) async {
  217. setIsLoading(true);
  218. RepoService<Pedido> repoPedido = RepoService<Pedido>();
  219. print('Consulta SQL de pedidos desde: $startDate hasta: $endDate');
  220. List<Pedido> pedidos = await repoPedido.buscarPorFecha(startDate, endDate);
  221. print('Pedidos obtenidos desde la base de datos: ${pedidos.length}');
  222. pedidos.forEach((pedido) => print(
  223. 'Pedido Folio: ${pedido.folio}, Estatus: ${pedido.estatus}, Total: ${pedido.totalPedido}'));
  224. setIsLoading(false);
  225. notifyListeners();
  226. return pedidos;
  227. }
  228. Future<void> cancelarPedido(int idPedido) async {
  229. var db = await RepoService().db;
  230. await db?.update('Pedido', {'estatus': 'CANCELADO'},
  231. where: 'id = ?', whereArgs: [idPedido]);
  232. fetchLocalPedidosForScreen();
  233. }
  234. Future<bool> sincronizarPedidos() async {
  235. List<Pedido> pedidosNoSincronizados =
  236. await fetchAllLocalPedidosOrdenadosPorFecha();
  237. if (pedidosNoSincronizados.isNotEmpty) {
  238. Pedido pedidoNoSincronizado = pedidosNoSincronizados.first;
  239. if (pedidoNoSincronizado.productos.isEmpty) {
  240. pedidoNoSincronizado =
  241. await fetchPedidoConProductos(pedidoNoSincronizado.id) ??
  242. pedidoNoSincronizado;
  243. }
  244. Map<String, dynamic> pedidoJson =
  245. await prepararPedidoParaApi(pedidoNoSincronizado);
  246. print('JSON enviado: $pedidoJson');
  247. var response = ApiResponse(await BaseService()
  248. .post('/pos/pedido/sincronizar', body: pedidoJson));
  249. if (response.isOk && response.detalle != null) {
  250. int idWeb = response.detalle!['id'];
  251. String sincronizado = response.detalle!['sincronizado'];
  252. await actualizarPedidoSincronizado(
  253. pedidoNoSincronizado.id!, idWeb, sincronizado);
  254. return true;
  255. } else {
  256. print('Error en la sincronización del pedido: ${response.mensaje}');
  257. return true;
  258. }
  259. } else {
  260. print('No se encontraron pedidos no sincronizados.');
  261. return false;
  262. }
  263. }
  264. Future<void> actualizarPedidoSincronizado(
  265. int idPedido, int idWeb, String sincronizado) async {
  266. var db = await RepoService().db;
  267. await db!.update(
  268. 'Pedido',
  269. {
  270. 'idWeb': idWeb,
  271. 'sincronizado': sincronizado,
  272. },
  273. where: 'id = ?',
  274. whereArgs: [idPedido],
  275. );
  276. }
  277. Future<List<Pedido>> fetchAllLocalPedidosOrdenadosPorFecha() async {
  278. setIsLoading(true);
  279. RepoService<Pedido> repoPedido = RepoService<Pedido>();
  280. List<Pedido> allPedidos =
  281. await repoPedido.obtenerPedidosOrdenadosPorFecha();
  282. setIsLoading(false);
  283. return allPedidos;
  284. }
  285. }
  286. Future<Map<String, dynamic>> prepararPedidoParaApi(Pedido pedido) async {
  287. String? claveSucursal = await obtenerClaveSucursal();
  288. Map<String, dynamic> apiMap = pedido.toApi();
  289. apiMap['claveSucursal'] = claveSucursal;
  290. if (pedido.idWeb != null && pedido.idWeb! > 0) {
  291. apiMap['idWeb'] = pedido.idWeb;
  292. }
  293. return apiMap;
  294. }
  295. Future<String?> obtenerClaveSucursal() async {
  296. RepoService<Variable> repoVariable = RepoService<Variable>();
  297. Variable? sucursalVariable = await repoVariable.obtenerPorNombre('Sucursal');
  298. return sucursalVariable?.clave;
  299. }