2026_01_24_200001_create_reservations_table.php 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. <?php
  2. use Illuminate\Database\Migrations\Migration;
  3. use Illuminate\Database\Schema\Blueprint;
  4. use Illuminate\Support\Facades\DB;
  5. use Illuminate\Support\Facades\Schema;
  6. return new class extends Migration
  7. {
  8. /**
  9. * Run the migrations.
  10. *
  11. * Таблица резервов — логическая сущность для отслеживания
  12. * зарезервированных запчастей под конкретные рекламации.
  13. *
  14. * Резерв уменьшает свободный остаток, но НЕ физический.
  15. * Физический остаток уменьшается только при списании (issue).
  16. */
  17. public function up(): void
  18. {
  19. Schema::create('reservations', function (Blueprint $table) {
  20. $table->id();
  21. // Какая запчасть зарезервирована
  22. $table->foreignId('spare_part_id')
  23. ->constrained('spare_parts')
  24. ->restrictOnDelete();
  25. // Из какой партии (для FIFO учёта)
  26. $table->foreignId('spare_part_order_id')
  27. ->constrained('spare_part_orders')
  28. ->restrictOnDelete();
  29. // Для какой рекламации
  30. $table->foreignId('reclamation_id')
  31. ->constrained('reclamations')
  32. ->cascadeOnDelete();
  33. // Количество зарезервировано
  34. $table->unsignedInteger('reserved_qty');
  35. // Признак документов
  36. $table->boolean('with_documents')->default(false);
  37. // Статус резерва
  38. $table->enum('status', [
  39. 'active', // Активный резерв
  40. 'issued', // Списано (резерв реализован)
  41. 'cancelled', // Отменён
  42. ])->default('active');
  43. // Связь с движением (для аудита)
  44. $table->foreignId('movement_id')
  45. ->nullable()
  46. ->constrained('inventory_movements')
  47. ->nullOnDelete();
  48. $table->timestamps();
  49. // Индексы
  50. $table->index(['spare_part_id', 'with_documents', 'status']);
  51. $table->index(['spare_part_order_id', 'status']);
  52. $table->index(['reclamation_id', 'status']);
  53. $table->index('status');
  54. });
  55. // CHECK constraint для положительного количества
  56. // MySQL 8.0.16+ поддерживает CHECK constraints
  57. DB::statement('ALTER TABLE reservations ADD CONSTRAINT chk_reserved_qty_positive CHECK (reserved_qty > 0)');
  58. }
  59. /**
  60. * Reverse the migrations.
  61. */
  62. public function down(): void
  63. {
  64. Schema::dropIfExists('reservations');
  65. }
  66. };