194 lines
9.1 KiB
PHP
194 lines
9.1 KiB
PHP
<?php
|
|
|
|
use Illuminate\Database\Migrations\Migration;
|
|
use Illuminate\Database\Schema\Blueprint;
|
|
use Illuminate\Support\Facades\Schema;
|
|
|
|
return new class extends Migration
|
|
{
|
|
/**
|
|
* Run the migrations.
|
|
*/
|
|
public function up(): void
|
|
{
|
|
Schema::create('warehouses', function (Blueprint $table) {
|
|
$table->smallIncrements('id');
|
|
|
|
$table->unsignedSmallInteger('store_id')->index(); // Relación con sucursal
|
|
$table->unsignedSmallInteger('work_center_id')->nullable()->index();
|
|
|
|
$table->string('code', 16)->unique();
|
|
$table->string('name', 96)->index();
|
|
|
|
$table->mediumText('description')->nullable();
|
|
|
|
$table->unsignedMediumInteger('manager_id')->nullable()->index(); // sat_codigo_postal.
|
|
|
|
$table->string('tel')->nullable();
|
|
$table->string('tel2')->nullable();
|
|
|
|
$table->unsignedTinyInteger('priority')->nullable();
|
|
|
|
$table->boolean('status')->default(true)->index();
|
|
|
|
$table->timestamps();
|
|
|
|
// Indices
|
|
$table->unique(['store_id', 'name']);
|
|
|
|
$table->foreign('store_id')->references('id')->on('stores')->onDelete('cascade');
|
|
$table->foreign('work_center_id')->references('id')->on('store_work_centers')->onDelete('cascade');
|
|
$table->foreign('manager_id')->references('id')->on('users')->onUpdate('restrict')->onDelete('restrict');
|
|
});
|
|
|
|
Schema::create('warehouse_movements', function (Blueprint $table) {
|
|
$table->mediumIncrements('id');
|
|
|
|
$table->unsignedSmallInteger('store_id')->index();
|
|
$table->unsignedSmallInteger('warehouse_id')->index(); // Almacén involucrado
|
|
|
|
// Tipo de ajuste (ajuste de inventario o traspaso)
|
|
$table->unsignedTinyInteger('movement_type')->index(); // Tipo de movimiento: ajuste o traspaso
|
|
$table->unsignedMediumInteger('movement_id')->nullable(); // UID específico por sucursal
|
|
|
|
$table->unsignedMediumInteger('created_by')->index(); // Usuario que registró el movimiento
|
|
$table->unsignedMediumInteger('approved_by')->nullable()->index(); // Usuario que autorizó el movimiento
|
|
|
|
// Cantidad ajustada
|
|
$table->decimal('adjusted_quantity', 13, 6); // Cantidad ajustada para el ajuste o transferencia
|
|
|
|
// Costo asociado
|
|
$table->decimal('cost', 9, 2)->unsigned()->default(0); // Costo de la operación
|
|
|
|
// Notas sobre el ajuste
|
|
$table->mediumText('notes')->nullable(); // Notas adicionales
|
|
|
|
// Campos para el traspaso
|
|
$table->unsignedSmallInteger('to_warehouse_id')->nullable()->index(); // Almacén de destino (solo para traspasos)
|
|
|
|
$table->unsignedTinyInteger('status')->index(); // Estatus de la orden ('pending', 'approved', 'received', 'cancelled')
|
|
|
|
$table->softDeletes();
|
|
$table->timestamps();
|
|
|
|
|
|
// Claves foráneas
|
|
$table->foreign('store_id')->references('id')->on('stores')->onDelete('restrict');
|
|
$table->foreign('warehouse_id')->references('id')->on('warehouses')->onDelete('restrict');
|
|
$table->foreign('to_warehouse_id')->references('id')->on('warehouses')->onDelete('restrict');
|
|
$table->foreign('created_by')->references('id')->on('users')->onDelete('restrict');
|
|
$table->foreign('approved_by')->references('id')->on('users')->onDelete('restrict');
|
|
|
|
});
|
|
|
|
Schema::create('lot_numbers', function (Blueprint $table) {
|
|
$table->mediumIncrements('id');
|
|
|
|
$table->unsignedMediumInteger('product_id')->index();
|
|
$table->unsignedSmallInteger('store_id')->index();
|
|
$table->unsignedSmallInteger('warehouse_id')->index();
|
|
|
|
$table->string('lot_number', 50)->unique()->comment('Número único del lote');
|
|
$table->date('production_date')->nullable();
|
|
$table->date('expiry_date')->nullable();
|
|
$table->decimal('initial_quantity', 13, 6)->unsigned()->default(0);
|
|
$table->decimal('remaining_quantity', 13, 6)->unsigned()->default(0);
|
|
$table->decimal('cost', 9, 2)->unsigned()->default(0);
|
|
|
|
$table->timestamps();
|
|
|
|
$table->foreign('product_id')->references('id')->on('products')->onDelete('restrict');
|
|
$table->foreign('store_id')->references('id')->on('stores')->onDelete('restrict');
|
|
$table->foreign('warehouse_id')->references('id')->on('warehouses')->onDelete('restrict');
|
|
});
|
|
|
|
Schema::create('inventory_stock_levels', function (Blueprint $table) {
|
|
$table->mediumIncrements('id');
|
|
|
|
$table->unsignedMediumInteger('product_id')->index();
|
|
$table->unsignedSmallInteger('store_id')->nullable()->index();
|
|
$table->unsignedSmallInteger('warehouse_id')->index();
|
|
|
|
$table->decimal('quantity', 13, 6)->unsigned()->comment('Stock total disponible en el almacén');
|
|
|
|
// Stock separado por área
|
|
$table->decimal('pos_stock', 13, 6)->unsigned()->default(0)->comment('Stock destinado a ventas en POS');
|
|
$table->decimal('ecommerce_stock', 13, 6)->unsigned()->default(0)->comment('Stock destinado a eCommerce');
|
|
$table->decimal('purchase_reserved_stock', 13, 6)->unsigned()->default(0)->comment('Stock reservado para órdenes de compra');
|
|
$table->decimal('asset_stock', 13, 6)->unsigned()->default(0)->comment('Stock reservado para uso interno');
|
|
|
|
// Alertas de Stock mínimo y máximo
|
|
$table->unsignedTinyInteger('alert_minimum_stock')->nullable()->index();
|
|
$table->decimal('minimum_stock', 13, 6)->unsigned()->nullable();
|
|
$table->unsignedTinyInteger('alert_maximum_stock')->nullable()->index();
|
|
$table->decimal('maximum_stock', 13, 6)->unsigned()->nullable();
|
|
|
|
// Costos asociados
|
|
$table->decimal('last_cost', 9, 2)->unsigned()->default(0); // Último costo registrado
|
|
$table->decimal('average_cost', 9, 2)->unsigned()->default(0); // Costo promedio ponderado
|
|
$table->decimal('total_last_cost', 11, 2)->unsigned()->default(0); // Costo total último costo registrado
|
|
$table->decimal('total_average_cost', 11, 2)->unsigned()->default(0); // Costo total promedio ponderado
|
|
$table->decimal('total_identified_cost', 11, 2)->unsigned()->default(0); // Costo total identificado
|
|
|
|
$table->unsignedTinyInteger('costing_method')->index(); // Método de costeo: 'average', 'last', 'identified'
|
|
|
|
$table->timestamps();
|
|
|
|
$table->unique(['warehouse_id', 'product_id']);
|
|
|
|
$table->foreign('product_id')->references('id')->on('products')->onDelete('restrict');
|
|
$table->foreign('store_id')->references('id')->on('stores')->onDelete('restrict');
|
|
$table->foreign('warehouse_id')->references('id')->on('warehouses')->onDelete('restrict');
|
|
});
|
|
|
|
Schema::create('inventory_movements', function (Blueprint $table) {
|
|
$table->integerIncrements('id');
|
|
|
|
$table->unsignedMediumInteger('product_id')->index();
|
|
$table->unsignedSmallInteger('store_id')->index();
|
|
$table->unsignedSmallInteger('warehouse_id')->index();
|
|
|
|
$table->enum('movement_type', ['in', 'out'])->index(); // Tipo de movimiento (entrada/salida)
|
|
|
|
$table->decimal('quantity', 13, 6)->unsigned();
|
|
|
|
$table->decimal('cost', 9, 2)->unsigned(); // Costo asociado a la transacción
|
|
$table->decimal('cost_before', 9, 2)->unsigned()->nullable();
|
|
$table->decimal('cost_after', 9, 2)->unsigned()->nullable();
|
|
$table->enum('cost_type', ['average', 'last', 'specific'])->default('last');
|
|
|
|
$table->text('notes')->nullable(); // Notas sobre el movimiento
|
|
|
|
// Define el campo para la relación polimórfica manualmente
|
|
$table->unsignedMediumInteger('transactionable_id')->index();
|
|
$table->string('transactionable_type')->index();
|
|
|
|
$table->unsignedMediumInteger('created_by')->index(); // Usuario que registró el movimiento
|
|
|
|
$table->timestamps();
|
|
|
|
// Agrega el índice con un nombre específico para evitar el problema de longitud
|
|
$table->index(['transactionable_type', 'transactionable_id'], 'inventory_movements_transactionable_index');
|
|
|
|
$table->foreign('product_id')->references('id')->on('products')->onDelete('restrict');
|
|
$table->foreign('store_id')->references('id')->on('stores')->onDelete('restrict');
|
|
$table->foreign('warehouse_id')->references('id')->on('warehouses')->onDelete('restrict');
|
|
$table->foreign('created_by')->references('id')->on('users')->onDelete('restrict');
|
|
});
|
|
|
|
|
|
}
|
|
|
|
/**
|
|
* Reverse the migrations.
|
|
*/
|
|
public function down(): void
|
|
{
|
|
Schema::dropIfExists('warehouses');
|
|
Schema::dropIfExists('warehouse_movements');
|
|
Schema::dropIfExists('lot_numbers');
|
|
Schema::dropIfExists('inventory_stock_levels');
|
|
Schema::dropIfExists('inventory_movements');
|
|
}
|
|
};
|