OscarGil03 5 kuukautta sitten
vanhempi
commit
e937f2d6b8

+ 47 - 0
lib/services/repo_service.dart

@@ -706,6 +706,53 @@ class RepoService<T> {
     }
   }
 
+  Future<int> guardarPedidoProducto(PedidoProducto pedidoProducto) async {
+    try {
+      var dbClient = await db;
+
+      // Busca registros existentes
+      List<Map<String, dynamic>> existingRecords = await dbClient!.query(
+        'PedidoProducto',
+        where: 'idPedido = ? AND idProducto = ?',
+        whereArgs: [pedidoProducto.idPedido, pedidoProducto.idProducto],
+      );
+
+      if (existingRecords.isNotEmpty) {
+        // Obtiene el ID existente
+        int existingId = existingRecords.first['id'] as int;
+
+        // Clona el mapa JSON y elimina el campo 'id' para la actualización
+        Map<String, dynamic> dataToUpdate = Map.from(pedidoProducto.toJson());
+        dataToUpdate.remove('id');
+
+        // Actualiza el registro
+        await dbClient.update(
+          'PedidoProducto',
+          dataToUpdate,
+          where: 'id = ?',
+          whereArgs: [existingId],
+        );
+
+        print(
+            "Registro actualizado para idPedido: ${pedidoProducto.idPedido}, idProducto: ${pedidoProducto.idProducto}");
+        return existingId;
+      } else {
+        // Inserta un nuevo registro eliminando el campo 'id' antes de insertar
+        Map<String, dynamic> dataToInsert = Map.from(pedidoProducto.toJson());
+        dataToInsert.remove('id');
+
+        int id = await dbClient.insert('PedidoProducto', dataToInsert);
+
+        print(
+            "Registro insertado para idPedido: ${pedidoProducto.idPedido}, idProducto: ${pedidoProducto.idProducto}");
+        return id;
+      }
+    } catch (e) {
+      print('Error al guardar PedidoProducto: $e');
+      return 0;
+    }
+  }
+
   void asignarFechasLocalmente(Basico model) {
     DateTime ahora = DateTime.now();
     if (model.creado == null) {

+ 58 - 1
lib/viewmodels/pedido_view_model.dart

@@ -1,3 +1,4 @@
+import 'package:collection/collection.dart';
 import 'package:flutter/material.dart';
 import 'package:intl/intl.dart';
 import 'package:sqflite/sqflite.dart';
@@ -92,6 +93,62 @@ class PedidoViewModel extends ChangeNotifier {
     }
   }
 
+  Future<bool> guardarPedidoConProductos({
+    required Pedido pedido,
+    required List<ItemCarrito> carrito,
+  }) async {
+    try {
+      RepoService<Pedido> repoPedido = RepoService<Pedido>();
+      RepoService<PedidoProducto> repoPedidoProducto =
+          RepoService<PedidoProducto>();
+      RepoService<PedidoProductoTopping> repoPedidoProductoTopping =
+          RepoService<PedidoProductoTopping>();
+
+      // Guardar el pedido en la base de datos
+      if (pedido.id == null || pedido.id == 0) {
+        int nextFolio = await repoPedido.obtenerProximoFolio();
+        pedido.folio = nextFolio;
+        pedido.id = await repoPedido.guardarLocal(pedido);
+      } else {
+        await repoPedido.guardar(pedido);
+      }
+
+      // Manejar los productos del carrito
+      for (var item in carrito) {
+        PedidoProducto pedidoProducto = PedidoProducto(
+          idPedido: pedido.id,
+          idProducto: item.producto.id,
+          cantidad: item.cantidad,
+          costoUnitario: item.producto.precio.toString(),
+          sincronizado: null,
+        );
+
+        // Guardar o actualizar el producto
+        int idPedidoProducto =
+            await repoPedidoProducto.guardarPedidoProducto(pedidoProducto);
+
+        // Manejar los toppings seleccionados
+        for (var entry in item.selectedToppings.entries) {
+          int categoriaId = entry.key;
+          for (int toppingId in entry.value) {
+            PedidoProductoTopping topping = PedidoProductoTopping(
+              idPedidoProducto: idPedidoProducto,
+              idTopping: toppingId,
+              idCategoria: categoriaId,
+            );
+            await repoPedidoProductoTopping.guardarLocal(topping);
+          }
+        }
+      }
+
+      notifyListeners();
+      return true;
+    } catch (e) {
+      print("Error al guardar el pedido con productos: $e");
+      return false;
+    }
+  }
+
   Future<void> fetchLocalPedidos({int page = 1}) async {
     _isLoading = true;
     _currentPage = page;
@@ -267,7 +324,7 @@ class PedidoViewModel extends ChangeNotifier {
       Map<String, dynamic> pedidoJson =
           await prepararPedidoParaApi(pedidoNoSincronizado);
 
-      print('JSON enviado: $pedidoJson');
+      // print('JSON enviado: $pedidoJson');
 
       var response = ApiResponse(await BaseService()
           .post('/pos/pedido/sincronizar', body: pedidoJson));

+ 94 - 145
lib/views/pedido/pedido_form.dart

@@ -12,6 +12,7 @@ import '../../models/models.dart';
 import '../../viewmodels/viewmodels.dart';
 import 'package:collection/collection.dart';
 import '../../widgets/widgets.dart';
+import '../../services/services.dart';
 
 class PedidoForm extends StatefulWidget {
   final Pedido? pedidoExistente;
@@ -257,46 +258,6 @@ class _PedidoFormState extends State<PedidoForm> {
     await _promptForCustomerName();
   }
 
-  void _crearPedido() async {
-    if (carrito.isEmpty) {
-      _mostrarDialogoPedidoVacio();
-      return;
-    }
-
-    Pedido nuevoPedido = Pedido(
-      peticion: DateTime.now().toUtc().toIso8601String(),
-      estatus: 'NUEVO',
-      totalPedido: totalPedido,
-      descuento: selectedDescuento,
-      idUsuario: await SessionStorage().getId(),
-      productos: carrito.map((item) {
-        return PedidoProducto(
-          idProducto: item.producto.id,
-          producto: item.producto,
-          costoUnitario: item.producto.precio.toString(),
-          cantidad: item.cantidad,
-          toppings: item.selectedToppings.entries.expand((entry) {
-            return entry.value.map((toppingId) {
-              return PedidoProductoTopping(
-                idCategoria: entry.key,
-                idTopping: toppingId,
-              );
-            });
-          }).toList(),
-        );
-      }).toList(),
-    );
-
-    bool result = await Provider.of<PedidoViewModel>(context, listen: false)
-        .guardarPedidoLocal(pedido: nuevoPedido);
-
-    if (result) {
-      Navigator.of(context).pop();
-    } else {
-      print('Error al crear el pedido');
-    }
-  }
-
   void _mostrarDialogoPedidoVacio() {
     showDialog(
       context: context,
@@ -327,6 +288,10 @@ class _PedidoFormState extends State<PedidoForm> {
   }
 
   Future<void> _crearPedidoConModal() async {
+    if (carrito.isEmpty) {
+      _mostrarDialogoPedidoVacio();
+      return;
+    }
     TextEditingController nombreController = TextEditingController();
     TextEditingController descripcionController = TextEditingController();
 
@@ -440,99 +405,53 @@ class _PedidoFormState extends State<PedidoForm> {
     }
   }
 
-  Future<void> _guardarPedidoExistente() async {
+  Future<void> _guardarPedidoExistente({
+    double? cantEfectivo,
+    double? cantTarjeta,
+    double? cantTransferencia,
+    String? tipoPago,
+    String? estatus,
+  }) async {
     if (pedidoActual == null) return;
+    DateTime now = DateTime.now().toUtc();
 
     pedidoActual!.totalPedido = totalPedido;
     pedidoActual!.descuento = selectedDescuento;
+    pedidoActual!.modificado = now;
     pedidoActual!.sincronizado = null;
 
-    final Map<int, PedidoProducto> productosExistentes = {
-      for (var producto in pedidoActual!.productos)
-        producto.idProducto!: producto
-    };
-
-    for (var item in carrito) {
-      PedidoProducto? productoExistente = productosExistentes[item.producto.id];
-
-      if (productoExistente != null) {
-        print(
-            "Actualizando producto existente: ID ${productoExistente.idProducto}, cantidad previa: ${productoExistente.cantidad}, cantidad nueva: ${item.cantidad}");
-
-        productoExistente.cantidad = item.cantidad;
-        productoExistente.descuento =
-            item.producto.descuento?.toString() ?? '0';
-        productoExistente.costoUnitario = item.producto.precio.toString();
-        productoExistente.sincronizado = null;
-
-        // Actualizar los toppings, si aplica
-        for (var entry in item.selectedToppings.entries) {
-          int categoriaId = entry.key;
-          for (int toppingId in entry.value) {
-            PedidoProductoTopping? toppingExistente =
-                productoExistente.toppings.firstWhereOrNull(
-              (t) => t.idTopping == toppingId && t.idCategoria == categoriaId,
-            );
-
-            if (toppingExistente == null) {
-              print(
-                  "Añadiendo topping nuevo: Categoria ${categoriaId}, Topping ${toppingId}");
-              productoExistente.toppings.add(
-                PedidoProductoTopping(
-                  idCategoria: categoriaId,
-                  idTopping: toppingId,
-                ),
-              );
-            }
-          }
-        }
-      } else {
-        print(
-            "Añadiendo nuevo producto: ID ${item.producto.id}, cantidad: ${item.cantidad}");
-        PedidoProducto nuevoProducto = PedidoProducto(
-          idProducto: item.producto.id,
-          producto: item.producto,
-          costoUnitario: item.producto.precio.toString(),
-          descuento: item.producto.descuento?.toString() ?? '0',
-          cantidad: item.cantidad,
-          sincronizado: null,
-          toppings: item.selectedToppings.entries.expand((entry) {
-            return entry.value.map((toppingId) {
-              return PedidoProductoTopping(
-                idCategoria: entry.key,
-                idTopping: toppingId,
-              );
-            });
-          }).toList(),
-        );
-
-        pedidoActual!.productos.add(nuevoProducto);
-      }
-    }
-
-    print("Productos finales antes de guardar:");
-    pedidoActual!.productos.forEach((producto) {
-      print(
-          "Producto ID: ${producto.idProducto}, Cantidad: ${producto.cantidad}, Costo: ${producto.costoUnitario}");
-    });
+    if (cantEfectivo != null) pedidoActual!.cantEfectivo = cantEfectivo;
+    if (cantTarjeta != null) pedidoActual!.cantTarjeta = cantTarjeta;
+    if (cantTransferencia != null)
+      pedidoActual!.cantTransferencia = cantTransferencia;
+    if (tipoPago != null) pedidoActual!.tipoPago = tipoPago;
+    if (estatus != null) pedidoActual!.estatus = estatus;
 
     bool result = await Provider.of<PedidoViewModel>(context, listen: false)
-        .guardarPedidoLocal(pedido: pedidoActual!);
+        .guardarPedidoConProductos(
+      pedido: pedidoActual!,
+      carrito: carrito,
+    );
 
     if (result) {
-      print("Pedido actualizado correctamente: ID ${pedidoActual!.id}");
+      print("Pedido actualizado correctamente");
       Navigator.of(context).pop();
     } else {
-      print('Error al actualizar el pedido');
+      print("Error al actualizar el pedido");
     }
   }
 
   Future<void> _promptForCustomerName() async {
-    TextEditingController nombreController = TextEditingController();
-    TextEditingController comentarioController = TextEditingController();
     TextEditingController efectivoController = TextEditingController();
     TextEditingController tarjetaController = TextEditingController();
     TextEditingController transferenciaController = TextEditingController();
+    TextEditingController? nombreController;
+    TextEditingController? comentarioController;
+
+    if (pedidoActual == null || pedidoActual!.id == 0) {
+      nombreController = TextEditingController();
+      comentarioController = TextEditingController();
+    }
 
     faltante = totalPedido;
     bool totalCompletado = false;
@@ -564,25 +483,29 @@ class _PedidoFormState extends State<PedidoForm> {
                 style: TextStyle(fontSize: 22, fontWeight: FontWeight.w500),
               ),
               content: Container(
-                height: 600,
+                height:
+                    pedidoActual == null || pedidoActual!.id == 0 ? 600 : 400,
                 child: Column(
                   children: [
                     Expanded(
                       child: SingleChildScrollView(
                         child: Column(
                           children: [
-                            AppTextField(
-                              controller: nombreController,
-                              etiqueta: 'Nombre',
-                              hintText: "Nombre del Cliente",
-                            ),
-                            const SizedBox(height: 10),
-                            AppTextField(
-                              controller: comentarioController,
-                              etiqueta: 'Comentarios (opcional)',
-                              hintText: 'Comentarios',
-                              maxLines: 2,
-                            ),
+                            if (nombreController != null)
+                              AppTextField(
+                                controller: nombreController,
+                                etiqueta: 'Nombre',
+                                hintText: "Nombre del Cliente",
+                              ),
+                            if (comentarioController != null) ...[
+                              const SizedBox(height: 10),
+                              AppTextField(
+                                controller: comentarioController,
+                                etiqueta: 'Comentarios (opcional)',
+                                hintText: 'Comentarios',
+                                maxLines: 2,
+                              ),
+                            ],
                             const SizedBox(height: 10),
                             Align(
                               alignment: Alignment.center,
@@ -779,13 +702,23 @@ class _PedidoFormState extends State<PedidoForm> {
     );
 
     if (shouldSave ?? false) {
-      prepararPedidoActual(
-        nombreController.text,
-        comentarioController.text,
-        efectivoController,
-        tarjetaController,
-        transferenciaController,
-      );
+      if (pedidoActual != null && pedidoActual!.id != 0) {
+        await _guardarPedidoExistente(
+          cantEfectivo: double.tryParse(efectivoController.text),
+          cantTarjeta: double.tryParse(tarjetaController.text),
+          cantTransferencia: double.tryParse(transferenciaController.text),
+          tipoPago: _obtenerTipoPago(),
+          estatus: "TERMINADO",
+        );
+      } else {
+        prepararPedidoActual(
+          nombreController?.text ?? '',
+          comentarioController?.text ?? '',
+          efectivoController,
+          tarjetaController,
+          transferenciaController,
+        );
+      }
     }
   }
 
@@ -1393,19 +1326,35 @@ class _PedidoFormState extends State<PedidoForm> {
                       style: TextStyle(color: Colors.white),
                     ),
                   ),
-                ] else
-                  ElevatedButton(
-                    onPressed: () => _crearPedidoConModal(),
-                    style: ElevatedButton.styleFrom(
-                      backgroundColor: AppTheme.tertiary,
-                      textStyle: const TextStyle(fontSize: 22),
-                      fixedSize: const Size(250, 50),
+                ] else ...[
+                  if (_isMesasActive) ...[
+                    ElevatedButton(
+                      onPressed: () => _crearPedidoConModal(),
+                      style: ElevatedButton.styleFrom(
+                        backgroundColor: AppTheme.tertiary,
+                        textStyle: const TextStyle(fontSize: 22),
+                        fixedSize: const Size(250, 50),
+                      ),
+                      child: Text(
+                        'Crear Pedido',
+                        style: TextStyle(color: AppTheme.quaternary),
+                      ),
                     ),
-                    child: Text(
-                      'Crear Pedido',
-                      style: TextStyle(color: AppTheme.quaternary),
+                  ] else ...[
+                    ElevatedButton(
+                      onPressed: () => _promptForCustomerName(),
+                      style: ElevatedButton.styleFrom(
+                        backgroundColor: AppTheme.tertiary,
+                        textStyle: const TextStyle(fontSize: 22),
+                        fixedSize: const Size(250, 50),
+                      ),
+                      child: Text(
+                        'Finalizar Pedido',
+                        style: TextStyle(color: AppTheme.quaternary),
+                      ),
                     ),
-                  ),
+                  ]
+                ]
               ],
             ),
           ),

+ 4 - 1
lib/views/pedido/pedido_screen.dart

@@ -95,7 +95,10 @@ class _PedidoScreenState extends State<PedidoScreen> {
               pedidoExistente: pedidoCompleto,
             ),
           ),
-        );
+        ).then((value) async {
+          await Provider.of<PedidoViewModel>(context, listen: false)
+              .fetchLocalPedidosForScreen();
+        });
       }
     } else {
       print("Error al cargar el pedido con productos");