From 832f9228af71c109e70ced30e713a80062a44cfb Mon Sep 17 00:00:00 2001
From: GianellaDelMestre <146126967+GianellaDelMestre@users.noreply.github.com>
Date: Sun, 7 Dec 2025 00:08:18 -0300
Subject: [PATCH 1/8] tablas y modelos
---
app/Models/Appointment.php | 18 ++++++++++
app/Models/Client.php | 16 +++++++++
app/Models/Product.php | 36 +++++++++++++++----
app/Models/Sale.php | 28 +++++++++++++++
app/Models/SaleDetail.php | 23 ++++++++++++
app/Models/Supplier.php | 18 ++++++++++
...25_12_06_182356_create_suppliers_table.php | 30 ++++++++++++++++
...25_12_06_182358_create_products_table.php} | 15 ++++----
...2025_12_06_184833_create_clients_table.php | 30 ++++++++++++++++
.../2025_12_06_193913_create_sales_table.php | 34 ++++++++++++++++++
...12_06_201853_create_sale_details_table.php | 31 ++++++++++++++++
...12_07_023045_create_appointments_table.php | 33 +++++++++++++++++
12 files changed, 298 insertions(+), 14 deletions(-)
create mode 100644 app/Models/Appointment.php
create mode 100644 app/Models/Client.php
create mode 100644 app/Models/Sale.php
create mode 100644 app/Models/SaleDetail.php
create mode 100644 app/Models/Supplier.php
create mode 100644 database/migrations/2025_12_06_182356_create_suppliers_table.php
rename database/migrations/{2025_08_05_005156_create_products_table.php => 2025_12_06_182358_create_products_table.php} (64%)
create mode 100644 database/migrations/2025_12_06_184833_create_clients_table.php
create mode 100644 database/migrations/2025_12_06_193913_create_sales_table.php
create mode 100644 database/migrations/2025_12_06_201853_create_sale_details_table.php
create mode 100644 database/migrations/2025_12_07_023045_create_appointments_table.php
diff --git a/app/Models/Appointment.php b/app/Models/Appointment.php
new file mode 100644
index 0000000..95ee0df
--- /dev/null
+++ b/app/Models/Appointment.php
@@ -0,0 +1,18 @@
+fecha_programada->format('d/m/Y')
+ protected $casts = [
+ 'fecha_programada' => 'datetime',
+ ];
+ public function clients()
+ {
+ return $this->belongsTo(Client::class);
+ }
+}
diff --git a/app/Models/Client.php b/app/Models/Client.php
new file mode 100644
index 0000000..1ac14d2
--- /dev/null
+++ b/app/Models/Client.php
@@ -0,0 +1,16 @@
+hasMany(Sale::class);
+ }
+}
diff --git a/app/Models/Product.php b/app/Models/Product.php
index 143a9b8..a4e3f49 100644
--- a/app/Models/Product.php
+++ b/app/Models/Product.php
@@ -9,13 +9,35 @@ class Product extends Model
{
use HasFactory;
protected $fillable = [
+ 'codigo',
'nombre',
- 'marca',
- 'modelo',
- 'rodado',
- 'color',
- 'tipo',
- 'descripcion',
- 'precio'
+ 'costo',
+ 'precio',
+ 'stock',
+ 'min_stock',
+ 'categoria',
+ 'descripcion'
];
+ public function supplier()
+ {
+ return $this->belongsTo(Suppliers::class);
+ }
+
+ // Opción 1: Relación directa con los detalles (Renglones de ticket)
+ // Útil para saber cantidad total vendida: $product->saleDetails->sum('quantity')
+ public function saleDetails()
+ {
+ return $this->hasMany(SaleDetail::class);
+ }
+
+ // Opción 2 (Pro Tip): Relación directa con las Ventas a través de los detalles
+ // Útil para saber EN QUÉ fechas se vendió: $product->sales
+ public function sales()
+ {
+ return $this->belongsToMany(Sale::class, 'sale_details');
+ }
+
}
+/**$user->sales: Te da la lista de todas las compras de ese usuario.
+
+$product->saleDetails->count(): Te dice cuántas veces aparece ese producto en tickets.**/
\ No newline at end of file
diff --git a/app/Models/Sale.php b/app/Models/Sale.php
new file mode 100644
index 0000000..c9c88ad
--- /dev/null
+++ b/app/Models/Sale.php
@@ -0,0 +1,28 @@
+belongsTo(User::class);
+ }
+
+ // Relación 2: Una venta tiene muchos items o detalles
+ public function details()
+ {
+ return $this->hasMany(SaleDetail::class);
+ }
+}
diff --git a/app/Models/SaleDetail.php b/app/Models/SaleDetail.php
new file mode 100644
index 0000000..bbe36e6
--- /dev/null
+++ b/app/Models/SaleDetail.php
@@ -0,0 +1,23 @@
+belongsTo(Sale::class);
+ }
+
+ // este detalle corresponde a un Producto
+ public function product()
+ {
+ return $this->belongsTo(Product::class);
+ }
+}
\ No newline at end of file
diff --git a/app/Models/Supplier.php b/app/Models/Supplier.php
new file mode 100644
index 0000000..8acf047
--- /dev/null
+++ b/app/Models/Supplier.php
@@ -0,0 +1,18 @@
+hasMany(Product::class);
+ }
+}
diff --git a/database/migrations/2025_12_06_182356_create_suppliers_table.php b/database/migrations/2025_12_06_182356_create_suppliers_table.php
new file mode 100644
index 0000000..c5e0c12
--- /dev/null
+++ b/database/migrations/2025_12_06_182356_create_suppliers_table.php
@@ -0,0 +1,30 @@
+id();
+ $table->string('nombre');
+ $table->string('telefono');
+ $table->string('email');
+ $table->timestamps();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('suppliers');
+ }
+};
diff --git a/database/migrations/2025_08_05_005156_create_products_table.php b/database/migrations/2025_12_06_182358_create_products_table.php
similarity index 64%
rename from database/migrations/2025_08_05_005156_create_products_table.php
rename to database/migrations/2025_12_06_182358_create_products_table.php
index ecbf13a..c785e32 100644
--- a/database/migrations/2025_08_05_005156_create_products_table.php
+++ b/database/migrations/2025_12_06_182358_create_products_table.php
@@ -13,14 +13,15 @@ return new class extends Migration
{
Schema::create('products', function (Blueprint $table) {
$table->id();
+ $table->string('codigo')->unique();
$table->string('nombre');
- $table->string('marca');
- $table->string('modelo');
- $table->string('rodado');
- $table->string('color');
- $table->string('tipo');
+ $table->decimal('costo', 12, 2);
+ $table->decimal('precio', 12, 2);
+ $table->integer('stock');
+ $table->integer('min_stock')->default(5);
+ $table->string('categoria');
$table->text('descripcion');
- $table->float('precio');
+ $table->foreignId('suppliers_id')->constrained();
$table->timestamps();
});
}
@@ -32,4 +33,4 @@ return new class extends Migration
{
Schema::dropIfExists('products');
}
-};
+};
\ No newline at end of file
diff --git a/database/migrations/2025_12_06_184833_create_clients_table.php b/database/migrations/2025_12_06_184833_create_clients_table.php
new file mode 100644
index 0000000..398e55b
--- /dev/null
+++ b/database/migrations/2025_12_06_184833_create_clients_table.php
@@ -0,0 +1,30 @@
+id();
+ $table->string('nombre');
+ $table->string('telefono');
+ $table->string('email');
+ $table->timestamps();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('clients');
+ }
+};
diff --git a/database/migrations/2025_12_06_193913_create_sales_table.php b/database/migrations/2025_12_06_193913_create_sales_table.php
new file mode 100644
index 0000000..b0bfc22
--- /dev/null
+++ b/database/migrations/2025_12_06_193913_create_sales_table.php
@@ -0,0 +1,34 @@
+id();
+ // 1. Cliente que compra
+ $table->foreignId('user_id')->constrained()->onDelete('cascade');
+ // 2. Datos generales de la venta
+ $table->decimal('total', 10, 2); // Total final del ticket
+ $table->string('metodo_pago'); // Ej: "Efectivo", "Tarjeta", "MercadoPago"
+ //capaz van mas datos ni idea
+ // 3. Fecha y Hora (created_at servirá como fecha de venta)
+ $table->timestamps();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('sales');
+ }
+};
diff --git a/database/migrations/2025_12_06_201853_create_sale_details_table.php b/database/migrations/2025_12_06_201853_create_sale_details_table.php
new file mode 100644
index 0000000..e357fa9
--- /dev/null
+++ b/database/migrations/2025_12_06_201853_create_sale_details_table.php
@@ -0,0 +1,31 @@
+id();
+ $table->foreignId('sale_id')->constrained()->onDelete('cascade');
+ $table->foreignId('product_id')->constrained();
+ $table->integer('cantidad');
+ $table->decimal('precio', 10, 2);
+ $table->timestamps();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('sale_details');
+ }
+};
diff --git a/database/migrations/2025_12_07_023045_create_appointments_table.php b/database/migrations/2025_12_07_023045_create_appointments_table.php
new file mode 100644
index 0000000..3bac73b
--- /dev/null
+++ b/database/migrations/2025_12_07_023045_create_appointments_table.php
@@ -0,0 +1,33 @@
+id();
+ $table->foreignId('client_id')->constrained();
+ $table->datetime('fecha_programada');
+ $table->string('modelo_bici')->nullable();
+ $table->string('descripcion')->nullable();
+ $table->string('estado')->default('pendiente');
+ $table->string('notas')->nullable();
+ $table->timestamps();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('appointments');
+ }
+};
From 9a5e84e73b16a5b737cfb222760b05f1409c47b2 Mon Sep 17 00:00:00 2001
From: Coassolo-Lucas <131891029+Coassolo-Lucas@users.noreply.github.com>
Date: Mon, 8 Dec 2025 01:36:36 -0300
Subject: [PATCH 2/8] l
---
app/Http/Controllers/SaleController.php | 56 +++++++++++++++++++++
resources/views/components/navbar.blade.php | 6 ++-
resources/views/sales/index.blade.php | 12 +++++
routes/web.php | 4 ++
4 files changed, 76 insertions(+), 2 deletions(-)
create mode 100644 app/Http/Controllers/SaleController.php
create mode 100644 resources/views/sales/index.blade.php
diff --git a/app/Http/Controllers/SaleController.php b/app/Http/Controllers/SaleController.php
new file mode 100644
index 0000000..6d99fb3
--- /dev/null
+++ b/app/Http/Controllers/SaleController.php
@@ -0,0 +1,56 @@
+Taller
- Ventas
-
+
+ Ventas
+
diff --git a/resources/views/sales/index.blade.php b/resources/views/sales/index.blade.php
new file mode 100644
index 0000000..8174db7
--- /dev/null
+++ b/resources/views/sales/index.blade.php
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Document
+
+
+ Gwssssssssssssssss
+
+
\ No newline at end of file
diff --git a/routes/web.php b/routes/web.php
index f819ba4..79aa241 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -7,6 +7,7 @@ use App\Http\Controllers\HomeController;
use App\Http\Controllers\LoginController;
use App\Http\Controllers\ProductosController;
use App\Http\Controllers\RegisterController;
+use App\Http\Controllers\SaleController;
use App\Models\Product;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;
@@ -45,6 +46,9 @@ Route::middleware(['auth'])->group(function () {
Route::post('/productos',[ProductosController::class,'store'])->name('productos.store');
Route::put('/productos/{id}',[ProductosController::class,'update'])->name('productos.update');
Route::delete('/productos/{id}', [ProductosController::class,'destroy'])->name('productos.destroy');
+
+ Route::get('/sales', [SaleController::class, 'index'])->name('sales.index');
+ Route::get('/sales/create', [SaleController::class, 'create'])->name('sales.create');
});
Route::get('/catalogo', [CatalogoController::class,'catalogo'])->name('catalogo');
From 04a8ecbd9a7e8d67eafa3726e17383b6762ab5a9 Mon Sep 17 00:00:00 2001
From: BryamE
Date: Mon, 8 Dec 2025 21:41:27 -0300
Subject: [PATCH 3/8] Empezando prototipo de "Registro de Ventas", usa la tabla
productos para ayuda visual. Agregado componente select.
---
app/Http/Controllers/CatalogoController.php | 24 +++++
.../views/components/forms/select.blade.php | 48 +++++++---
resources/views/components/navbar.blade.php | 10 +-
.../views/components/section-header.blade.php | 2 +-
resources/views/layouts/app.blade.php | 17 ----
resources/views/sales.blade.php | 91 +++++++++++++++++++
routes/web.php | 1 +
7 files changed, 162 insertions(+), 31 deletions(-)
delete mode 100644 resources/views/layouts/app.blade.php
create mode 100644 resources/views/sales.blade.php
diff --git a/app/Http/Controllers/CatalogoController.php b/app/Http/Controllers/CatalogoController.php
index b7e5632..e74a30a 100644
--- a/app/Http/Controllers/CatalogoController.php
+++ b/app/Http/Controllers/CatalogoController.php
@@ -13,4 +13,28 @@ class CatalogoController extends Controller
$productos = Product::all();
return view('catalogo', compact('productos'));
}
+
+ /**
+ * Muestra los registros de ventas con buscador y paginación.
+ */
+ public function index(Request $request)
+ {
+ // Recuperamos lo que el usuario escribió en el buscador (si escribió algo)
+ $query = $request->input('search');
+ // Recuperamos el filtro aplicado (si aplica)
+ $filter = $request->input('filter');
+
+ // Construimos la consulta
+ $sales = Product::query()
+ ->when($query, function ($q) use ($query) {
+ // Si hay búsqueda, filtra por nombre o SKU
+ return $q->where('name', 'like', "%{$query}%")
+ ->orWhere('sku', 'like', "%{$query}%");
+ })
+ ->orderBy('stock_quantity', 'asc') // Ordenamos primero los que tienen poco stock (Alerta visual)
+ ->paginate(10) // Paginamos de a 10
+ ->withQueryString(); // Mantiene el filtro de búsqueda al cambiar de página
+
+ return view('sales', compact('sales'));
+ }
}
diff --git a/resources/views/components/forms/select.blade.php b/resources/views/components/forms/select.blade.php
index 1346f60..697461c 100644
--- a/resources/views/components/forms/select.blade.php
+++ b/resources/views/components/forms/select.blade.php
@@ -1,13 +1,39 @@
-@props(['disabled' => false, 'options', 'error' => null])
+@props(['disabled' => false, 'error' => null, 'options' => [], 'placeholder' => 'Seleccionar...'])
-