ソースを参照

sincronización

OscarGil03 8 ヶ月 前
コミット
e91012dc80

+ 26 - 0
lib/models/pedido_model.dart

@@ -21,6 +21,8 @@ class Pedido extends Basico {
   double? cantTarjeta;
   double? cantTransferencia;
   List<PedidoProducto> productos = [];
+  int? idWeb;
+  String? sincronizado;
 
   Pedido({
     super.id,
@@ -43,6 +45,8 @@ class Pedido extends Basico {
     this.cantTarjeta,
     this.cantTransferencia,
     this.productos = const [],
+    this.idWeb,
+    this.sincronizado,
   });
 
   @override
@@ -70,6 +74,26 @@ class Pedido extends Basico {
     }..addAll(super.toJson());
   }
 
+  @override
+  Map<String, dynamic> toApi() {
+    return {
+      'idLocal': id,
+      'folio': folio,
+      'estatus': estatus,
+      'comentarios': comentarios,
+      'creado': peticion,
+      'nombreCliente': nombreCliente,
+      'totalPedido': totalPedido,
+      'descuento': descuento,
+      'idCliente': idCliente,
+      'tipoPago': tipoPago,
+      'cantEfectivo': cantEfectivo,
+      'cantTarjeta': cantTarjeta,
+      'cantTransferencia': cantTransferencia,
+      'productos': productos.map((producto) => producto.toApi()).toList(),
+    }..addAll(super.toJson());
+  }
+
   Pedido.fromJson(Map<String, dynamic> json) {
     super.parseJson(json);
     id = (json['id'] as int?)!;
@@ -91,6 +115,8 @@ class Pedido extends Basico {
     cantEfectivo = Basico.parseDouble(json['cantEfectivo']);
     cantTarjeta = Basico.parseDouble(json['cantTarjeta']);
     cantTransferencia = Basico.parseDouble(json['cantTransferencia']);
+    idWeb = Basico.parseInt(json['idWeb']);
+    sincronizado = Basico.parseString(json['sincronizado']);
 
     List<PedidoProducto> _productos = [];
     if (json["productos"] != null && (json["productos"] as List).isNotEmpty) {

+ 16 - 0
lib/models/pedido_producto_model.dart

@@ -10,6 +10,8 @@ class PedidoProducto extends Basico {
   int? terminar;
   String? comentario;
   List<PedidoProductoTopping> toppings = [];
+  int? idWeb;
+  String? sincronizado;
 
   PedidoProducto({
     super.id,
@@ -22,6 +24,8 @@ class PedidoProducto extends Basico {
     this.terminar,
     this.comentario,
     this.toppings = const [],
+    this.idWeb,
+    this.sincronizado,
   });
 
   @override
@@ -38,6 +42,16 @@ class PedidoProducto extends Basico {
     }..addAll(super.toJson());
   }
 
+  Map<String, dynamic> toApi() {
+    return {
+      'idProducto': idProducto,
+      'costoUnitario': costoUnitario,
+      'descuento': descuento,
+      'cantidad': cantidad,
+      'comentario': comentario,
+    };
+  }
+
   PedidoProducto.fromJson(Map<String, dynamic> json) {
     super.parseJson(json);
     idPedido = Basico.parseInt(json['idPedido']);
@@ -49,6 +63,8 @@ class PedidoProducto extends Basico {
     cantidad = Basico.parseInt(json['cantidad']);
     terminar = Basico.parseInt(json['terminar']);
     comentario = Basico.parseString(json['comentario']);
+    idWeb = Basico.parseInt(json['idWeb']);
+    sincronizado = Basico.parseString(json['sincronizado']);
     toppings = (json['toppings'] as List<dynamic>?)
             ?.map((topingJson) => PedidoProductoTopping.fromJson(
                 topingJson as Map<String, dynamic>))

+ 16 - 1
lib/services/repo_service.dart

@@ -6,7 +6,7 @@ import 'package:sqflite/sqflite.dart';
 import '../models/models.dart';
 
 class RepoService<T> {
-  static int dbVersion = 9;
+  static int dbVersion = 10;
   static String dbName = 'conalepPos7.db';
   static const String id = Basico.identificadorWeb;
   static const String idLocal = Basico.identificadorLocal;
@@ -216,6 +216,21 @@ class RepoService<T> {
           ALTER TABLE Producto ADD COLUMN toping INTEGER DEFAULT 0;
         ''');
           break;
+
+        // case 9:
+        //   await db.execute('''
+        //   ALTER TABLE Pedido ADD COLUMN idWeb INTEGER;
+        // ''');
+        //   await db.execute('''
+        //   ALTER TABLE Pedido ADD COLUMN sincronizado TEXT;
+        // ''');
+        //   await db.execute('''
+        //   ALTER TABLE PedidoProducto ADD COLUMN idWeb INTEGER;
+        // ''');
+        //   await db.execute('''
+        //   ALTER TABLE PedidoProducto ADD COLUMN sincronizado TEXT;
+        // ''');
+        //   break;
       }
       oldVersion++;
     }

+ 29 - 0
lib/viewmodels/pedido_view_model.dart

@@ -220,4 +220,33 @@ class PedidoViewModel extends ChangeNotifier {
         where: 'id = ?', whereArgs: [idPedido]);
     fetchLocalPedidosForScreen();
   }
+
+  Future<void> sincronizarPedidos() async {
+    List<Pedido> todosLosPedidos = await fetchAllLocalPedidos();
+
+    Pedido? pedidoNoSincronizado;
+
+    for (var pedido in todosLosPedidos) {
+      if (pedido.sincronizado == null || pedido.sincronizado!.isEmpty) {
+        pedidoNoSincronizado = pedido;
+        break;
+      }
+    }
+
+    if (pedidoNoSincronizado != null) {
+      if (pedidoNoSincronizado.productos.isEmpty) {
+        pedidoNoSincronizado =
+            await fetchPedidoConProductos(pedidoNoSincronizado.id) ??
+                pedidoNoSincronizado;
+      }
+
+      Map<String, dynamic> pedidoJson = pedidoNoSincronizado.toApi();
+
+      // Imprimir en consola
+      print('Sincronizando Pedido: ${pedidoJson['folio']}');
+      print(pedidoJson);
+    } else {
+      print('No se encontraron pedidos no sincronizados.');
+    }
+  }
 }

+ 15 - 0
lib/viewmodels/variable_view_model.dart

@@ -118,4 +118,19 @@ class VariableViewModel extends ChangeNotifier {
 
     return false;
   }
+
+  Future<Variable?> getVariableByClave(String clave) async {
+    var db = await RepoService().db;
+    var result = await db!.query(
+      'Variable',
+      where: 'clave = ?',
+      whereArgs: [clave],
+    );
+
+    if (result.isNotEmpty) {
+      return Variable.fromJson(result.first);
+    }
+
+    return null;
+  }
 }

+ 495 - 271
lib/views/pedido/pedido_form.dart

@@ -9,6 +9,7 @@ import '../../themes/themes.dart';
 import '../../models/models.dart';
 import '../../viewmodels/viewmodels.dart';
 import 'package:collection/collection.dart';
+import 'package:flutter/services.dart';
 
 import '../../widgets/widgets.dart';
 
@@ -166,6 +167,9 @@ class _PedidoFormState extends State<PedidoForm> {
     String errorMessage = '';
     double faltante = totalPedido;
     bool totalCompletado = false;
+    bool efectivoCompleto = false;
+    bool tarjetaCompleto = false;
+    bool transferenciaCompleto = false;
 
     void _calcularCambio(StateSetter setState) {
       double totalPagado = (double.tryParse(efectivoController.text) ?? 0) +
@@ -182,6 +186,13 @@ class _PedidoFormState extends State<PedidoForm> {
           faltante = 0;
           totalCompletado = true;
         }
+
+        // Si el total ha sido alcanzado o excedido, desactivar otros métodos de pago
+        if (totalPagado >= totalPedido) {
+          if (!efectivoSeleccionado) efectivoSeleccionado = false;
+          if (!tarjetaSeleccionada) tarjetaSeleccionada = false;
+          if (!transferenciaSeleccionada) transferenciaSeleccionada = false;
+        }
       });
     }
 
@@ -196,303 +207,516 @@ class _PedidoFormState extends State<PedidoForm> {
       _calcularCambio(setState);
     }
 
+    bool _isPaymentOptionEnabled(bool isSelected) {
+      return !totalCompletado || isSelected;
+    }
+
     bool? shouldSave = await showDialog<bool>(
       context: context,
       builder: (BuildContext context) {
         return StatefulBuilder(
           builder: (context, setState) {
-            return AlertDialog(
-              actionsPadding: EdgeInsets.fromLTRB(50, 10, 50, 30),
-              title: const Text(
-                'Finalizar Pedido',
-                style: TextStyle(fontSize: 22, fontWeight: FontWeight.w500),
-              ),
-              content: Container(
-                height: 600,
-                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,
-                            ),
-                            const SizedBox(height: 10),
-                            Align(
-                              alignment: Alignment.center,
-                              child: Text(
-                                'Métodos de pago',
-                                style: TextStyle(
-                                    fontWeight: FontWeight.bold, fontSize: 20),
-                              ),
-                            ),
-                            const SizedBox(height: 10),
-                            // Efectivo
-                            GestureDetector(
-                              onTap: () {
-                                setState(() {
-                                  efectivoSeleccionado = !efectivoSeleccionado;
-                                  if (!efectivoSeleccionado) {
-                                    efectivoController.clear();
-                                    _calcularCambio(setState);
-                                  }
-                                });
-                              },
-                              child: Row(
-                                mainAxisAlignment:
-                                    MainAxisAlignment.spaceBetween,
-                                children: [
-                                  Row(
+            return RawKeyboardListener(
+                focusNode: FocusNode(),
+                onKey: (RawKeyEvent event) {
+                  if (event.isKeyPressed(LogicalKeyboardKey.enter) &&
+                      totalCompletado) {
+                    Navigator.of(context).pop(true);
+                  }
+                },
+                child: AlertDialog(
+                  actionsPadding: EdgeInsets.fromLTRB(50, 10, 50, 30),
+                  title: const Text(
+                    'Finalizar Pedido',
+                    style: TextStyle(fontSize: 22, fontWeight: FontWeight.w500),
+                  ),
+                  content: Container(
+                    height: 600,
+                    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,
+                                ),
+                                const SizedBox(height: 10),
+                                Align(
+                                  alignment: Alignment.center,
+                                  child: Text(
+                                    'Métodos de pago',
+                                    style: TextStyle(
+                                        fontWeight: FontWeight.bold,
+                                        fontSize: 20),
+                                  ),
+                                ),
+                                const SizedBox(height: 10),
+                                // Efectivo
+                                GestureDetector(
+                                  onTap: () {
+                                    if (_isPaymentOptionEnabled(
+                                        efectivoSeleccionado)) {
+                                      setState(() {
+                                        efectivoSeleccionado =
+                                            !efectivoSeleccionado;
+                                        if (!efectivoSeleccionado) {
+                                          efectivoCompleto = false;
+                                          efectivoController.clear();
+                                          _calcularCambio(setState);
+                                        } else if (efectivoCompleto) {
+                                          efectivoController.text =
+                                              totalPedido.toStringAsFixed(2);
+                                          _calcularCambio(setState);
+                                        }
+                                      });
+                                    }
+                                  },
+                                  child: Row(
+                                    mainAxisAlignment:
+                                        MainAxisAlignment.spaceBetween,
+                                    crossAxisAlignment:
+                                        CrossAxisAlignment.center,
                                     children: [
-                                      Checkbox(
-                                        activeColor: AppTheme.primary,
-                                        value: efectivoSeleccionado,
-                                        onChanged: (totalCompletado &&
-                                                !efectivoSeleccionado)
-                                            ? null
-                                            : (bool? value) {
-                                                setState(() {
-                                                  efectivoSeleccionado =
-                                                      value ?? false;
-                                                  if (!efectivoSeleccionado) {
-                                                    efectivoController.clear();
-                                                    _calcularCambio(setState);
+                                      Row(
+                                        children: [
+                                          Checkbox(
+                                            activeColor: AppTheme.primary,
+                                            value: efectivoSeleccionado,
+                                            onChanged: _isPaymentOptionEnabled(
+                                                    efectivoSeleccionado)
+                                                ? (bool? value) {
+                                                    setState(() {
+                                                      efectivoSeleccionado =
+                                                          value ?? false;
+                                                      if (!efectivoSeleccionado) {
+                                                        efectivoCompleto =
+                                                            false;
+                                                        efectivoController
+                                                            .clear();
+                                                        _calcularCambio(
+                                                            setState);
+                                                      } else if (efectivoCompleto) {
+                                                        efectivoController
+                                                                .text =
+                                                            totalPedido
+                                                                .toStringAsFixed(
+                                                                    2);
+                                                        _calcularCambio(
+                                                            setState);
+                                                      }
+                                                    });
                                                   }
-                                                });
-                                              },
-                                      ),
-                                      const Text(
-                                        "Efectivo",
-                                        style: TextStyle(
-                                            fontSize: 18,
-                                            fontWeight: FontWeight.bold),
+                                                : null,
+                                          ),
+                                          const Text(
+                                            "Efectivo",
+                                            style: TextStyle(
+                                                fontSize: 18,
+                                                fontWeight: FontWeight.bold),
+                                          ),
+                                        ],
                                       ),
+                                      if (efectivoSeleccionado)
+                                        SizedBox(
+                                          width: 180,
+                                          child: Row(
+                                            crossAxisAlignment:
+                                                CrossAxisAlignment.start,
+                                            children: [
+                                              Column(
+                                                children: [
+                                                  const Text('Exacto',
+                                                      style: TextStyle(
+                                                          fontSize: 18,
+                                                          fontWeight:
+                                                              FontWeight.bold,
+                                                          color: Colors.black)),
+                                                  const SizedBox(
+                                                    height: 17,
+                                                  ),
+                                                  Checkbox(
+                                                    activeColor:
+                                                        AppTheme.primary,
+                                                    value: efectivoCompleto,
+                                                    onChanged:
+                                                        efectivoSeleccionado
+                                                            ? (bool? value) {
+                                                                setState(() {
+                                                                  efectivoCompleto =
+                                                                      value ??
+                                                                          false;
+                                                                  if (efectivoCompleto) {
+                                                                    efectivoController
+                                                                            .text =
+                                                                        totalPedido
+                                                                            .toStringAsFixed(2);
+                                                                    _calcularCambio(
+                                                                        setState);
+                                                                  } else {
+                                                                    efectivoController
+                                                                        .clear();
+                                                                    _calcularCambio(
+                                                                        setState);
+                                                                  }
+                                                                });
+                                                              }
+                                                            : null,
+                                                  ),
+                                                ],
+                                              ),
+                                              const SizedBox(
+                                                width: 5,
+                                              ),
+                                              Expanded(
+                                                child: AppTextField(
+                                                  controller:
+                                                      efectivoController,
+                                                  etiqueta: 'Cantidad',
+                                                  hintText: '0.00',
+                                                  keyboardType:
+                                                      TextInputType.number,
+                                                  onChanged: (value) =>
+                                                      _calcularCambio(setState),
+                                                ),
+                                              ),
+                                            ],
+                                          ),
+                                        ),
                                     ],
                                   ),
-                                  if (efectivoSeleccionado)
-                                    SizedBox(
-                                      width: 150,
-                                      child: AppTextField(
-                                        controller: efectivoController,
-                                        etiqueta: 'Cantidad',
-                                        hintText: '0.00',
-                                        keyboardType: TextInputType.number,
-                                        onChanged: (value) =>
-                                            _calcularCambio(setState),
-                                      ),
-                                    ),
-                                ],
-                              ),
-                            ),
-                            const SizedBox(height: 10),
-                            // Tarjeta
-                            GestureDetector(
-                              onTap: () {
-                                setState(() {
-                                  tarjetaSeleccionada = !tarjetaSeleccionada;
-                                  if (!tarjetaSeleccionada) {
-                                    tarjetaController.clear();
-                                    _calcularCambio(setState);
-                                  }
-                                });
-                              },
-                              child: Row(
-                                mainAxisAlignment:
-                                    MainAxisAlignment.spaceBetween,
-                                children: [
-                                  Row(
+                                ),
+                                const SizedBox(height: 10),
+                                // Tarjeta
+                                GestureDetector(
+                                  onTap: () {
+                                    if (_isPaymentOptionEnabled(
+                                        tarjetaSeleccionada)) {
+                                      setState(() {
+                                        tarjetaSeleccionada =
+                                            !tarjetaSeleccionada;
+                                        if (!tarjetaSeleccionada) {
+                                          tarjetaController.clear();
+                                          _calcularCambio(setState);
+                                        }
+                                      });
+                                    }
+                                  },
+                                  child: Row(
+                                    mainAxisAlignment:
+                                        MainAxisAlignment.spaceBetween,
+                                    crossAxisAlignment:
+                                        CrossAxisAlignment.center,
                                     children: [
-                                      Checkbox(
-                                        activeColor: AppTheme.primary,
-                                        value: tarjetaSeleccionada,
-                                        onChanged: (totalCompletado &&
-                                                !tarjetaSeleccionada)
-                                            ? null
-                                            : (bool? value) {
-                                                setState(() {
-                                                  tarjetaSeleccionada =
-                                                      value ?? false;
-                                                  if (!tarjetaSeleccionada) {
-                                                    tarjetaController.clear();
-                                                    _calcularCambio(setState);
+                                      Row(
+                                        children: [
+                                          Checkbox(
+                                            activeColor: AppTheme.primary,
+                                            value: tarjetaSeleccionada,
+                                            onChanged: _isPaymentOptionEnabled(
+                                                    tarjetaSeleccionada)
+                                                ? (bool? value) {
+                                                    setState(() {
+                                                      tarjetaSeleccionada =
+                                                          value ?? false;
+                                                      if (!tarjetaSeleccionada) {
+                                                        tarjetaController
+                                                            .clear();
+                                                        _calcularCambio(
+                                                            setState);
+                                                      }
+                                                    });
                                                   }
-                                                });
-                                              },
-                                      ),
-                                      const Text(
-                                        "Tarjeta",
-                                        style: TextStyle(
-                                            fontSize: 18,
-                                            fontWeight: FontWeight.bold),
+                                                : null,
+                                          ),
+                                          const Text(
+                                            "Tarjeta",
+                                            style: TextStyle(
+                                                fontSize: 18,
+                                                fontWeight: FontWeight.bold),
+                                          ),
+                                        ],
                                       ),
+                                      if (tarjetaSeleccionada)
+                                        SizedBox(
+                                          width: 180,
+                                          child: Row(
+                                            crossAxisAlignment:
+                                                CrossAxisAlignment.start,
+                                            children: [
+                                              Column(
+                                                children: [
+                                                  const Text('Exacto',
+                                                      style: TextStyle(
+                                                          fontSize: 18,
+                                                          fontWeight:
+                                                              FontWeight.bold,
+                                                          color: Colors.black)),
+                                                  const SizedBox(
+                                                    height: 17,
+                                                  ),
+                                                  Checkbox(
+                                                    activeColor:
+                                                        AppTheme.primary,
+                                                    value: tarjetaCompleto,
+                                                    onChanged:
+                                                        tarjetaSeleccionada
+                                                            ? (bool? value) {
+                                                                setState(() {
+                                                                  tarjetaCompleto =
+                                                                      value ??
+                                                                          false;
+                                                                  if (tarjetaCompleto) {
+                                                                    tarjetaController
+                                                                            .text =
+                                                                        totalPedido
+                                                                            .toStringAsFixed(2);
+                                                                    _calcularCambio(
+                                                                        setState);
+                                                                  } else {
+                                                                    tarjetaController
+                                                                        .clear();
+                                                                    _calcularCambio(
+                                                                        setState);
+                                                                  }
+                                                                });
+                                                              }
+                                                            : null,
+                                                  ),
+                                                ],
+                                              ),
+                                              const SizedBox(
+                                                width: 5,
+                                              ),
+                                              Expanded(
+                                                child: AppTextField(
+                                                  controller: tarjetaController,
+                                                  etiqueta: 'Cantidad',
+                                                  hintText: '0.00',
+                                                  keyboardType:
+                                                      TextInputType.number,
+                                                  onChanged: (value) {
+                                                    _validarCantidad(setState,
+                                                        tarjetaController);
+                                                  },
+                                                ),
+                                              ),
+                                            ],
+                                          ),
+                                        ),
                                     ],
                                   ),
-                                  if (tarjetaSeleccionada)
-                                    SizedBox(
-                                      width: 150,
-                                      child: AppTextField(
-                                        controller: tarjetaController,
-                                        etiqueta: 'Cantidad',
-                                        hintText: '0.00',
-                                        keyboardType: TextInputType.number,
-                                        onChanged: (value) {
-                                          _validarCantidad(
-                                              setState, tarjetaController);
-                                        },
-                                      ),
-                                    ),
-                                ],
-                              ),
-                            ),
-                            const SizedBox(height: 10),
-                            // Transferencia
-                            GestureDetector(
-                              onTap: () {
-                                setState(() {
-                                  transferenciaSeleccionada =
-                                      !transferenciaSeleccionada;
-                                  if (!transferenciaSeleccionada) {
-                                    transferenciaController.clear();
-                                    _calcularCambio(setState);
-                                  }
-                                });
-                              },
-                              child: Row(
-                                mainAxisAlignment:
-                                    MainAxisAlignment.spaceBetween,
-                                children: [
-                                  Row(
+                                ),
+                                const SizedBox(height: 10),
+                                // Transferencia
+                                GestureDetector(
+                                  onTap: () {
+                                    if (_isPaymentOptionEnabled(
+                                        transferenciaSeleccionada)) {
+                                      setState(() {
+                                        transferenciaSeleccionada =
+                                            !transferenciaSeleccionada;
+                                        if (!transferenciaSeleccionada) {
+                                          transferenciaController.clear();
+                                          _calcularCambio(setState);
+                                        }
+                                      });
+                                    }
+                                  },
+                                  child: Row(
+                                    mainAxisAlignment:
+                                        MainAxisAlignment.spaceBetween,
+                                    crossAxisAlignment:
+                                        CrossAxisAlignment.center,
                                     children: [
-                                      Checkbox(
-                                        activeColor: AppTheme.primary,
-                                        value: transferenciaSeleccionada,
-                                        onChanged: (totalCompletado &&
-                                                !transferenciaSeleccionada)
-                                            ? null
-                                            : (bool? value) {
-                                                setState(() {
-                                                  transferenciaSeleccionada =
-                                                      value ?? false;
-                                                  if (!transferenciaSeleccionada) {
-                                                    transferenciaController
-                                                        .clear();
-                                                    _calcularCambio(setState);
+                                      Row(
+                                        children: [
+                                          Checkbox(
+                                            activeColor: AppTheme.primary,
+                                            value: transferenciaSeleccionada,
+                                            onChanged: _isPaymentOptionEnabled(
+                                                    transferenciaSeleccionada)
+                                                ? (bool? value) {
+                                                    setState(() {
+                                                      transferenciaSeleccionada =
+                                                          value ?? false;
+                                                      if (!transferenciaSeleccionada) {
+                                                        transferenciaController
+                                                            .clear();
+                                                        _calcularCambio(
+                                                            setState);
+                                                      }
+                                                    });
                                                   }
-                                                });
-                                              },
-                                      ),
-                                      const Text(
-                                        "Transferencia",
-                                        style: TextStyle(
-                                            fontSize: 18,
-                                            fontWeight: FontWeight.bold),
+                                                : null,
+                                          ),
+                                          const Text(
+                                            "Transferencia",
+                                            style: TextStyle(
+                                                fontSize: 18,
+                                                fontWeight: FontWeight.bold),
+                                          ),
+                                        ],
                                       ),
+                                      if (transferenciaSeleccionada)
+                                        SizedBox(
+                                          width: 180,
+                                          child: Row(
+                                            crossAxisAlignment:
+                                                CrossAxisAlignment.start,
+                                            children: [
+                                              Column(
+                                                children: [
+                                                  const Text('Exacto',
+                                                      style: TextStyle(
+                                                          fontSize: 18,
+                                                          fontWeight:
+                                                              FontWeight.bold,
+                                                          color: Colors.black)),
+                                                  const SizedBox(
+                                                    height: 17,
+                                                  ),
+                                                  Checkbox(
+                                                    activeColor:
+                                                        AppTheme.primary,
+                                                    value:
+                                                        transferenciaCompleto,
+                                                    onChanged:
+                                                        transferenciaSeleccionada
+                                                            ? (bool? value) {
+                                                                setState(() {
+                                                                  transferenciaCompleto =
+                                                                      value ??
+                                                                          false;
+                                                                  if (transferenciaCompleto) {
+                                                                    transferenciaController
+                                                                            .text =
+                                                                        totalPedido
+                                                                            .toStringAsFixed(2);
+                                                                    _calcularCambio(
+                                                                        setState);
+                                                                  } else {
+                                                                    transferenciaController
+                                                                        .clear();
+                                                                    _calcularCambio(
+                                                                        setState);
+                                                                  }
+                                                                });
+                                                              }
+                                                            : null,
+                                                  ),
+                                                ],
+                                              ),
+                                              const SizedBox(
+                                                width: 5,
+                                              ),
+                                              Expanded(
+                                                child: AppTextField(
+                                                  controller:
+                                                      transferenciaController,
+                                                  etiqueta: 'Cantidad',
+                                                  hintText: '0.00',
+                                                  keyboardType:
+                                                      TextInputType.number,
+                                                  onChanged: (value) {
+                                                    _validarCantidad(setState,
+                                                        transferenciaController);
+                                                  },
+                                                ),
+                                              ),
+                                            ],
+                                          ),
+                                        ),
                                     ],
                                   ),
-                                  if (transferenciaSeleccionada)
-                                    SizedBox(
-                                      width: 150,
-                                      child: AppTextField(
-                                        controller: transferenciaController,
-                                        etiqueta: 'Cantidad',
-                                        hintText: '0.00',
-                                        keyboardType: TextInputType.number,
-                                        onChanged: (value) {
-                                          _validarCantidad(setState,
-                                              transferenciaController);
-                                        },
-                                      ),
-                                    ),
-                                ],
-                              ),
-                            ),
-                            const SizedBox(height: 10),
-                            // Mostrar el total del pedido y la cantidad faltante
-                            Align(
-                              alignment: Alignment.centerRight,
-                              child: Column(
-                                  crossAxisAlignment: CrossAxisAlignment.end,
-                                  children: [
-                                    Text(
-                                      'Total del pedido: \$${totalPedido.toStringAsFixed(2)}',
-                                      style: const TextStyle(
-                                          fontWeight: FontWeight.bold,
-                                          fontSize: 18),
-                                    ),
-                                    if (faltante > 0)
-                                      Text(
-                                        'Faltante: \$${faltante.toStringAsFixed(2)}',
-                                        style: const TextStyle(
-                                            color: Colors.red,
-                                            fontSize: 18,
-                                            fontWeight: FontWeight.bold),
-                                      )
-                                    else if (cambio > 0)
-                                      Text(
-                                          'Cambio: \$${cambio.toStringAsFixed(2)}',
+                                ),
+                                const SizedBox(height: 10),
+                                // Mostrar el total del pedido y la cantidad faltante
+                                Align(
+                                  alignment: Alignment.centerRight,
+                                  child: Column(
+                                      crossAxisAlignment:
+                                          CrossAxisAlignment.end,
+                                      children: [
+                                        Text(
+                                          'Total del pedido: \$${totalPedido.toStringAsFixed(2)}',
                                           style: const TextStyle(
-                                              color: Colors.green,
-                                              fontSize: 18,
-                                              fontWeight: FontWeight.bold)),
-                                  ]),
+                                              fontWeight: FontWeight.bold,
+                                              fontSize: 18),
+                                        ),
+                                        if (faltante > 0)
+                                          Text(
+                                            'Faltante: \$${faltante.toStringAsFixed(2)}',
+                                            style: const TextStyle(
+                                                color: Colors.red,
+                                                fontSize: 18,
+                                                fontWeight: FontWeight.bold),
+                                          )
+                                        else if (cambio > 0)
+                                          Text(
+                                              'Cambio: \$${cambio.toStringAsFixed(2)}',
+                                              style: const TextStyle(
+                                                  color: Colors.green,
+                                                  fontSize: 18,
+                                                  fontWeight: FontWeight.bold)),
+                                      ]),
+                                ),
+                              ],
                             ),
-                          ],
-                        ),
-                      ),
-                    ),
-                    // Aquí mantenemos los botones fijos
-                    Row(
-                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
-                      children: [
-                        TextButton(
-                          child: const Text('Cancelar',
-                              style: TextStyle(fontSize: 18)),
-                          onPressed: () {
-                            Navigator.of(context).pop(false);
-                          },
-                          style: ButtonStyle(
-                              padding: MaterialStatePropertyAll(
-                                  EdgeInsets.fromLTRB(30, 20, 30, 20)),
-                              backgroundColor:
-                                  MaterialStatePropertyAll(Colors.red),
-                              foregroundColor:
-                                  MaterialStatePropertyAll(AppTheme.secondary)),
+                          ),
                         ),
-                        const SizedBox(width: 100),
-                        TextButton(
-                          child: const Text('Guardar',
-                              style: TextStyle(fontSize: 18)),
-                          onPressed: totalCompletado
-                              ? () {
-                                  Navigator.of(context).pop(true);
-                                }
-                              : null,
-                          style: ButtonStyle(
-                              padding: MaterialStatePropertyAll(
-                                  EdgeInsets.fromLTRB(30, 20, 30, 20)),
-                              backgroundColor: MaterialStatePropertyAll(
-                                  totalCompletado
-                                      ? AppTheme.tertiary
-                                      : Colors.grey),
-                              foregroundColor: MaterialStatePropertyAll(
-                                  AppTheme.quaternary)),
+                        // Aquí mantenemos los botones fijos
+                        Row(
+                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                          children: [
+                            TextButton(
+                              child: const Text('Cancelar',
+                                  style: TextStyle(fontSize: 18)),
+                              onPressed: () {
+                                Navigator.of(context).pop(false);
+                              },
+                              style: ButtonStyle(
+                                  padding: MaterialStatePropertyAll(
+                                      EdgeInsets.fromLTRB(30, 20, 30, 20)),
+                                  backgroundColor:
+                                      MaterialStatePropertyAll(Colors.red),
+                                  foregroundColor: MaterialStatePropertyAll(
+                                      AppTheme.secondary)),
+                            ),
+                            const SizedBox(width: 100),
+                            TextButton(
+                              child: const Text('Guardar',
+                                  style: TextStyle(fontSize: 18)),
+                              onPressed: totalCompletado
+                                  ? () {
+                                      Navigator.of(context).pop(true);
+                                    }
+                                  : null,
+                              style: ButtonStyle(
+                                  padding: MaterialStatePropertyAll(
+                                      EdgeInsets.fromLTRB(30, 20, 30, 20)),
+                                  backgroundColor: MaterialStatePropertyAll(
+                                      totalCompletado
+                                          ? AppTheme.tertiary
+                                          : Colors.grey),
+                                  foregroundColor: MaterialStatePropertyAll(
+                                      AppTheme.quaternary)),
+                            ),
+                          ],
                         ),
                       ],
                     ),
-                  ],
-                ),
-              ),
-            );
+                  ),
+                ));
           },
         );
       },

+ 214 - 166
lib/views/pedido/pedido_screen.dart

@@ -99,6 +99,10 @@ class _PedidoScreenState extends State<PedidoScreen> {
     TextStyle estilo = const TextStyle(fontWeight: FontWeight.bold);
     List<DataRow> registros = [];
     for (Pedido item in pvm.pedidos) {
+      final sincronizadoStatus = item.sincronizado?.isEmpty ?? true
+          ? "No Sincronizado"
+          : item.sincronizado;
+
       registros.add(DataRow(cells: [
         DataCell(
             Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
@@ -198,6 +202,10 @@ class _PedidoScreenState extends State<PedidoScreen> {
           Text(item.peticion ?? "Sin fecha"),
           onTap: () => go(item),
         ),
+        DataCell(
+          Text(sincronizadoStatus!),
+          onTap: () => go(item),
+        ),
       ]));
     }
 
@@ -216,181 +224,221 @@ class _PedidoScreenState extends State<PedidoScreen> {
             ),
           ],
           iconTheme: IconThemeData(color: AppTheme.secondary)),
-      floatingActionButton: FloatingActionButton.extended(
-        onPressed: () async {
-          await Navigator.push(
-            context,
-            MaterialPageRoute(
-              builder: (context) => PedidoForm(),
-            ),
-          ).then((_) => Provider.of<PedidoViewModel>(context, listen: false)
-              .fetchLocalPedidosForScreen());
-        },
-        icon: Icon(Icons.add, size: 30, color: AppTheme.quaternary),
-        label: Text(
-          "Agregar Pedido",
-          style: TextStyle(fontSize: 20, color: AppTheme.quaternary),
-        ),
-        shape: RoundedRectangleBorder(
-          borderRadius: BorderRadius.circular(8),
-        ),
-        materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
-        backgroundColor: AppTheme.tertiary,
-      ),
-      body: Column(
+      body: Stack(
         children: [
-          Expanded(
-            child: ListView(
-              padding: const EdgeInsets.fromLTRB(8, 0, 8, 0),
-              children: [
-                const SizedBox(height: 8),
-                clase.tarjeta(
-                  Padding(
-                    padding: const EdgeInsets.all(8.0),
-                    child: LayoutBuilder(
-                      builder: (context, constraints) {
-                        if (screenWidth > 1000) {
-                          return Row(
-                            crossAxisAlignment: CrossAxisAlignment.end,
-                            children: [
-                              Expanded(
-                                flex: 7,
-                                child: _buildDateRangePicker(),
-                              ),
-                              const SizedBox(width: 5),
-                              botonBuscar()
-                            ],
-                          );
-                        } else {
-                          return Column(
-                            children: [
-                              Row(
-                                children: [_buildDateRangePicker()],
-                              ),
-                              Row(
-                                children: [botonBuscar()],
-                              ),
-                            ],
-                          );
-                        }
-                      },
+          Column(
+            children: [
+              Expanded(
+                child: ListView(
+                  padding: const EdgeInsets.fromLTRB(8, 0, 8, 0),
+                  children: [
+                    const SizedBox(height: 8),
+                    clase.tarjeta(
+                      Padding(
+                        padding: const EdgeInsets.all(8.0),
+                        child: LayoutBuilder(
+                          builder: (context, constraints) {
+                            if (screenWidth > 1000) {
+                              return Row(
+                                crossAxisAlignment: CrossAxisAlignment.end,
+                                children: [
+                                  Expanded(
+                                    flex: 7,
+                                    child: _buildDateRangePicker(),
+                                  ),
+                                  const SizedBox(width: 5),
+                                  botonBuscar()
+                                ],
+                              );
+                            } else {
+                              return Column(
+                                children: [
+                                  Row(
+                                    children: [_buildDateRangePicker()],
+                                  ),
+                                  Row(
+                                    children: [botonBuscar()],
+                                  ),
+                                ],
+                              );
+                            }
+                          },
+                        ),
+                      ),
                     ),
-                  ),
-                ),
-                const SizedBox(height: 8),
-                pvm.isLoading
-                    ? const Center(child: CircularProgressIndicator())
-                    : Container(),
-                clase.tarjeta(
-                  Column(
-                    children: [
-                      LayoutBuilder(builder: (context, constraints) {
-                        return SingleChildScrollView(
-                          scrollDirection: Axis.vertical,
-                          child: Scrollbar(
-                            controller: horizontalScrollController,
-                            interactive: true,
-                            thumbVisibility: true,
-                            thickness: 10.0,
-                            child: SingleChildScrollView(
-                              controller: horizontalScrollController,
-                              scrollDirection: Axis.horizontal,
-                              child: ConstrainedBox(
-                                constraints: BoxConstraints(
-                                    minWidth: isMobile
-                                        ? constraints.maxWidth
-                                        : screenWidth),
-                                child: DataTable(
-                                  columnSpacing: columnSpacing,
-                                  sortAscending: true,
-                                  sortColumnIndex: 1,
-                                  columns: [
-                                    DataColumn(label: Text(" ", style: estilo)),
-                                    DataColumn(
-                                        label: Text("FOLIO", style: estilo)),
-                                    DataColumn(
-                                        label: Text("NOMBRE", style: estilo)),
-                                    DataColumn(
-                                        label:
-                                            Text("COMENTARIOS", style: estilo)),
-                                    DataColumn(
-                                        label: Text("ESTATUS", style: estilo)),
-                                    DataColumn(
-                                        label: Text("FECHA", style: estilo)),
-                                  ],
-                                  rows: registros,
+                    const SizedBox(height: 8),
+                    pvm.isLoading
+                        ? const Center(child: CircularProgressIndicator())
+                        : Container(),
+                    clase.tarjeta(
+                      Column(
+                        children: [
+                          LayoutBuilder(builder: (context, constraints) {
+                            return SingleChildScrollView(
+                              scrollDirection: Axis.vertical,
+                              child: Scrollbar(
+                                controller: horizontalScrollController,
+                                interactive: true,
+                                thumbVisibility: true,
+                                thickness: 10.0,
+                                child: SingleChildScrollView(
+                                  controller: horizontalScrollController,
+                                  scrollDirection: Axis.horizontal,
+                                  child: ConstrainedBox(
+                                    constraints: BoxConstraints(
+                                        minWidth: isMobile
+                                            ? constraints.maxWidth
+                                            : screenWidth),
+                                    child: DataTable(
+                                      columnSpacing: columnSpacing,
+                                      sortAscending: true,
+                                      sortColumnIndex: 1,
+                                      columns: [
+                                        DataColumn(
+                                            label: Text(" ", style: estilo)),
+                                        DataColumn(
+                                            label:
+                                                Text("FOLIO", style: estilo)),
+                                        DataColumn(
+                                            label:
+                                                Text("NOMBRE", style: estilo)),
+                                        DataColumn(
+                                            label: Text("COMENTARIOS",
+                                                style: estilo)),
+                                        DataColumn(
+                                            label:
+                                                Text("ESTATUS", style: estilo)),
+                                        DataColumn(
+                                            label:
+                                                Text("FECHA", style: estilo)),
+                                        DataColumn(
+                                            label: Text("SINCRONIZADO",
+                                                style: estilo)),
+                                      ],
+                                      rows: registros,
+                                    ),
+                                  ),
                                 ),
                               ),
-                            ),
-                          ),
-                        );
-                      }),
-                    ],
-                  ),
-                ),
-                const SizedBox(height: 15),
-                if (!pvm.isLoading)
-                  Row(
-                    mainAxisAlignment: MainAxisAlignment.center,
-                    children: [
-                      TextButton(
-                        onPressed:
-                            pvm.currentPage > 1 ? pvm.previousPage : null,
-                        child: Text('Anterior'),
-                        style: ButtonStyle(
-                          backgroundColor:
-                              MaterialStateProperty.resolveWith<Color?>(
-                            (Set<MaterialState> states) {
-                              if (states.contains(MaterialState.disabled)) {
-                                return Colors.grey;
-                              }
-                              return AppTheme.tertiary;
-                            },
-                          ),
-                          foregroundColor:
-                              MaterialStateProperty.resolveWith<Color?>(
-                            (Set<MaterialState> states) {
-                              if (states.contains(MaterialState.disabled)) {
-                                return Colors.black;
-                              }
-                              return Colors.white;
-                            },
-                          ),
-                        ),
+                            );
+                          }),
+                        ],
                       ),
-                      SizedBox(width: 15),
-                      Text('Página ${pvm.currentPage} de ${pvm.totalPages}'),
-                      SizedBox(width: 15),
-                      TextButton(
-                        onPressed: pvm.currentPage < pvm.totalPages
-                            ? pvm.nextPage
-                            : null,
-                        child: Text('Siguiente'),
-                        style: ButtonStyle(
-                          backgroundColor:
-                              MaterialStateProperty.resolveWith<Color?>(
-                            (Set<MaterialState> states) {
-                              if (states.contains(MaterialState.disabled)) {
-                                return Colors.grey;
-                              }
-                              return AppTheme.tertiary;
-                            },
+                    ),
+                    const SizedBox(height: 15),
+                    if (!pvm.isLoading)
+                      Row(
+                        mainAxisAlignment: MainAxisAlignment.center,
+                        children: [
+                          TextButton(
+                            onPressed:
+                                pvm.currentPage > 1 ? pvm.previousPage : null,
+                            child: Text('Anterior'),
+                            style: ButtonStyle(
+                              backgroundColor:
+                                  MaterialStateProperty.resolveWith<Color?>(
+                                (Set<MaterialState> states) {
+                                  if (states.contains(MaterialState.disabled)) {
+                                    return Colors.grey;
+                                  }
+                                  return AppTheme.tertiary;
+                                },
+                              ),
+                              foregroundColor:
+                                  MaterialStateProperty.resolveWith<Color?>(
+                                (Set<MaterialState> states) {
+                                  if (states.contains(MaterialState.disabled)) {
+                                    return Colors.black;
+                                  }
+                                  return Colors.white;
+                                },
+                              ),
+                            ),
                           ),
-                          foregroundColor:
-                              MaterialStateProperty.resolveWith<Color?>(
-                            (Set<MaterialState> states) {
-                              if (states.contains(MaterialState.disabled)) {
-                                return Colors.black;
-                              }
-                              return Colors.white;
-                            },
+                          SizedBox(width: 15),
+                          Text(
+                              'Página ${pvm.currentPage} de ${pvm.totalPages}'),
+                          SizedBox(width: 15),
+                          TextButton(
+                            onPressed: pvm.currentPage < pvm.totalPages
+                                ? pvm.nextPage
+                                : null,
+                            child: Text('Siguiente'),
+                            style: ButtonStyle(
+                              backgroundColor:
+                                  MaterialStateProperty.resolveWith<Color?>(
+                                (Set<MaterialState> states) {
+                                  if (states.contains(MaterialState.disabled)) {
+                                    return Colors.grey;
+                                  }
+                                  return AppTheme.tertiary;
+                                },
+                              ),
+                              foregroundColor:
+                                  MaterialStateProperty.resolveWith<Color?>(
+                                (Set<MaterialState> states) {
+                                  if (states.contains(MaterialState.disabled)) {
+                                    return Colors.black;
+                                  }
+                                  return Colors.white;
+                                },
+                              ),
+                            ),
                           ),
-                        ),
+                        ],
                       ),
-                    ],
+                    const SizedBox(height: 15),
+                  ],
+                ),
+              ),
+            ],
+          ),
+          Positioned(
+            bottom: 16,
+            right: 16,
+            child: FloatingActionButton.extended(
+              heroTag: 'addPedido',
+              onPressed: () async {
+                await Navigator.push(
+                  context,
+                  MaterialPageRoute(
+                    builder: (context) => PedidoForm(),
                   ),
-                const SizedBox(height: 15),
-              ],
+                ).then((_) =>
+                    Provider.of<PedidoViewModel>(context, listen: false)
+                        .fetchLocalPedidosForScreen());
+              },
+              icon: Icon(Icons.add, size: 30, color: AppTheme.quaternary),
+              label: Text(
+                "Agregar Pedido",
+                style: TextStyle(fontSize: 20, color: AppTheme.quaternary),
+              ),
+              shape: RoundedRectangleBorder(
+                borderRadius: BorderRadius.circular(8),
+              ),
+              materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
+              backgroundColor: AppTheme.tertiary,
+            ),
+          ),
+          Positioned(
+            bottom: 16,
+            left: 16,
+            child: FloatingActionButton.extended(
+              heroTag: 'sincronizacion',
+              onPressed: () async {
+                await Provider.of<PedidoViewModel>(context, listen: false)
+                    .sincronizarPedidos();
+              },
+              icon: Icon(Icons.sync, size: 30, color: AppTheme.quaternary),
+              label: Text(
+                "Sincronización",
+                style: TextStyle(fontSize: 20, color: AppTheme.quaternary),
+              ),
+              shape: RoundedRectangleBorder(
+                borderRadius: BorderRadius.circular(8),
+              ),
+              materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
+              backgroundColor: AppTheme.tertiary,
             ),
           ),
         ],

+ 21 - 7
lib/views/pedido/pedido_ticket.dart

@@ -28,9 +28,9 @@ Future<void> imprimirTicketsJuntos(BuildContext context, Pedido pedido) async {
   }
 
   if (ticketCocinaActivo) {
-    pdf.addPage(
-      generarPaginaSegundoTicket(pedido),
-    );
+    final paginaSegundoTicket =
+        await generarPaginaSegundoTicket(context, pedido);
+    pdf.addPage(paginaSegundoTicket);
   }
 
   await printPdf(Uint8List.fromList(await pdf.save()));
@@ -196,26 +196,40 @@ pw.Page generarPaginaPrimerTicket(Pedido pedido, pw.MemoryImage image) {
       });
 }
 
-pw.Page generarPaginaSegundoTicket(Pedido pedido) {
+Future<pw.Page> generarPaginaSegundoTicket(
+    BuildContext context, Pedido pedido) async {
   final numberFormat = NumberFormat('#,##0.00', 'es_MX');
   double subtotal = 0;
   double totalConDescuento = 0;
   double descuento = pedido.descuento?.toDouble() ?? 0.0;
   double precioDescuento = 0;
 
+  final sucursalVariable =
+      await Provider.of<VariableViewModel>(context, listen: false)
+          .getVariableByClave('sucursal');
+  final sucursalDescripcion = sucursalVariable?.descripcion ?? '';
+
   List<pw.Widget> content = [
     pw.SizedBox(height: 20),
     pw.Text('.', style: pw.TextStyle(fontSize: 1)),
     pw.Row(
       mainAxisAlignment: pw.MainAxisAlignment.spaceAround,
       children: [
-        pw.Text('${pedido.folio}',
-            style: pw.TextStyle(fontSize: 12, fontWeight: pw.FontWeight.bold)),
-        pw.Text('${pedido.peticion}',
+        pw.Text('${pedido.folio}/ ',
             style: pw.TextStyle(fontSize: 12, fontWeight: pw.FontWeight.bold)),
+        if (sucursalDescripcion.isNotEmpty)
+          pw.Text('$sucursalDescripcion/ ',
+              style:
+                  pw.TextStyle(fontWeight: pw.FontWeight.bold, fontSize: 12)),
       ],
     ),
     pw.SizedBox(height: 5),
+    pw.Row(children: [
+      pw.Text('${pedido.peticion}',
+          style: pw.TextStyle(fontSize: 12, fontWeight: pw.FontWeight.bold)),
+    ]),
+    if (pedido.nombreCliente != null && pedido.nombreCliente!.isNotEmpty)
+      pw.SizedBox(height: 5),
     if (pedido.nombreCliente != null && pedido.nombreCliente!.isNotEmpty)
       pw.Text('Cliente: ${pedido.nombreCliente}',
           style: pw.TextStyle(fontWeight: pw.FontWeight.bold, fontSize: 12)),