Procházet zdrojové kódy

Sincronizacion productos y ajustes variables

OscarGil03 před 6 měsíci
rodič
revize
2ea88fb8e7

+ 1 - 1
lib/models/basico_model.dart

@@ -67,7 +67,7 @@ class Basico {
     return {
       'id': id,
       'idLocal': idLocal,
-      'eliminado': eliminado,
+      'eliminado': eliminado?.toIso8601String(),
     };
   }
 

+ 3 - 3
lib/models/categoria_producto_model.dart

@@ -27,9 +27,9 @@ class CategoriaProducto extends Basico {
       'descripcion': descripcion ?? '',
       'esToping': esToping ?? 0,
       'maximo': maximo ?? 0,
-      'creado': creado != null ? creado!.toIso8601String() : null,
-      'modificado': modificado != null ? modificado!.toIso8601String() : null,
-      'eliminado': eliminado != null ? eliminado!.toIso8601String() : null,
+      'creado': creado?.toIso8601String(),
+      'modificado': modificado?.toIso8601String(),
+      'eliminado': eliminado?.toIso8601String(),
     }..addAll(super.toJson());
   }
 

+ 9 - 3
lib/models/producto_model.dart

@@ -17,6 +17,7 @@ class Producto extends Basico {
   String? descuento;
   int? toping;
   List<Producto>? topings;
+  int? activo;
 
   Producto({
     super.id,
@@ -32,6 +33,7 @@ class Producto extends Basico {
     this.descuento,
     this.toping,
     this.topings,
+    this.activo,
   });
 
   @override
@@ -56,9 +58,10 @@ class Producto extends Basico {
       'codigo': codigo ?? '',
       'descuento': descuento ?? '',
       'toping': toping ?? 0,
-      'creado': creado != null ? creado!.toIso8601String() : null,
-      'modificado': modificado != null ? modificado!.toIso8601String() : null,
-      'eliminado': eliminado != null ? eliminado!.toIso8601String() : null,
+      'activo': activo ?? 0,
+      'creado': creado?.toIso8601String(),
+      'modificado': modificado?.toIso8601String(),
+      'eliminado': eliminado?.toIso8601String(),
     }..addAll(super.toJson());
   }
 
@@ -76,6 +79,7 @@ class Producto extends Basico {
       'codigo': codigo,
       'descuento': descuento,
       'toping': toping,
+      'activo': activo,
       'creado': creado != null ? creado!.toIso8601String() : null,
       'modificado': modificado != null ? modificado!.toIso8601String() : null,
       'eliminado': eliminado != null ? eliminado!.toIso8601String() : null,
@@ -97,6 +101,7 @@ class Producto extends Basico {
     verMenu = Basico.parseInt(json['verMenu']);
     codigo = Basico.parseString(json['codigo']);
     descuento = Basico.parseString(json['descuento']);
+    activo = Basico.parseInt(json['activo']);
     if (json['toping'] is bool) {
       toping = json['toping'] ? 1 : 0;
     } else {
@@ -121,6 +126,7 @@ class Producto extends Basico {
     verMenu = Basico.parseInt(json['verEnMenu']);
     codigo = Basico.parseString(json['codigo']);
     descuento = Basico.parseString(json['descuento']);
+    activo = Basico.parseInt(json['activo']);
     creado = Basico.parseDate(json['creado']);
     modificado = Basico.parseDate(json['modificado']);
     eliminado = Basico.parseDate(json['eliminado']);

+ 34 - 6
lib/services/repo_service.dart

@@ -6,7 +6,7 @@ import 'package:sqflite/sqflite.dart';
 import '../models/models.dart';
 
 class RepoService<T> {
-  static int dbVersion = 13;
+  static int dbVersion = 14;
   static String dbName = 'joshipos026.db';
   static const String id = Basico.identificadorWeb;
   static const String idLocal = Basico.identificadorLocal;
@@ -450,6 +450,16 @@ class RepoService<T> {
           ''');
 
           break;
+
+        case 12:
+          await db.execute('''
+            ALTER TABLE Producto ADD COLUMN activo INTEGER;
+          ''');
+
+        case 13:
+          await db.execute('''
+            ALTER TABLE Producto ADD COLUMN activo INTEGER;
+          ''');
       }
       oldVersion++;
     }
@@ -845,22 +855,40 @@ class RepoService<T> {
   Future<void> sincronizarProductos(List<Producto> productosApi) async {
     var db = await RepoService().db;
 
+    // Print del JSON recibido
+    print(
+        "Productos API recibidos: ${productosApi.map((e) => e.toJson()).toList()}");
+
     var productosLocalesQuery = await db!.query('Producto');
     List<Producto> productosLocales =
         productosLocalesQuery.map((e) => Producto.fromJson(e)).toList();
 
     for (var productoApi in productosApi) {
+      // Validar que el ID del producto no sea nulo
+      if (productoApi.id == null) {
+        print("Producto con ID nulo, se omite: ${productoApi.nombre}");
+        continue; // Ignorar productos sin ID
+      }
+
+      // Buscar el producto localmente
       var productoLocal = productosLocales.firstWhere(
         (producto) => producto.id == productoApi.id,
-        orElse: () => Producto(),
+        orElse: () =>
+            Producto(), // Si no existe el producto, devolver uno nuevo con id 0
       );
 
-      if (productoLocal.id != 0 &&
-          productoApi.modificado != null &&
-          productoApi.modificado!.isAfter(productoLocal.modificado!)) {
+      if (productoLocal.id == 0) {
+        print("Insertando nuevo producto: ${productoApi.nombre}");
         await RepoService().guardar(productoApi);
-      } else if (productoLocal.id == 0) {
+      } else if (productoApi.modificado != null &&
+          (productoLocal.modificado == null ||
+              productoApi.modificado!.isAfter(productoLocal.modificado!))) {
+        print("Actualizando producto: ${productoApi.nombre}");
         await RepoService().guardar(productoApi);
+      } else {
+        // Producto sin cambios
+        print(
+            "Producto sin cambios o datos insuficientes: ${productoApi.nombre}");
       }
     }
   }

+ 13 - 4
lib/views/pedido/pedido_form.dart

@@ -92,17 +92,22 @@ class _PedidoFormState extends State<PedidoForm> {
     Provider.of<DescuentoViewModel>(context, listen: false).cargarDescuentos();
   }
 
-  void _onSearchChanged(String value) {
+  void _onSearchChanged(String value) async {
     if (value.isEmpty) {
       cargarProductosPorCategoria(
           categoriaSeleccionada?.id ?? categorias.first.id);
     } else {
       setState(() {
         _estadoBusqueda = true;
-        categoriaSeleccionada = null;
       });
-      Provider.of<ProductoViewModel>(context, listen: false)
+
+      await Provider.of<ProductoViewModel>(context, listen: false)
           .fetchLocalByName(nombre: value);
+
+      setState(() {
+        productos =
+            Provider.of<ProductoViewModel>(context, listen: false).productos;
+      });
     }
   }
 
@@ -1264,9 +1269,13 @@ class _PedidoFormState extends State<PedidoForm> {
               itemCount: productos.length,
               itemBuilder: (context, index) {
                 final producto = productos[index];
-                if (producto.idCategoria != categoriaSeleccionada?.id) {
+
+                // Si no se está buscando, aplicar el filtro de categoría
+                if (!_estadoBusqueda &&
+                    producto.idCategoria != categoriaSeleccionada?.id) {
                   return Container();
                 }
+
                 return Card(
                   child: InkWell(
                     onTap: () => agregarAlCarrito(producto),

+ 55 - 47
lib/views/pedido/pedido_screen.dart

@@ -49,7 +49,7 @@ class _PedidoScreenState extends State<PedidoScreen> {
     }
 
     if (pedidosConProductos.isNotEmpty) {
-      String fileName = 'Pedidos_Conalep_POS';
+      String fileName = 'Pedidos_JoshiPapas_POS';
       if (fechaInicio != null && fechaFin != null) {
         String startDateStr = DateFormat('dd-MM-yyyy').format(fechaInicio!);
         String endDateStr = DateFormat('dd-MM-yyyy').format(fechaFin!);
@@ -505,60 +505,68 @@ class _PedidoScreenState extends State<PedidoScreen> {
 
   Widget botonBuscar() {
     return Expanded(
-        flex: 2,
-        child: Row(
-          children: [
-            Expanded(
-              flex: 2,
-              child: Padding(
-                padding: const EdgeInsets.only(bottom: 5),
-                child: ElevatedButton(
-                  onPressed: clearSearchAndReset,
-                  style: ElevatedButton.styleFrom(
-                    shape: RoundedRectangleBorder(
-                      borderRadius: BorderRadius.circular(20.0),
-                    ),
-                    primary: AppTheme.tertiary,
-                    padding: const EdgeInsets.symmetric(vertical: 25),
+      flex: 2,
+      child: Row(
+        children: [
+          Expanded(
+            flex: 2,
+            child: Padding(
+              padding: const EdgeInsets.only(bottom: 5),
+              child: ElevatedButton(
+                onPressed: clearSearchAndReset,
+                style: ElevatedButton.styleFrom(
+                  shape: RoundedRectangleBorder(
+                    borderRadius: BorderRadius.circular(20.0),
                   ),
-                  child: Text('Limpiar',
-                      style: TextStyle(color: AppTheme.quaternary)),
+                  primary: AppTheme.tertiary,
+                  padding: const EdgeInsets.symmetric(vertical: 25),
                 ),
+                child: Text('Limpiar',
+                    style: TextStyle(color: AppTheme.quaternary)),
               ),
             ),
-            const SizedBox(width: 8),
-            Expanded(
-              flex: 2,
-              child: Padding(
-                padding: const EdgeInsets.only(bottom: 5),
-                child: ElevatedButton(
-                  onPressed: () async {
-                    if (_busqueda.text.isNotEmpty) {
-                      await Provider.of<PedidoViewModel>(context, listen: false)
-                          .buscarPedidosPorFolio(_busqueda.text.trim());
-                    } else if (fechaInicio != null && fechaFin != null) {
-                      await Provider.of<PedidoViewModel>(context, listen: false)
-                          .buscarPedidosPorFecha(fechaInicio!, fechaFin!);
-                    } else {
-                      ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
-                          content: Text(
-                              'Introduce un folio o selecciona un rango de fechas para buscar.')));
-                    }
-                  },
-                  style: ElevatedButton.styleFrom(
-                    shape: RoundedRectangleBorder(
-                      borderRadius: BorderRadius.circular(20.0),
-                    ),
-                    primary: AppTheme.tertiary,
-                    padding: const EdgeInsets.symmetric(vertical: 25),
+          ),
+          const SizedBox(width: 8),
+          Expanded(
+            flex: 2,
+            child: Padding(
+              padding: const EdgeInsets.only(bottom: 5),
+              child: ElevatedButton(
+                onPressed: () async {
+                  if (_busqueda.text.isNotEmpty) {
+                    await Provider.of<PedidoViewModel>(context, listen: false)
+                        .buscarPedidosPorFolio(_busqueda.text.trim());
+                  } else if (fechaInicio != null && fechaFin != null) {
+                    DateTime fechaInicioUTC = DateTime(fechaInicio!.year,
+                            fechaInicio!.month, fechaInicio!.day)
+                        .toUtc();
+                    DateTime fechaFinUTC = DateTime(fechaFin!.year,
+                            fechaFin!.month, fechaFin!.day, 23, 59, 59)
+                        .toUtc();
+
+                    await Provider.of<PedidoViewModel>(context, listen: false)
+                        .buscarPedidosPorFecha(fechaInicioUTC, fechaFinUTC);
+                  } else {
+                    ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
+                        content: Text(
+                            'Introduce un folio o selecciona un rango de fechas para buscar.')));
+                  }
+                },
+                style: ElevatedButton.styleFrom(
+                  shape: RoundedRectangleBorder(
+                    borderRadius: BorderRadius.circular(20.0),
                   ),
-                  child: Text('Buscar',
-                      style: TextStyle(color: AppTheme.quaternary)),
+                  primary: AppTheme.tertiary,
+                  padding: const EdgeInsets.symmetric(vertical: 25),
                 ),
+                child: Text('Buscar',
+                    style: TextStyle(color: AppTheme.quaternary)),
               ),
             ),
-          ],
-        ));
+          ),
+        ],
+      ),
+    );
   }
 
   void alertaSync(BuildContext context) {

+ 55 - 31
lib/views/venta/venta_screen.dart

@@ -25,6 +25,8 @@ class _VentaScreenState extends State<VentaScreen> {
   double totalEfectivoDelDia = 0.0;
   double totalTarjetaDelDia = 0.0;
   double totalTransferenciaDelDia = 0.0;
+  double cambio = 0.0;
+  double totalSinCambio = 0.0;
 
   String formatCurrency(double amount) {
     final format = NumberFormat("#,##0.00", "es_MX");
@@ -200,33 +202,46 @@ class _VentaScreenState extends State<VentaScreen> {
                             fontSize: 20, fontWeight: FontWeight.bold),
                       ),
                     ),
-                    if (totalEfectivoDelDia > 0)
-                      Padding(
-                        padding: const EdgeInsets.all(16.0),
-                        child: Text(
-                          "Total en Efectivo: \$${formatCurrency(totalEfectivoDelDia)}",
-                          style: TextStyle(
-                              fontSize: 20, fontWeight: FontWeight.bold),
-                        ),
-                      ),
-                    if (totalTarjetaDelDia > 0)
-                      Padding(
-                        padding: const EdgeInsets.all(16.0),
-                        child: Text(
-                          "Total en Tarjeta: \$${formatCurrency(totalTarjetaDelDia)}",
-                          style: TextStyle(
-                              fontSize: 20, fontWeight: FontWeight.bold),
-                        ),
-                      ),
-                    if (totalTransferenciaDelDia > 0)
-                      Padding(
-                        padding: const EdgeInsets.all(16.0),
-                        child: Text(
-                          "Total en Transferencia: \$${formatCurrency(totalTransferenciaDelDia)}",
-                          style: TextStyle(
-                              fontSize: 20, fontWeight: FontWeight.bold),
-                        ),
-                      ),
+                    Row(
+                      children: [
+                        if (totalTarjetaDelDia > 0)
+                          Padding(
+                            padding: const EdgeInsets.all(16.0),
+                            child: Text(
+                              "Total en Tarjeta: \$${formatCurrency(totalTarjetaDelDia)}",
+                              style: TextStyle(
+                                  fontSize: 20, fontWeight: FontWeight.bold),
+                            ),
+                          ),
+                        if (totalTransferenciaDelDia > 0)
+                          Padding(
+                            padding: const EdgeInsets.all(16.0),
+                            child: Text(
+                              "Total en Transferencia: \$${formatCurrency(totalTransferenciaDelDia)}",
+                              style: TextStyle(
+                                  fontSize: 20, fontWeight: FontWeight.bold),
+                            ),
+                          ),
+                        if (totalEfectivoDelDia > 0)
+                          Padding(
+                            padding: const EdgeInsets.all(16.0),
+                            child: Text(
+                              "Total en Efectivo: \$${formatCurrency(totalEfectivoDelDia)}",
+                              style: TextStyle(
+                                  fontSize: 20, fontWeight: FontWeight.bold),
+                            ),
+                          ),
+                        if (cambio > 0)
+                          Padding(
+                            padding: const EdgeInsets.all(16.0),
+                            child: Text(
+                              "Cambio Entregado: \$${formatCurrency(cambio)}",
+                              style: TextStyle(
+                                  fontSize: 20, fontWeight: FontWeight.bold),
+                            ),
+                          ),
+                      ],
+                    ),
                     if (totalCancelados > 0)
                       Padding(
                         padding: const EdgeInsets.all(16.0),
@@ -249,11 +264,14 @@ class _VentaScreenState extends State<VentaScreen> {
   }
 
   void cargarPedidos(DateTime fecha) async {
-    final inicioDelDia = DateTime.utc(fecha.year, fecha.month, fecha.day);
-    final finDelDia =
-        DateTime.utc(fecha.year, fecha.month, fecha.day, 23, 59, 59);
+    // Convertir el inicio y fin del día local a UTC
+    final inicioDelDia = DateTime(fecha.year, fecha.month, fecha.day)
+        .toUtc(); // Convierte la fecha local de inicio del día a UTC
 
-    print('Buscando pedidos desde: $inicioDelDia hasta: $finDelDia');
+    final finDelDia = DateTime(fecha.year, fecha.month, fecha.day, 23, 59, 59)
+        .toUtc(); // Convierte la fecha local de fin del día a UTC
+
+    print('Buscando pedidos desde: $inicioDelDia hasta: $finDelDia (en UTC)');
 
     // Realizar la búsqueda en UTC
     final pedidos = await Provider.of<PedidoViewModel>(context, listen: false)
@@ -273,12 +291,18 @@ class _VentaScreenState extends State<VentaScreen> {
     totalEfectivoDelDia = 0.0;
     totalTarjetaDelDia = 0.0;
     totalTransferenciaDelDia = 0.0;
+    cambio = 0.0;
+    totalSinCambio = 0.0;
 
     for (var pedido in pedidosNoCancelados) {
       totalDelDia += pedido.totalPedido ?? 0.0;
       totalEfectivoDelDia += pedido.cantEfectivo ?? 0.0;
       totalTarjetaDelDia += pedido.cantTarjeta ?? 0.0;
       totalTransferenciaDelDia += pedido.cantTransferencia ?? 0.0;
+      totalSinCambio =
+          totalEfectivoDelDia + totalTarjetaDelDia + totalTransferenciaDelDia;
+
+      cambio = totalSinCambio - totalDelDia;
     }
 
     totalCancelados = pedidosCancelados.fold(

+ 22 - 15
lib/views/venta/venta_ticket.dart

@@ -38,6 +38,9 @@ class VentaTicket {
     double totalTransferencia = pedidosNoCancelados.fold(
         0.0, (sum, p) => sum + (p.cantTransferencia ?? 0.0));
 
+    double totalSinCambio = totalEfectivo + totalTarjeta + totalTransferencia;
+    double cambio = totalSinCambio - totalNoCancelados;
+
     final spelling = SpellingNumber(lang: 'es');
     String totalEnLetras = toTitleCase(spelling.convert(totalNoCancelados));
 
@@ -48,14 +51,12 @@ class VentaTicket {
     String formattedTotalTarjeta = numberFormat.format(totalTarjeta);
     String formattedTotalTransferencia =
         numberFormat.format(totalTransferencia);
+    String formattedCambio = numberFormat.format(cambio);
 
     int centavos =
         ((totalNoCancelados - totalNoCancelados.floor()) * 100).round();
     String centavosEnLetras = centavos.toString().padLeft(2, '0') + "/100 M.N.";
 
-    print("Total en letras: $totalEnLetras $centavosEnLetras");
-    print("Total formateado: $formattedTotalNoCancelados");
-
     pdf.addPage(pw.Page(
         pageFormat: PdfPageFormat.roll57,
         build: (pw.Context context) {
@@ -94,19 +95,25 @@ class VentaTicket {
                 child: pw.Column(
                   crossAxisAlignment: pw.CrossAxisAlignment.start,
                   children: [
-                    pw.Text("- Total en Efectivo: \$${formattedTotalEfectivo}",
-                        style: pw.TextStyle(
-                            fontWeight: pw.FontWeight.bold, fontSize: 11)),
-                    pw.Text("- Total en Tarjeta: \$${formattedTotalTarjeta}",
-                        style: pw.TextStyle(
-                            fontWeight: pw.FontWeight.bold, fontSize: 11)),
-                    pw.Text(
-                        "- Total en Transferencia: \$${formattedTotalTransferencia}",
-                        style: pw.TextStyle(
-                            fontWeight: pw.FontWeight.bold, fontSize: 11)),
-                    pw.Text("- Total General: \$${formattedTotalNoCancelados}",
+                    if (totalTarjeta > 0)
+                      pw.Text("-Tarjeta: \$${formattedTotalTarjeta}",
+                          style: pw.TextStyle(
+                              fontWeight: pw.FontWeight.bold, fontSize: 9.5)),
+                    if (totalTransferencia > 0)
+                      pw.Text("-Transf: \$${formattedTotalTransferencia}",
+                          style: pw.TextStyle(
+                              fontWeight: pw.FontWeight.bold, fontSize: 9.5)),
+                    if (totalEfectivo > 0)
+                      pw.Text("-Efectivo: \$${formattedTotalEfectivo}",
+                          style: pw.TextStyle(
+                              fontWeight: pw.FontWeight.bold, fontSize: 9.5)),
+                    if (cambio > 0)
+                      pw.Text("-Cambio: \$${formattedCambio}",
+                          style: pw.TextStyle(
+                              fontWeight: pw.FontWeight.bold, fontSize: 9.5)),
+                    pw.Text("-Total: \$${formattedTotalNoCancelados}",
                         style: pw.TextStyle(
-                            fontWeight: pw.FontWeight.bold, fontSize: 11)),
+                            fontWeight: pw.FontWeight.bold, fontSize: 9.5)),
                     pw.Text("Son: $totalEnLetras Pesos $centavosEnLetras",
                         style: pw.TextStyle(fontSize: 10))
                   ],

+ 1 - 1
lib/widgets/app_drawer.dart

@@ -168,7 +168,7 @@ class AppDrawer extends StatelessWidget {
             child: Align(
               alignment: Alignment.bottomCenter,
               child: Text(
-                'v1.24.09.23',
+                'v1.24.10.09+1',
                 style: const TextStyle(fontWeight: FontWeight.w300),
               ),
             ),