migrate to gtea from bistbucket
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('food_categories', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('restaurant_id')->nullable();
|
||||
|
||||
$table->string('name'); // Category Name
|
||||
$table->string('slug')->nullable();
|
||||
|
||||
$table->string('image')->nullable(); // Image path
|
||||
$table->foreignId('parent_id')->nullable()->constrained('food_categories')->onDelete('cascade'); // Parent category
|
||||
$table->boolean('is_offer')->default(false); // Offer toggle
|
||||
$table->date('start_date')->nullable(); // Offer start
|
||||
$table->date('end_date')->nullable(); // Offer end
|
||||
$table->smallInteger('status')->default(1)->comment('1=Active, 2=InActive');
|
||||
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('food_categories');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('menu_types', function (Blueprint $table) {
|
||||
$table->id();
|
||||
|
||||
// Multi-restaurant support
|
||||
$table->unsignedBigInteger('restaurant_id')->index()->nullable();
|
||||
|
||||
// Menu type details
|
||||
$table->string('name')->index()->comment('e.g., Lunch, Dinner, Breakfast, Happy Hour');
|
||||
$table->string('slug')->nullable()->unique()->comment('Unique slug for URLs and API');
|
||||
$table->string('icon')->nullable()->comment('Optional icon or image for menu type');
|
||||
$table->text('description')->nullable()->comment('Optional description of this menu type');
|
||||
$table->integer('display_order')->default(0)->comment('Ordering in menu display');
|
||||
|
||||
// Status & flags
|
||||
$table->smallInteger('status')->default(1)->comment('1=Active, 2=Inactive');
|
||||
$table->boolean('is_default')->default(false)->comment('Default menu type for new items');
|
||||
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
// Indexes
|
||||
$table->index(['restaurant_id', 'status']);
|
||||
$table->index(['restaurant_id', 'name']);
|
||||
|
||||
// Foreign key
|
||||
$table->foreign('restaurant_id')->references('id')->on('restaurants')->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('menu_types');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('addons', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('restaurant_id')->index();
|
||||
$table->string('name')->index();
|
||||
$table->decimal('price', 12, 2);
|
||||
$table->decimal('vat', 5, 2)->default(0);
|
||||
$table->decimal('pst', 5, 2)->default(0);
|
||||
$table->tinyInteger('status')->default(1)->comment('1=Active, 2=Inactive');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
$table->foreign('restaurant_id')->references('id')->on('restaurants')->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('addons');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('menu_categories', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('restaurant_id')->nullable();
|
||||
|
||||
$table->string('name');
|
||||
$table->string('slug')->nullable();
|
||||
$table->string('icon')->nullable();
|
||||
$table->text('description')->nullable();
|
||||
$table->integer('priority')->default(0)->comment('Display order');
|
||||
|
||||
$table->smallInteger('status')->default(1)->comment('1=Active, 2=InActive');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
// Unique constraint: restaurant_id + name (nullable restaurant_id supported)
|
||||
$table->unique(['restaurant_id', 'name'], 'restaurant_name_unique');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('menu_categories');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('menu_sections', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('restaurant_id')->nullable();
|
||||
|
||||
$table->foreignId('menu_category_id')->constrained('menu_categories')->onDelete('cascade');
|
||||
$table->string('name');
|
||||
$table->string('slug')->nullable();
|
||||
$table->text('description')->nullable();
|
||||
$table->integer('priority')->default(0)->comment('Display order');
|
||||
|
||||
$table->smallInteger('status')->default(1)->comment('1=Active, 2=InActive');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
// Unique constraint: restaurant_id + name
|
||||
$table->unique(['restaurant_id', 'name'], 'restaurant_section_name_unique');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('menu_sections');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('food_items', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('restaurant_id')->index();
|
||||
$table->unsignedBigInteger('category_id')->index();
|
||||
$table->unsignedBigInteger('menu_category_id')->nullable();
|
||||
$table->unsignedBigInteger('menu_section_id')->nullable();
|
||||
|
||||
$table->string('name')->index();
|
||||
$table->string('slug')->nullable();
|
||||
$table->text('description')->nullable();
|
||||
$table->enum('food_type', ['Veg', 'Non-Veg']);
|
||||
|
||||
$table->integer('points')->default(0); // points for this item
|
||||
$table->tinyInteger('is_featured')->default(0);
|
||||
$table->tinyInteger('is_party')->default(0);
|
||||
$table->tinyInteger('is_dinner')->default(0);
|
||||
$table->tinyInteger('is_lunch')->default(0);
|
||||
$table->tinyInteger('is_popular_item')->default(0)->index();
|
||||
$table->tinyInteger('is_chef_special')->default(0)->index();
|
||||
$table->string('image')->nullable();
|
||||
$table->time('prep_time')->nullable();
|
||||
$table->time('cooking_time')->nullable();
|
||||
$table->decimal('vat', 5, 2)->default(0);
|
||||
$table->decimal('pst', 5, 2)->default(0);
|
||||
$table->decimal('ingredients_cost', 12, 2)->default(0);
|
||||
$table->string('allergens')->nullable();
|
||||
$table->text('notes')->nullable();
|
||||
$table->tinyInteger('status')->default(1)->index();
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
$table->foreign('restaurant_id')->references('id')->on('restaurants')->onDelete('cascade');
|
||||
$table->foreign('category_id')->references('id')->on('food_categories')->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('food_items');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('addon_food', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('restaurant_id')->index();
|
||||
$table->unsignedBigInteger('food_item_id')->index();
|
||||
$table->unsignedBigInteger('addon_id')->index();
|
||||
$table->tinyInteger('status')->default(1);
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
$table->foreign('food_item_id')->references('id')->on('food_items')->onDelete('cascade');
|
||||
$table->foreign('addon_id')->references('id')->on('addons')->onDelete('cascade');
|
||||
$table->foreign('restaurant_id')->references('id')->on('restaurants')->onDelete('cascade');
|
||||
|
||||
$table->unique(['food_item_id', 'addon_id']); // avoid duplicate assignments
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('addon_food');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('units', function (Blueprint $table) {
|
||||
$table->id();
|
||||
// Multi-tenant support
|
||||
$table->unsignedBigInteger('restaurant_id')->nullable();
|
||||
$table->unsignedBigInteger('user_id')->nullable();
|
||||
|
||||
// Full international naming
|
||||
$table->string('name'); // e.g., Gram
|
||||
$table->string('short_name'); // e.g., g
|
||||
$table->string('type')->nullable(); // weight, volume, length, count
|
||||
|
||||
// Relation to base unit within same category
|
||||
$table->foreignId('base_unit_id')->nullable()->constrained('units')->nullOnDelete();
|
||||
|
||||
// Conversion logic
|
||||
$table->enum('operator', ['*', '/'])->default('*');
|
||||
$table->float('operator_value')->default(1); // e.g., 1000 for (kg → g)
|
||||
|
||||
// Config
|
||||
$table->smallInteger('priority')->default(1);
|
||||
$table->smallInteger('version')->default(1);
|
||||
$table->boolean('is_default')->default(false);
|
||||
|
||||
$table->smallInteger('status')->default(1)->comment('1=Active, 2=InActive');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
// Indexes
|
||||
$table->index(['type']);
|
||||
$table->index(['name']);
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('units');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('food_variants', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('restaurant_id')->index();
|
||||
$table->unsignedBigInteger('food_item_id')->index();
|
||||
|
||||
$table->string('name');
|
||||
$table->string('sku')->unique();
|
||||
$table->string('barcode')->nullable();
|
||||
$table->decimal('price', 12, 2);
|
||||
$table->decimal('offer_price', 12, 2)->nullable();
|
||||
$table->integer('discount')->default(0);
|
||||
$table->foreignId('unit_id')->constrained('units')->cascadeOnDelete();
|
||||
$table->string('image')->nullable();
|
||||
$table->text('description')->nullable();
|
||||
|
||||
$table->tinyInteger('is_default')->default(0);
|
||||
$table->tinyInteger('stock_tracking')->default(0);
|
||||
|
||||
$table->decimal('ingredients_cost', 12, 2)->default(0);
|
||||
$table->decimal('profit_margin', 12, 2)->default(0);
|
||||
$table->decimal('alert_stock_quantity', 10, 2)->nullable();
|
||||
$table->enum('combo_type', ['single', 'combo', 'add-on'])->default('single');
|
||||
$table->tinyInteger('is_active_offer')->default(0);
|
||||
$table->timestamp('offer_start_at')->nullable();
|
||||
$table->timestamp('offer_end_at')->nullable();
|
||||
$table->tinyInteger('status')->default(1);
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
$table->foreign('food_item_id')->references('id')->on('food_items')->onDelete('cascade');
|
||||
$table->foreign('restaurant_id')->references('id')->on('restaurants')->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('food_variants');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('food_availabilities', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('restaurant_id')->constrained()->onDelete('cascade');
|
||||
$table->foreignId('food_item_id')->constrained()->onDelete('cascade');
|
||||
|
||||
$table->enum('day', [
|
||||
'Sunday',
|
||||
'Monday',
|
||||
'Tuesday',
|
||||
'Wednesday',
|
||||
'Thursday',
|
||||
'Friday',
|
||||
'Saturday',
|
||||
]);
|
||||
|
||||
$table->boolean('is_available')->default(true);
|
||||
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
$table->unique(['food_item_id', 'day']);
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('food_availabilities');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('food_availability_times', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('food_availability_id')
|
||||
->constrained('food_availabilities')
|
||||
->onDelete('cascade');
|
||||
|
||||
$table->time('open_time');
|
||||
$table->time('close_time');
|
||||
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
$table->unique(
|
||||
['food_availability_id', 'open_time', 'close_time'],
|
||||
'unique_food_time_slot'
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('food_availability_times');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('tables', function (Blueprint $table) {
|
||||
$table->id();
|
||||
|
||||
$table->unsignedBigInteger('restaurant_id')->index();
|
||||
|
||||
$table->string('name'); // T01, T02 …
|
||||
$table->string('location')->nullable(); // floor / zone / hall
|
||||
$table->string('section')->nullable();
|
||||
$table->string('serial')->nullable(); // optional serial for sorting
|
||||
|
||||
// Table type
|
||||
$table->enum('table_type', ['regular', 'vip', 'outdoor', 'booth'])
|
||||
->default('regular');
|
||||
|
||||
$table->integer('capacity')->default(2);
|
||||
$table->boolean('is_bookable')->default(true);
|
||||
|
||||
$table->string('qr_code')->nullable();
|
||||
$table->string('image')->nullable(); // icon for UI
|
||||
|
||||
// ⭐ Position Fields for Drag & Drop Layout
|
||||
$table->float('position_x')->default(0);
|
||||
$table->float('position_y')->default(0);
|
||||
$table->float('rotation')->default(0); // rotate table icon
|
||||
$table->integer('z_index')->default(1); // layer ordering
|
||||
|
||||
$table->tinyInteger('status')->default(1)->comment('1 = Active, 2 = Inactive');
|
||||
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
$table->foreign('restaurant_id')->references('id')->on('restaurants')->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('tables');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('payment_methods', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('restaurant_id')->index()->nullable(); // multi-restaurant support
|
||||
|
||||
$table->string('name'); // e.g., "Stripe", "PayPal", "Cash"
|
||||
$table->string('type')->nullable()->comment('gateway, cash, card, wallet');
|
||||
$table->json('credentials')->nullable()->comment('store API keys, tokens, or config as JSON');
|
||||
$table->boolean('is_default')->default(false); // default payment method
|
||||
$table->tinyInteger('status')->default(1)->comment('1=Active, 2=Inactive');
|
||||
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
$table->foreign('restaurant_id')->references('id')->on('restaurants')->onDelete('cascade');
|
||||
$table->unique(['restaurant_id', 'name']); // avoid duplicate payment methods per restaurant
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('payment_methods');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('customers', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('restaurant_id')->nullable()->index();
|
||||
|
||||
$table->string('customer_code')->nullable(); // auto-generated code (QR/loyalty)
|
||||
$table->string('name')->default('Walk-in');
|
||||
$table->string('username')->nullable();
|
||||
$table->string('email')->nullable();
|
||||
$table->string('phone', 50)->nullable();
|
||||
$table->string('password')->nullable();
|
||||
$table->integer('otp_code')->nullable();
|
||||
$table->boolean('isVerified')->default(false);
|
||||
$table->timestamp('email_verified_at')->nullable();
|
||||
$table->string('avatar')->nullable();
|
||||
$table->string('address')->nullable();
|
||||
$table->tinyInteger('role_id')->default(9)->comment('9=Customer');
|
||||
|
||||
$table->enum('gender', ['male', 'female', 'other'])->nullable();
|
||||
$table->date('date_of_birth')->nullable();
|
||||
|
||||
$table->string('nid')->nullable();
|
||||
$table->enum('platform', ['APP', 'WEB'])->default('APP');
|
||||
$table->longText('device_info')->nullable();
|
||||
$table->timestamp('last_active_time')->nullable();
|
||||
|
||||
$table->json('meta')->nullable(); // loyalty, preferences
|
||||
|
||||
$table->tinyInteger('status')->default(1)->comment('1 = Active, 2 = Inactive');
|
||||
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
// 🧩 Multi-restaurant scoped uniqueness
|
||||
$table->unique(['restaurant_id', 'email']);
|
||||
$table->unique(['restaurant_id', 'phone']);
|
||||
|
||||
// Foreign key
|
||||
$table->foreign('restaurant_id')
|
||||
->references('id')
|
||||
->on('restaurants')
|
||||
->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('customers');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
use App\Enum\OrderStatus;
|
||||
use App\Enum\OrderType;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('orders', function (Blueprint $table) {
|
||||
$table->id();
|
||||
|
||||
// ====== Foreign Keys ======
|
||||
$table->foreignId('restaurant_id')->constrained()->cascadeOnDelete();
|
||||
$table->foreignId('table_id')->nullable()->constrained()->nullOnDelete();
|
||||
$table->foreignId('waiter_id')->nullable()->constrained('users')->nullOnDelete();
|
||||
$table->foreignId('driver_id')->nullable()->constrained('users')->nullOnDelete();
|
||||
$table->foreignId('customer_id')->nullable()->constrained('customers')->nullOnDelete();
|
||||
$table->foreignId('payment_method_id')->nullable()->constrained('payment_methods')->nullOnDelete();
|
||||
|
||||
// ====== Order Identifiers ======
|
||||
$table->string('order_number')->unique()->comment('Unique order number for search');
|
||||
$table->string('reference')->nullable();
|
||||
|
||||
// ====== Order Attributes ======
|
||||
$table->enum('order_type', OrderType::values())->default(OrderType::DINE_IN)->index();
|
||||
$table->enum('status', OrderStatus::values())->default(OrderStatus::PENDING)->index();
|
||||
|
||||
// ====== Amounts ======
|
||||
$table->decimal('subtotal', 12, 2)->default(0.00)->comment('Sum of item totals before discount and tax');
|
||||
$table->decimal('discount', 12, 2)->default(0.00)->comment('Discount applied to order');
|
||||
$table->decimal('tax', 12, 2)->default(0.00)->comment('Tax applied on subtotal or after discount');
|
||||
$table->decimal('service_charge', 12, 2)->default(0.00);
|
||||
$table->decimal('tip_amount', 12, 2)->default(0.00);
|
||||
$table->decimal('grand_total', 12, 2)->default(0.00)->comment('Total amount to be paid');
|
||||
|
||||
// ====== Payment Tracking ======
|
||||
$table->boolean('payment_status')->default(false)->index();
|
||||
$table->string('payment_reference')->nullable();
|
||||
$table->timestamp('paid_at')->nullable();
|
||||
|
||||
// ====== Date & Time Tracking ======
|
||||
$table->timestamp('order_date')->useCurrent()->index();
|
||||
$table->time('preparation_time')->nullable()->comment('Estimated preparation duration (HH:MM:SS)');
|
||||
$table->timestamp('ready_at')->nullable()->comment('Time when order ready');
|
||||
$table->timestamp('handed_over_at')->nullable()->comment('Time when handed over to customer');
|
||||
$table->timestamp('delivered_at')->nullable()->comment('Time delivered for delivery orders');
|
||||
$table->timestamp('estimated_ready_time')->nullable();
|
||||
|
||||
// ====== Other Attributes ======
|
||||
$table->text('delivery_address')->nullable();
|
||||
$table->enum('order_source', ['POS', 'Web', 'MobileApp', 'ThirdParty'])->default('POS')->index();
|
||||
$table->json('meta')->nullable()->comment('Flexible storage for extra info: loyalty, coupon, special instructions');
|
||||
|
||||
// Order Cancel
|
||||
$table->timestamp('cancelled_at')->nullable();
|
||||
$table->text('cancel_reason')->nullable();
|
||||
$table->unsignedBigInteger('cancelled_by')->nullable();
|
||||
|
||||
// ====== Audit ======
|
||||
$table->foreignId('added_by')->nullable()->constrained('users')->nullOnDelete();
|
||||
$table->foreignId('updated_by')->nullable()->constrained('users')->nullOnDelete();
|
||||
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
// ====== Composite Indexes for Reports ======
|
||||
$table->index(['restaurant_id', 'status', 'order_date'], 'idx_restaurant_status_date');
|
||||
$table->index(['restaurant_id', 'order_date'], 'idx_restaurant_date');
|
||||
$table->index(['customer_id', 'order_date'], 'idx_customer_date');
|
||||
$table->index(['waiter_id', 'order_date'], 'idx_waiter_date');
|
||||
$table->index(['order_type', 'order_date'], 'idx_order_type_date');
|
||||
$table->index(['payment_status', 'order_date'], 'idx_payment_status_date');
|
||||
$table->index(['order_source', 'order_date'], 'idx_order_source_date');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('orders');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('order_items', function (Blueprint $table) {
|
||||
$table->id();
|
||||
|
||||
$table->foreignId('order_id')->constrained('orders')->cascadeOnDelete();
|
||||
$table->foreignId('restaurant_id')->constrained('restaurants')->cascadeOnDelete();
|
||||
$table->foreignId('food_item_id')->constrained('food_items')->restrictOnDelete();
|
||||
$table->foreignId('food_variant_id')->nullable()->constrained('food_variants')->restrictOnDelete();
|
||||
|
||||
$table->integer('quantity')->default(1);
|
||||
$table->decimal('price', 12, 2)->default(0.00)->comment('Unit price of item/variant');
|
||||
$table->decimal('discount', 12, 2)->default(0.00)->comment('Discount on this item');
|
||||
$table->decimal('tax', 12, 2)->default(0.00)->comment('Tax for this item');
|
||||
$table->decimal('total', 12, 2)->default(0.00)->comment('Total after quantity, discount, tax');
|
||||
|
||||
$table->json('addons')->nullable()->comment('List of addons with price, quantity');
|
||||
$table->json('meta')->nullable()->comment('Extra info: special instructions, combo info, etc');
|
||||
|
||||
$table->smallInteger('status')->default(1)->comment('1=Active, 2=Cancelled');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
// ====== Indexes for reporting ======
|
||||
$table->index(['order_id', 'food_item_id'], 'idx_order_food');
|
||||
$table->index(['restaurant_id', 'food_item_id'], 'idx_restaurant_food');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('order_items');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('suppliers', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('restaurant_id')->nullable();
|
||||
|
||||
// Basic Info
|
||||
$table->string('name');
|
||||
$table->string('phone');
|
||||
$table->string('company_name')->nullable();
|
||||
$table->string('contact_person')->nullable();
|
||||
$table->string('alternate_phone')->nullable();
|
||||
$table->string('email')->nullable();
|
||||
$table->string('website')->nullable();
|
||||
$table->string('image')->nullable(); // profile picture
|
||||
|
||||
// Address Info
|
||||
$table->text('address')->nullable();
|
||||
$table->string('city')->nullable();
|
||||
$table->string('state')->nullable();
|
||||
$table->string('country')->nullable();
|
||||
$table->string('postal_code')->nullable();
|
||||
|
||||
// Financial / Business Info
|
||||
$table->string('tax_number')->nullable()->comment('VAT/GST/Tax ID');
|
||||
$table->string('bank_name')->nullable();
|
||||
$table->string('bank_account_name')->nullable();
|
||||
$table->string('bank_account_number')->nullable();
|
||||
$table->string('ifsc_code')->nullable()->comment('For local bank transactions');
|
||||
$table->decimal('opening_balance', 15, 2)->default(0);
|
||||
$table->date('opening_balance_date')->nullable();
|
||||
$table->decimal('due', 15, 2)->default(0);
|
||||
$table->decimal('balance', 15, 2)->default(0);
|
||||
|
||||
// Relationship Info
|
||||
$table->string('supply_type')->nullable()->comment('e.g. Food, Beverage, Cleaning, Equipment');
|
||||
$table->string('payment_terms')->nullable()->comment('e.g. Net 7, Net 30, COD');
|
||||
$table->decimal('credit_limit', 15, 2)->nullable();
|
||||
|
||||
// Ratings & Notes
|
||||
$table->decimal('rating', 3, 2)->nullable()->comment('Average rating from 1-5');
|
||||
$table->text('notes')->nullable();
|
||||
|
||||
// Documents
|
||||
$table->string('contract_file')->nullable()->comment('Stored contract document path');
|
||||
$table->string('trade_license')->nullable();
|
||||
$table->string('nid_number')->nullable();
|
||||
|
||||
// Status and Timestamps
|
||||
$table->smallInteger('status')->default(1)->comment('1=Active, 2=Inactive');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
// Foreign key (optional if restaurants table exists)
|
||||
$table->foreign('restaurant_id')->references('id')->on('restaurants')->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('suppliers');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('ingredients', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('restaurant_id')->nullable();
|
||||
|
||||
$table->string('name')->index();
|
||||
// Unit Manage
|
||||
$table->foreignId('unit_id')->constrained('units')->cascadeOnDelete();
|
||||
$table->foreignId('unit_sale_id')->nullable()->constrained('units');
|
||||
$table->foreignId('unit_purchase_id')->nullable()->constrained('units');
|
||||
|
||||
$table->decimal('stock_quantity', 10, 2)->default(0);
|
||||
$table->decimal('cost_per_unit', 10, 2)->default(0);
|
||||
$table->decimal('low_stock_alert', 10, 2)->default(0);
|
||||
$table->string('image')->nullable(); // profile picture
|
||||
|
||||
// Supplier & Purchase Info
|
||||
$table->unsignedBigInteger('supplier_id')->nullable()->comment('Link to main supplier');
|
||||
$table->decimal('last_purchase_price', 10, 2)->nullable();
|
||||
$table->date('last_purchase_date')->nullable();
|
||||
|
||||
// Units & conversions
|
||||
$table->decimal('conversion_factor', 10, 2)->default(1)->comment('For unit conversions if needed');
|
||||
|
||||
// Stock & inventory tracking
|
||||
$table->decimal('reserved_quantity', 10, 2)->default(0)->comment('Quantity reserved for pending orders/recipes');
|
||||
$table->decimal('wastage_quantity', 10, 2)->default(0)->comment('Total wastage recorded');
|
||||
|
||||
// Optional categorization
|
||||
$table->string('category')->nullable()->comment('e.g. Vegetable, Meat, Dairy, Beverage');
|
||||
|
||||
// Operational Notes
|
||||
$table->text('notes')->nullable();
|
||||
|
||||
$table->smallInteger('status')->default(1)->comment('1=Active, 2=InActive');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
// Foreign keys
|
||||
// $table->foreign('supplier_id')->references('id')->on('suppliers')->onDelete('set null');
|
||||
$table->foreign('restaurant_id')->references('id')->on('restaurants')->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('ingredients');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('food_variant_ingredients', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('restaurant_id')->nullable();
|
||||
$table->unsignedBigInteger('food_variant_id')->index();
|
||||
$table->unsignedBigInteger('ingredient_id')->index();
|
||||
$table->decimal('quantity', 10, 2)->default(0);
|
||||
$table->decimal('wastage_percentage', 5, 2)->default(0);
|
||||
$table->decimal('unit_conversion_factor', 10, 2)->default(1);
|
||||
$table->string('optional', 1)->default('N');
|
||||
$table->text('notes')->nullable();
|
||||
$table->smallInteger('status')->default(1)->comment('1=Active, 2=Inactive');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
$table->foreign('food_variant_id')->references('id')->on('food_variants')->onDelete('cascade');
|
||||
$table->foreign('ingredient_id')->references('id')->on('ingredients')->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('food_variant_ingredients');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('purchases', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('restaurant_id')->nullable();
|
||||
$table->unsignedBigInteger('supplier_id')->nullable()->index();
|
||||
$table->string('invoice_no')->nullable()->unique();
|
||||
$table->date('purchase_date')->default(now());
|
||||
|
||||
// Financial fields
|
||||
$table->decimal('sub_total', 12, 2)->default(0);
|
||||
$table->decimal('discount_amount', 12, 2)->default(0);
|
||||
$table->decimal('tax_amount', 12, 2)->default(0);
|
||||
$table->decimal('total_amount', 12, 2)->default(0);
|
||||
$table->string('payment_status')->default('unpaid')->comment('paid, unpaid, partial');
|
||||
$table->string('payment_method')->nullable()->comment('cash, bank, credit');
|
||||
$table->string('purchase_type')->default('ingredient')->comment('ingredient, equipment, others');
|
||||
$table->unsignedBigInteger('created_by')->nullable()->comment('User ID who created the purchase');
|
||||
|
||||
$table->text('notes')->nullable();
|
||||
$table->smallInteger('status')->default(1)->comment('1=Active, 2=Inactive');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
// Foreign keys
|
||||
$table->foreign('supplier_id')->references('id')->on('suppliers')->onDelete('set null');
|
||||
$table->foreign('restaurant_id')->references('id')->on('restaurants')->onDelete('cascade');
|
||||
$table->foreign('created_by')->references('id')->on('users')->onDelete('set null');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('purchases');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('purchase_items', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('restaurant_id')->nullable();
|
||||
$table->unsignedBigInteger('purchase_id')->index();
|
||||
$table->unsignedBigInteger('ingredient_id')->index();
|
||||
$table->unsignedBigInteger('food_variant_id')->nullable();
|
||||
|
||||
$table->decimal('quantity', 10, 2);
|
||||
$table->decimal('unit_price', 12, 2);
|
||||
$table->decimal('total_cost', 12, 2);
|
||||
$table->decimal('tax_amount', 12, 2)->default(0);
|
||||
$table->decimal('discount_amount', 12, 2)->default(0);
|
||||
$table->string('batch_no')->nullable();
|
||||
$table->date('expiry_date')->nullable();
|
||||
$table->decimal('received_quantity', 10, 2)->nullable();
|
||||
$table->decimal('wastage_quantity', 10, 2)->default(0);
|
||||
$table->decimal('returned_quantity', 10, 2)->default(0);
|
||||
$table->smallInteger('status')->default(1)->comment('1=Active, 2=Inactive');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
$table->foreign('purchase_id')->references('id')->on('purchases')->onDelete('cascade');
|
||||
$table->foreign('ingredient_id')->references('id')->on('ingredients')->onDelete('cascade');
|
||||
$table->foreign('food_variant_id')->references('id')->on('food_variants')->onDelete('set null');
|
||||
$table->foreign('restaurant_id')->references('id')->on('restaurants')->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('purchase_items');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('stocks', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('restaurant_id')->nullable();
|
||||
$table->foreignId('ingredient_id')->constrained()->onDelete('cascade');
|
||||
|
||||
// Type of stock movement
|
||||
$table->enum('type', ['purchase', 'usage', 'return', 'damage', 'transfer_in', 'transfer_out'])->index();
|
||||
|
||||
$table->decimal('quantity', 10, 2);
|
||||
|
||||
// Cost tracking
|
||||
$table->decimal('unit_cost', 12, 2)->nullable()->comment('Cost per unit at time of stock movement');
|
||||
$table->decimal('total_cost', 12, 2)->nullable()->comment('quantity * unit_cost');
|
||||
|
||||
// Reference linking
|
||||
$table->string('reference_type')->nullable()->comment('e.g., Purchase, FoodVariant, Transfer');
|
||||
$table->unsignedBigInteger('purchase_id')->nullable();
|
||||
|
||||
// Optional batch and expiry tracking
|
||||
$table->string('batch_no')->nullable();
|
||||
$table->date('expiry_date')->nullable();
|
||||
|
||||
// Accountability
|
||||
$table->unsignedBigInteger('added_by')->nullable()->comment('User ID who added/modified stock');
|
||||
|
||||
$table->text('remarks')->nullable();
|
||||
$table->smallInteger('status')->default(1)->comment('1=Active, 2=Inactive');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
// Foreign keys
|
||||
$table->foreign('restaurant_id')->references('id')->on('restaurants')->onDelete('cascade');
|
||||
$table->foreign('added_by')->references('id')->on('users')->onDelete('set null');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('stocks');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('ingredient_damages', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('restaurant_id')->nullable();
|
||||
|
||||
// Link directly to the ingredient
|
||||
$table->unsignedBigInteger('ingredient_id')->index();
|
||||
|
||||
// Optional: link to purchase batch for perishable tracking
|
||||
$table->string('batch_no')->nullable();
|
||||
|
||||
$table->decimal('quantity', 10, 2);
|
||||
|
||||
// Cost tracking
|
||||
$table->decimal('unit_cost', 12, 2)->nullable()->comment('Cost per unit at time of damage');
|
||||
$table->decimal('total_cost', 12, 2)->nullable()->comment('quantity * unit_cost');
|
||||
|
||||
$table->string('reason')->nullable()->comment('Reason for damage: spoilage, breakage, etc.');
|
||||
$table->date('damage_date')->default(now());
|
||||
|
||||
// Accountability
|
||||
$table->unsignedBigInteger('reported_by')->nullable()->comment('User ID who reported the damage');
|
||||
|
||||
$table->smallInteger('status')->default(1)->comment('1=Active, 2=Inactive');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
// Foreign keys
|
||||
$table->foreign('restaurant_id')->references('id')->on('restaurants')->onDelete('cascade');
|
||||
$table->foreign('ingredient_id')->references('id')->on('ingredients')->onDelete('cascade');
|
||||
$table->foreign('reported_by')->references('id')->on('users')->onDelete('set null');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('ingredient_damages');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('food_wastes', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('restaurant_id')->nullable();
|
||||
$table->foreignId('food_item_id')->constrained('food_items')->restrictOnDelete();
|
||||
$table->foreignId('food_variant_id')->nullable()->constrained('food_variants')->restrictOnDelete();
|
||||
$table->decimal('quantity', 10, 2)->default(0);
|
||||
$table->decimal('unit_cost', 16, 2)->nullable();
|
||||
$table->string('reason')->nullable();
|
||||
$table->text('notes')->nullable();
|
||||
$table->unsignedBigInteger('wasted_by')->nullable();
|
||||
$table->unsignedBigInteger('approved_by')->nullable();
|
||||
$table->dateTime('wasted_at')->nullable();
|
||||
$table->enum('status', ['pending', 'approved', 'rejected'])->default('pending');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('food_wastes');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('purchase_returns', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('restaurant_id')->nullable();
|
||||
|
||||
// Link to the original purchase and item
|
||||
$table->unsignedBigInteger('purchase_id')->index();
|
||||
$table->unsignedBigInteger('purchase_item_id')->index();
|
||||
$table->unsignedBigInteger('ingredient_id')->index();
|
||||
|
||||
// Optional: link to purchase batch for tracking
|
||||
$table->string('batch_no')->nullable();
|
||||
|
||||
// Return quantity and cost
|
||||
$table->decimal('quantity', 10, 2);
|
||||
$table->decimal('unit_cost', 12, 2)->nullable()->comment('Unit cost at time of purchase');
|
||||
$table->decimal('total_cost', 12, 2)->nullable()->comment('quantity * unit_cost');
|
||||
|
||||
$table->string('reason')->nullable()->comment('Reason for return: damaged, expired, supplier return, etc.');
|
||||
$table->date('return_date')->default(now());
|
||||
|
||||
// Accountability
|
||||
$table->unsignedBigInteger('processed_by')->nullable()->comment('User ID who processed the return');
|
||||
|
||||
$table->smallInteger('status')->default(1)->comment('1=Active, 2=Inactive');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
// Foreign keys
|
||||
$table->foreign('restaurant_id')->references('id')->on('restaurants')->onDelete('cascade');
|
||||
$table->foreign('purchase_id')->references('id')->on('purchases')->onDelete('cascade');
|
||||
$table->foreign('purchase_item_id')->references('id')->on('purchase_items')->onDelete('cascade');
|
||||
$table->foreign('ingredient_id')->references('id')->on('ingredients')->onDelete('cascade');
|
||||
$table->foreign('processed_by')->references('id')->on('users')->onDelete('set null');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('purchase_returns');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('reservations', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('restaurant_id')->nullable();
|
||||
$table->unsignedBigInteger('table_id')->nullable();
|
||||
$table->unsignedBigInteger('customer_id')->nullable();
|
||||
|
||||
$table->date('reservation_date');
|
||||
$table->time('start_time');
|
||||
$table->time('end_time')->nullable();
|
||||
|
||||
$table->integer('people_count')->default(1);
|
||||
$table->enum('status', ['booked', 'free', 'upcoming', 'cancelled'])->default('upcoming');
|
||||
$table->text('note')->nullable();
|
||||
|
||||
$table->foreign('table_id')->references('id')->on('tables')->onDelete('set null');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('reservations');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('reservation_unavailables', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('restaurant_id')->nullable();
|
||||
$table->unsignedBigInteger('table_id')->nullable();
|
||||
$table->date('date');
|
||||
$table->time('start_time');
|
||||
$table->time('end_time');
|
||||
$table->string('reason')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('reservation_unavailables');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('delivery_charges', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('zone_id')->constrained('zones')->onDelete('cascade');
|
||||
$table->foreignId('restaurant_id')->nullable()->constrained('restaurants')->onDelete('cascade');
|
||||
$table->enum('type', ['flat', 'distance_based'])->default('flat');
|
||||
$table->decimal('base_charge', 10, 2)->default(0.00);
|
||||
$table->decimal('per_km_charge', 10, 2)->nullable();
|
||||
$table->decimal('min_order_amount', 10, 2)->default(0.00);
|
||||
$table->decimal('free_delivery_above', 10, 2)->nullable();
|
||||
$table->boolean('is_active')->default(true);
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('delivery_charges');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('customer_addresses', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('user_id')->constrained('users')->onDelete('cascade');
|
||||
$table->string('label', 50)->default('Home');
|
||||
$table->string('address_line_1');
|
||||
$table->string('address_line_2')->nullable();
|
||||
$table->string('city', 100)->nullable();
|
||||
$table->string('postal_code', 20)->nullable();
|
||||
$table->decimal('latitude', 10, 7)->nullable();
|
||||
$table->decimal('longitude', 10, 7)->nullable();
|
||||
$table->boolean('is_default')->default(false);
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('customer_addresses');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
use App\Enum\TrackingStatus;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('order_trackings', function (Blueprint $table) {
|
||||
$table->id();
|
||||
|
||||
$table->foreignId('order_id')
|
||||
->constrained('orders')
|
||||
->onDelete('cascade');
|
||||
|
||||
$table->foreignId('delivery_boy_id')
|
||||
->nullable()
|
||||
->constrained('users')
|
||||
->onDelete('set null');
|
||||
|
||||
// ✅ Use Enum instead of hard-coded strings
|
||||
$table->enum('status', TrackingStatus::values())
|
||||
->default(TrackingStatus::Placed->value);
|
||||
|
||||
$table->decimal('latitude', 10, 7)->nullable();
|
||||
$table->decimal('longitude', 10, 7)->nullable();
|
||||
$table->string('location_name')->nullable();
|
||||
$table->text('note')->nullable();
|
||||
$table->timestamp('tracked_at')->useCurrent();
|
||||
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('order_trackings');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('restaurant_schedules', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('restaurant_id')->constrained()->onDelete('cascade');
|
||||
$table->enum('day', [
|
||||
'Sunday',
|
||||
'Monday',
|
||||
'Tuesday',
|
||||
'Wednesday',
|
||||
'Thursday',
|
||||
'Friday',
|
||||
'Saturday',
|
||||
]);
|
||||
|
||||
// if restaurant is closed full day
|
||||
$table->boolean('is_open')->default(true);
|
||||
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
$table->unique(['restaurant_id', 'day']);
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('restaurant_schedules');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('restaurant_schedule_times', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('restaurant_schedule_id')->constrained('restaurant_schedules')->onDelete('cascade');
|
||||
|
||||
$table->time('open_time');
|
||||
$table->time('close_time');
|
||||
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
$table->unique(['restaurant_schedule_id', 'open_time', 'close_time'], 'unique_restaurant_time_slot');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('restaurant_schedule_times');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('loyalty_points', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('restaurant_id')->nullable();
|
||||
$table->unsignedBigInteger('user_id');
|
||||
$table->unsignedBigInteger('order_id')->nullable();
|
||||
$table->unsignedBigInteger('food_item_id')->nullable();
|
||||
$table->integer('points')->default(0);
|
||||
$table->enum('type', ['earned', 'redeemed', 'manual'])->default('earned');
|
||||
$table->string('reason')->nullable();
|
||||
$table->smallInteger('status')->default(1)->comment('1=Active, 2=InActive');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('loyalty_points');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('loyalty_redemptions', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('restaurant_id')->nullable();
|
||||
$table->unsignedBigInteger('user_id');
|
||||
$table->unsignedBigInteger('food_item_id')->nullable();
|
||||
$table->integer('points_used')->default(0);
|
||||
$table->decimal('price', 16, 2)->nullable(); // original price
|
||||
$table->smallInteger('status')->default(1)->comment('1=Active, 2=InActive');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('loyalty_redemptions');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('reservation_settings', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('restaurant_id')->nullable();
|
||||
$table->time('start_time');
|
||||
$table->time('end_time');
|
||||
$table->integer('max_reservation')->default(0);
|
||||
$table->smallInteger('status')->default(1)->comment('1=Active, 2=InActive');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('reservation_settings');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('loyalty_point_settings', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('restaurant_id')->nullable();
|
||||
$table->string('name');
|
||||
$table->decimal('from_amount', 12, 2)->nullable();
|
||||
$table->decimal('to_amount', 12, 2)->nullable();
|
||||
$table->decimal('amount', 12, 2)->nullable();
|
||||
$table->integer('earn_point')->default(0);
|
||||
$table->smallInteger('status')->default(1)->comment('1=Active, 2=InActive');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('loyalty_point_settings');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('tax_settings', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('restaurant_id')->nullable();
|
||||
// Basic tax info
|
||||
$table->string('name', 100); // e.g., VAT, GST
|
||||
$table->string('reg_no', 100)->nullable(); // registration number
|
||||
|
||||
// Upgrade: Instead of string default_value, use proper decimal
|
||||
$table->enum('type', ['percentage', 'fixed'])->default('percentage');
|
||||
$table->decimal('value', 12, 2)->nullable(); // actual tax value
|
||||
|
||||
// Default tax flag
|
||||
$table->boolean('is_default')->default(false);
|
||||
|
||||
// Status
|
||||
$table->smallInteger('status')->default(1)->comment('1=Active, 2=Inactive');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('tax_settings');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('q_r_menu_settings', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('restaurant_id')->nullable();
|
||||
|
||||
// Menu settings
|
||||
$table->string('name', 100);
|
||||
$table->string('menu_title', 150)->nullable();
|
||||
$table->string('logo')->nullable();
|
||||
$table->string('menu_url')->nullable();
|
||||
$table->string('primary_color', 20)->nullable();
|
||||
$table->string('secondary_color', 20)->nullable();
|
||||
$table->string('bg_color', 20)->nullable();
|
||||
$table->string('template', 50)->default('default');
|
||||
$table->text('description')->nullable();
|
||||
$table->string('qr_code_url')->nullable();
|
||||
|
||||
// WiFi settings
|
||||
$table->string('wifi_name')->nullable();
|
||||
$table->string('wifi_ssid')->nullable();
|
||||
$table->string('wifi_password')->nullable();
|
||||
|
||||
$table->smallInteger('status')->default(1)->comment('1=Active, 2=InActive');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('q_r_menu_settings');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('kitchens', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('restaurant_id')->nullable();
|
||||
$table->string('name');
|
||||
$table->integer('serial')->default(0);
|
||||
$table->smallInteger('status')->default(1)->comment('1=Active, 2=InActive');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('kitchens');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('kitchen_assigns', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('restaurant_id')->nullable();
|
||||
$table->foreignId('kitchen_id')->constrained('kitchens')->onDelete('cascade');
|
||||
$table->foreignId('user_id')->constrained('users')->onDelete('cascade');
|
||||
$table->smallInteger('status')->default(1)->comment('1=Active, 2=InActive');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('kitchen_assigns');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('food_reviews', function (Blueprint $table) {
|
||||
$table->id();
|
||||
// SaaS Scope
|
||||
$table->unsignedBigInteger('restaurant_id')->index();
|
||||
$table->unsignedBigInteger('food_item_id')->index();
|
||||
$table->unsignedBigInteger('customer_id')->nullable()->index();
|
||||
|
||||
// Review Data
|
||||
$table->tinyInteger('rating')->comment('1-5');
|
||||
$table->text('review')->nullable();
|
||||
|
||||
// Media
|
||||
$table->json('images')->nullable(); // ["url1","url2"]
|
||||
$table->string('video_url')->nullable();
|
||||
$table->string('video_file')->nullable();
|
||||
|
||||
// Status & Control
|
||||
$table->enum('status', ['pending', 'approved', 'rejected'])->default('pending');
|
||||
$table->boolean('is_featured')->default(false);
|
||||
$table->integer('position')->default(0);
|
||||
|
||||
// Meta
|
||||
$table->integer('helpful_count')->default(0);
|
||||
$table->text('reject_reason')->nullable();
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('food_reviews');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('food_review_replies', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('restaurant_id')->nullable();
|
||||
$table->unsignedBigInteger('review_id')->index();
|
||||
$table->unsignedBigInteger('user_id')->nullable();
|
||||
$table->unsignedBigInteger('customer_id')->nullable();
|
||||
$table->enum('user_type', ['admin', 'customer']);
|
||||
|
||||
$table->text('message')->nullable();
|
||||
$table->json('attachments')->nullable();
|
||||
$table->smallInteger('status')->default(1)->comment('1=Active, 0=InActive');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('food_review_replies');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Restaurant\Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Modules\Authentication\Models\Restaurant;
|
||||
use Modules\Restaurant\Models\Addon;
|
||||
use Modules\Restaurant\Models\FoodItem;
|
||||
|
||||
class AddonFoodSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$foodItems = FoodItem::all();
|
||||
$addons = Addon::all();
|
||||
$restaurantId = Restaurant::first()?->id; // optional
|
||||
|
||||
foreach ($foodItems as $food) {
|
||||
// randomly assign 1-3 addons
|
||||
$randomAddons = $addons->random(rand(1, 3));
|
||||
|
||||
foreach ($randomAddons as $addon) {
|
||||
DB::table('addon_food')->insert([
|
||||
'restaurant_id' => $restaurantId,
|
||||
'food_item_id' => $food->id,
|
||||
'addon_id' => $addon->id,
|
||||
'status' => 1,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Restaurant\Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Modules\Restaurant\Models\Addon;
|
||||
|
||||
class AddonTableSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$addons = [
|
||||
['name' => 'Cookie', 'price' => 2.50, 'vat' => 5, 'pst' => 0, 'status' => 1],
|
||||
['name' => 'Chilli Sauce', 'price' => 1.20, 'vat' => 5, 'pst' => 0, 'status' => 1],
|
||||
['name' => 'Sour Plum Powder', 'price' => 0.99, 'vat' => 5, 'pst' => 0, 'status' => 1],
|
||||
['name' => 'Extra Meat', 'price' => 3.99, 'vat' => 5, 'pst' => 0, 'status' => 1],
|
||||
['name' => 'BBQ Sauce', 'price' => 1.50, 'vat' => 5, 'pst' => 0, 'status' => 1],
|
||||
['name' => 'Fresh Milk', 'price' => 2.00, 'vat' => 5, 'pst' => 0, 'status' => 1],
|
||||
['name' => 'Enoki Mushrooms', 'price' => 2.99, 'vat' => 5, 'pst' => 0, 'status' => 1],
|
||||
['name' => 'Chilli Padi', 'price' => 0.80, 'vat' => 5, 'pst' => 0, 'status' => 1],
|
||||
['name' => 'Cheese', 'price' => 2.50, 'vat' => 5, 'pst' => 0, 'status' => 1],
|
||||
['name' => 'Soup of the Day', 'price' => 3.99, 'vat' => 5, 'pst' => 0, 'status' => 1],
|
||||
];
|
||||
|
||||
foreach ($addons as $addon) {
|
||||
Addon::updateOrCreate(['restaurant_id' => 1, 'name' => $addon['name']], $addon);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Restaurant\Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Modules\Restaurant\Models\FoodAvailability;
|
||||
use Modules\Restaurant\Models\FoodAvailabilityTime;
|
||||
|
||||
class FoodAvailabilityTableSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$restaurantId = 1; // demo
|
||||
$foodItemId = 1; // demo
|
||||
$days = [
|
||||
'Sunday',
|
||||
'Monday',
|
||||
'Tuesday',
|
||||
'Wednesday',
|
||||
'Thursday',
|
||||
'Friday',
|
||||
'Saturday',
|
||||
];
|
||||
|
||||
$defaultTimeSlots = [
|
||||
['open_time' => '09:00:00', 'close_time' => '12:00:00'],
|
||||
['open_time' => '13:00:00', 'close_time' => '17:00:00'],
|
||||
['open_time' => '18:00:00', 'close_time' => '22:00:00'],
|
||||
];
|
||||
|
||||
foreach ($days as $day) {
|
||||
// Create availability per day
|
||||
$availability = FoodAvailability::create([
|
||||
'restaurant_id' => $restaurantId,
|
||||
'food_item_id' => $foodItemId,
|
||||
'day' => $day,
|
||||
'is_available' => true,
|
||||
]);
|
||||
|
||||
// Create time slots
|
||||
foreach ($defaultTimeSlots as $slot) {
|
||||
FoodAvailabilityTime::create([
|
||||
'food_availability_id' => $availability->id,
|
||||
'open_time' => $slot['open_time'],
|
||||
'close_time' => $slot['close_time'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Restaurant\Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Modules\Restaurant\Models\FoodCategory;
|
||||
|
||||
class FoodCategoryTableSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
FoodCategory::create([
|
||||
'restaurant_id' => 1,
|
||||
'name' => 'Biryani & Rice',
|
||||
'image' => 'biryani_rice.jpg',
|
||||
'parent_id' => null,
|
||||
'status' => 1,
|
||||
'is_offer' => false,
|
||||
'start_date' => '2023-01-01',
|
||||
'end_date' => null,
|
||||
]);
|
||||
|
||||
FoodCategory::create([
|
||||
'restaurant_id' => 1,
|
||||
'name' => 'Tandoori Specials',
|
||||
'image' => 'tandoori_specials.jpg',
|
||||
'parent_id' => null,
|
||||
'status' => 1,
|
||||
'is_offer' => true,
|
||||
'start_date' => '2023-11-01',
|
||||
'end_date' => '2023-12-31',
|
||||
]);
|
||||
|
||||
FoodCategory::create([
|
||||
'restaurant_id' => 1,
|
||||
'name' => 'Naan & Breads',
|
||||
'image' => 'naan_breads.jpg',
|
||||
'parent_id' => null,
|
||||
'status' => 1,
|
||||
'is_offer' => false,
|
||||
'start_date' => '2022-10-10',
|
||||
'end_date' => null,
|
||||
]);
|
||||
|
||||
FoodCategory::create([
|
||||
'restaurant_id' => 1,
|
||||
'name' => 'South Indian',
|
||||
'image' => 'south_indian.jpg',
|
||||
'parent_id' => null,
|
||||
'status' => 1,
|
||||
'is_offer' => false,
|
||||
'start_date' => '2023-02-01',
|
||||
'end_date' => null,
|
||||
]);
|
||||
|
||||
FoodCategory::create([
|
||||
'restaurant_id' => 1,
|
||||
'name' => 'Chinese Cuisine',
|
||||
'image' => 'chinese.jpg',
|
||||
'parent_id' => null,
|
||||
'status' => 1,
|
||||
'is_offer' => true,
|
||||
'start_date' => '2024-05-01',
|
||||
'end_date' => '2024-07-01',
|
||||
]);
|
||||
|
||||
FoodCategory::create([
|
||||
'restaurant_id' => 1,
|
||||
'name' => 'Snacks & Starters',
|
||||
'image' => 'starters.jpg',
|
||||
'parent_id' => null,
|
||||
'status' => 1,
|
||||
'is_offer' => false,
|
||||
'start_date' => '2023-03-01',
|
||||
'end_date' => null,
|
||||
]);
|
||||
|
||||
FoodCategory::create([
|
||||
'restaurant_id' => 1,
|
||||
'name' => 'Desserts',
|
||||
'image' => 'desserts.jpg',
|
||||
'parent_id' => null,
|
||||
'status' => 1,
|
||||
'is_offer' => true,
|
||||
'start_date' => '2024-12-01',
|
||||
'end_date' => '2025-01-10',
|
||||
]);
|
||||
|
||||
FoodCategory::create([
|
||||
'restaurant_id' => 1,
|
||||
'name' => 'Beverages',
|
||||
'image' => 'beverages.jpg',
|
||||
'parent_id' => null,
|
||||
'status' => 1,
|
||||
'is_offer' => false,
|
||||
'start_date' => '2022-10-10',
|
||||
'end_date' => null,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Restaurant\Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Modules\Restaurant\Models\FoodItem;
|
||||
|
||||
class FoodItemTableSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
FoodItem::create([
|
||||
'restaurant_id' => 1,
|
||||
'menu_category_id' => 1,
|
||||
'menu_section_id' => 1,
|
||||
'name' => 'Butter Chicken',
|
||||
'description' => 'Rich and creamy tomato-based chicken curry',
|
||||
'category_id' => 2, // e.g., Tandoori Specials
|
||||
'food_type' => 'Non-Veg',
|
||||
'is_party' => 1,
|
||||
'is_dinner' => 1,
|
||||
'is_lunch' => 1,
|
||||
'is_chef_special' => 1,
|
||||
'is_popular_item' => 1,
|
||||
'image' => 'butter_chicken.jpg',
|
||||
'cooking_time' => '00:25:00',
|
||||
'notes' => 'Pairs well with naan or rice',
|
||||
'vat' => 5,
|
||||
'pst' => 2,
|
||||
'status' => 1,
|
||||
]);
|
||||
|
||||
FoodItem::create([
|
||||
'restaurant_id' => 1,
|
||||
'menu_category_id' => 1,
|
||||
'menu_section_id' => 1,
|
||||
'name' => 'Vegetable Biryani',
|
||||
'description' => 'Fragrant basmati rice with mixed vegetables and spices',
|
||||
'category_id' => 1, // Biryani & Rice
|
||||
'food_type' => 'Veg',
|
||||
'is_party' => 1,
|
||||
'is_dinner' => 1,
|
||||
'is_lunch' => 1,
|
||||
'is_chef_special' => 1,
|
||||
'is_popular_item' => 1,
|
||||
'image' => 'veg_biryani.jpg',
|
||||
'cooking_time' => '00:30:00',
|
||||
'notes' => 'Best served with raita',
|
||||
'vat' => 5,
|
||||
'pst' => 0,
|
||||
'status' => 1,
|
||||
]);
|
||||
|
||||
FoodItem::create([
|
||||
'restaurant_id' => 1,
|
||||
'menu_category_id' => 1,
|
||||
'menu_section_id' => 1,
|
||||
'name' => 'Masala Dosa',
|
||||
'description' => 'Crispy rice pancake filled with spiced potato masala',
|
||||
'category_id' => 4, // South Indian
|
||||
'food_type' => 'Veg',
|
||||
'is_party' => 0,
|
||||
'is_dinner' => 0,
|
||||
'is_lunch' => 1,
|
||||
'is_chef_special' => 0,
|
||||
'is_popular_item' => 1,
|
||||
'image' => 'masala_dosa.jpg',
|
||||
'cooking_time' => '00:20:00',
|
||||
'notes' => 'Serve with coconut chutney and sambar',
|
||||
'vat' => 5,
|
||||
'pst' => 0,
|
||||
'status' => 1,
|
||||
]);
|
||||
|
||||
FoodItem::create([
|
||||
'restaurant_id' => 1,
|
||||
'menu_category_id' => 1,
|
||||
'menu_section_id' => 1,
|
||||
'name' => 'Spring Rolls',
|
||||
'description' => 'Crispy fried rolls stuffed with mixed vegetables',
|
||||
'category_id' => 5, // Chinese Cuisine
|
||||
'food_type' => 'Veg',
|
||||
'is_party' => 1,
|
||||
'is_dinner' => 0,
|
||||
'is_lunch' => 0,
|
||||
'is_chef_special' => 1,
|
||||
'is_popular_item' => 0,
|
||||
'image' => 'spring_rolls.jpg',
|
||||
'cooking_time' => '00:15:00',
|
||||
'notes' => 'Good as a starter',
|
||||
'vat' => 5,
|
||||
'pst' => 1,
|
||||
'status' => 1,
|
||||
]);
|
||||
|
||||
FoodItem::create([
|
||||
'restaurant_id' => 1,
|
||||
'menu_category_id' => 1,
|
||||
'menu_section_id' => 1,
|
||||
'name' => 'Chicken Manchurian',
|
||||
'description' => 'Fried chicken balls tossed in spicy tangy sauce',
|
||||
'category_id' => 5,
|
||||
'food_type' => 'Non-Veg',
|
||||
'is_party' => 1,
|
||||
'is_dinner' => 1,
|
||||
'is_lunch' => 1,
|
||||
'is_chef_special' => 1,
|
||||
'is_popular_item' => 0,
|
||||
'image' => 'chicken_manchurian.jpg',
|
||||
'cooking_time' => '00:25:00',
|
||||
'notes' => 'Serve with fried rice or noodles',
|
||||
'vat' => 5,
|
||||
'pst' => 2,
|
||||
'status' => 1,
|
||||
]);
|
||||
|
||||
FoodItem::create([
|
||||
'restaurant_id' => 1,
|
||||
'menu_category_id' => 1,
|
||||
'menu_section_id' => 1,
|
||||
'name' => 'Paneer Tikka',
|
||||
'description' => 'Grilled cottage cheese cubes marinated in Indian spices',
|
||||
'category_id' => 2,
|
||||
'food_type' => 'Veg',
|
||||
'is_party' => 1,
|
||||
'is_dinner' => 1,
|
||||
'is_lunch' => 0,
|
||||
'is_chef_special' => 0,
|
||||
'is_popular_item' => 1,
|
||||
'image' => 'paneer_tikka.jpg',
|
||||
'cooking_time' => '00:20:00',
|
||||
'notes' => 'Serve with mint chutney',
|
||||
'vat' => 5,
|
||||
'pst' => 1,
|
||||
'status' => 1,
|
||||
]);
|
||||
|
||||
FoodItem::create([
|
||||
'restaurant_id' => 1,
|
||||
'menu_category_id' => 1,
|
||||
'menu_section_id' => 1,
|
||||
'name' => 'Gulab Jamun',
|
||||
'description' => 'Soft deep-fried dumplings soaked in sugar syrup',
|
||||
'category_id' => 7, // Desserts
|
||||
'food_type' => 'Veg',
|
||||
'is_party' => 1,
|
||||
'is_dinner' => 0,
|
||||
'is_lunch' => 0,
|
||||
'is_chef_special' => 0,
|
||||
'is_popular_item' => 1,
|
||||
'image' => 'gulab_jamun.jpg',
|
||||
'cooking_time' => '00:10:00',
|
||||
'notes' => 'Serve warm',
|
||||
'vat' => 5,
|
||||
'pst' => 0,
|
||||
'status' => 1,
|
||||
]);
|
||||
|
||||
FoodItem::create([
|
||||
'restaurant_id' => 1,
|
||||
'menu_category_id' => 1,
|
||||
'menu_section_id' => 1,
|
||||
'name' => 'Lassi',
|
||||
'description' => 'Refreshing yogurt-based drink',
|
||||
'category_id' => 8, // Beverages
|
||||
'food_type' => 'Veg',
|
||||
'is_party' => 0,
|
||||
'is_dinner' => 0,
|
||||
'is_lunch' => 1,
|
||||
'is_chef_special' => 1,
|
||||
'is_popular_item' => 0,
|
||||
'image' => 'lassi.jpg',
|
||||
'cooking_time' => '00:05:00',
|
||||
'notes' => 'Serve chilled',
|
||||
'vat' => 5,
|
||||
'pst' => 0,
|
||||
'status' => 1,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Restaurant\Database\Seeders;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class FoodVariantIngredientSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$now = Carbon::now();
|
||||
|
||||
$data = [
|
||||
// 🍔 Beef Burger (variant_id = 1)
|
||||
[
|
||||
'restaurant_id' => 1,
|
||||
'food_variant_id' => 1,
|
||||
'ingredient_id' => 1, // Beef Patty
|
||||
'quantity' => 1,
|
||||
'wastage_percentage' => 2,
|
||||
'unit_conversion_factor' => 1,
|
||||
'optional' => 'N',
|
||||
'notes' => '150g patty',
|
||||
'status' => 1,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
],
|
||||
[
|
||||
'restaurant_id' => 1,
|
||||
'food_variant_id' => 1,
|
||||
'ingredient_id' => 2, // Burger Bun
|
||||
'quantity' => 1,
|
||||
'wastage_percentage' => 1,
|
||||
'unit_conversion_factor' => 1,
|
||||
'optional' => 'N',
|
||||
'notes' => 'Fresh baked bun',
|
||||
'status' => 1,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
],
|
||||
[
|
||||
'restaurant_id' => 1,
|
||||
'food_variant_id' => 1,
|
||||
'ingredient_id' => 3, // Cheese Slice
|
||||
'quantity' => 1,
|
||||
'wastage_percentage' => 0,
|
||||
'unit_conversion_factor' => 1,
|
||||
'optional' => 'Y',
|
||||
'notes' => 'Optional cheese topping',
|
||||
'status' => 1,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
],
|
||||
[
|
||||
'restaurant_id' => 1,
|
||||
'food_variant_id' => 1,
|
||||
'ingredient_id' => 4, // Tomato
|
||||
'quantity' => 0.05,
|
||||
'wastage_percentage' => 5,
|
||||
'unit_conversion_factor' => 1,
|
||||
'optional' => 'N',
|
||||
'notes' => 'Fresh tomato slices',
|
||||
'status' => 1,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
],
|
||||
[
|
||||
'restaurant_id' => 1,
|
||||
'food_variant_id' => 1,
|
||||
'ingredient_id' => 5, // Lettuce
|
||||
'quantity' => 0.03,
|
||||
'wastage_percentage' => 5,
|
||||
'unit_conversion_factor' => 1,
|
||||
'optional' => 'N',
|
||||
'notes' => 'Crisp lettuce leaves',
|
||||
'status' => 1,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
],
|
||||
|
||||
// 🍟 French Fries (variant_id = 2)
|
||||
[
|
||||
'restaurant_id' => 1,
|
||||
'food_variant_id' => 2,
|
||||
'ingredient_id' => 6, // Potato
|
||||
'quantity' => 0.25,
|
||||
'wastage_percentage' => 8,
|
||||
'unit_conversion_factor' => 1,
|
||||
'optional' => 'N',
|
||||
'notes' => 'Peeled & sliced',
|
||||
'status' => 1,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
],
|
||||
[
|
||||
'restaurant_id' => 1,
|
||||
'food_variant_id' => 2,
|
||||
'ingredient_id' => 7, // Salt
|
||||
'quantity' => 0.005,
|
||||
'wastage_percentage' => 0,
|
||||
'unit_conversion_factor' => 1,
|
||||
'optional' => 'N',
|
||||
'notes' => 'Seasoning',
|
||||
'status' => 1,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
],
|
||||
[
|
||||
'restaurant_id' => 1,
|
||||
'food_variant_id' => 2,
|
||||
'ingredient_id' => 8, // Oil
|
||||
'quantity' => 0.05,
|
||||
'wastage_percentage' => 10,
|
||||
'unit_conversion_factor' => 1,
|
||||
'optional' => 'N',
|
||||
'notes' => 'For deep frying',
|
||||
'status' => 1,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
],
|
||||
|
||||
// 🍕 Margherita Pizza (variant_id = 3)
|
||||
[
|
||||
'restaurant_id' => 1,
|
||||
'food_variant_id' => 3,
|
||||
'ingredient_id' => 9, // Pizza Dough
|
||||
'quantity' => 0.25,
|
||||
'wastage_percentage' => 3,
|
||||
'unit_conversion_factor' => 1,
|
||||
'optional' => 'N',
|
||||
'notes' => 'Prepared dough base',
|
||||
'status' => 1,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
],
|
||||
[
|
||||
'restaurant_id' => 1,
|
||||
'food_variant_id' => 3,
|
||||
'ingredient_id' => 10, // Tomato Sauce
|
||||
'quantity' => 0.10,
|
||||
'wastage_percentage' => 2,
|
||||
'unit_conversion_factor' => 1,
|
||||
'optional' => 'N',
|
||||
'notes' => 'Base sauce',
|
||||
'status' => 1,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
],
|
||||
[
|
||||
'restaurant_id' => 1,
|
||||
'food_variant_id' => 3,
|
||||
'ingredient_id' => 11, // Mozzarella Cheese
|
||||
'quantity' => 0.15,
|
||||
'wastage_percentage' => 2,
|
||||
'unit_conversion_factor' => 1,
|
||||
'optional' => 'N',
|
||||
'notes' => 'Fresh mozzarella',
|
||||
'status' => 1,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
],
|
||||
[
|
||||
'restaurant_id' => 1,
|
||||
'food_variant_id' => 3,
|
||||
'ingredient_id' => 12, // Basil
|
||||
'quantity' => 0.005,
|
||||
'wastage_percentage' => 5,
|
||||
'unit_conversion_factor' => 1,
|
||||
'optional' => 'N',
|
||||
'notes' => 'Fresh basil leaves',
|
||||
'status' => 1,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
],
|
||||
[
|
||||
'restaurant_id' => 1,
|
||||
'food_variant_id' => 3,
|
||||
'ingredient_id' => 13, // Olive Oil
|
||||
'quantity' => 0.02,
|
||||
'wastage_percentage' => 0,
|
||||
'unit_conversion_factor' => 1,
|
||||
'optional' => 'N',
|
||||
'notes' => 'Drizzle after baking',
|
||||
'status' => 1,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
],
|
||||
];
|
||||
|
||||
DB::table('food_variant_ingredients')->insert($data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Restaurant\Database\Seeders;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Str;
|
||||
use Modules\Restaurant\Models\FoodVariant;
|
||||
|
||||
class FoodVariantTableSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$variants = [
|
||||
// Garlic Naan (food_item_id = 1)
|
||||
['food_item_id' => 1, 'name' => 'Single Piece', 'price' => 1.99, 'offer_price' => 1.79, 'discount' => 10, 'unit_id' => 1],
|
||||
['food_item_id' => 1, 'name' => 'Double Piece', 'price' => 3.49, 'offer_price' => 2.99, 'discount' => 14, 'unit_id' => 1],
|
||||
|
||||
// Butter Chicken (food_item_id = 2)
|
||||
['food_item_id' => 2, 'name' => 'Half Plate', 'price' => 6.99, 'offer_price' => 6.49, 'discount' => 7, 'unit_id' => 1],
|
||||
['food_item_id' => 2, 'name' => 'Full Plate', 'price' => 11.99, 'offer_price' => 10.99, 'discount' => 8, 'unit_id' => 1],
|
||||
|
||||
// Vegetable Biryani (food_item_id = 3)
|
||||
['food_item_id' => 3, 'name' => 'Regular', 'price' => 5.49, 'offer_price' => 4.99, 'discount' => 9, 'unit_id' => 1],
|
||||
['food_item_id' => 3, 'name' => 'Family Pack', 'price' => 9.99, 'offer_price' => 8.99, 'discount' => 10, 'unit_id' => 1],
|
||||
|
||||
// Masala Dosa (food_item_id = 4)
|
||||
['food_item_id' => 4, 'name' => 'Classic', 'price' => 4.99, 'offer_price' => 4.49, 'discount' => 10, 'unit_id' => 1],
|
||||
['food_item_id' => 4, 'name' => 'Cheese Masala Dosa', 'price' => 6.49, 'offer_price' => 5.99, 'discount' => 8, 'unit_id' => 1],
|
||||
|
||||
// Spring Rolls (food_item_id = 5)
|
||||
['food_item_id' => 5, 'name' => '4 pcs', 'price' => 3.99, 'offer_price' => 3.49, 'discount' => 12, 'unit_id' => 1],
|
||||
['food_item_id' => 5, 'name' => '8 pcs', 'price' => 6.99, 'offer_price' => 6.49, 'discount' => 7, 'unit_id' => 1],
|
||||
|
||||
// Paneer Tikka (food_item_id = 6)
|
||||
['food_item_id' => 6, 'name' => '6 pcs', 'price' => 5.49, 'offer_price' => 4.99, 'discount' => 9, 'unit_id' => 1],
|
||||
['food_item_id' => 6, 'name' => '10 pcs', 'price' => 8.99, 'offer_price' => 7.99, 'discount' => 11, 'unit_id' => 1],
|
||||
|
||||
// Gulab Jamun (food_item_id = 7)
|
||||
['food_item_id' => 7, 'name' => '2 pcs', 'price' => 2.49, 'offer_price' => 2.29, 'discount' => 8, 'unit_id' => 1],
|
||||
['food_item_id' => 7, 'name' => '5 pcs', 'price' => 5.49, 'offer_price' => 4.99, 'discount' => 9, 'unit_id' => 1],
|
||||
|
||||
// Lassi (food_item_id = 8)
|
||||
['food_item_id' => 8, 'name' => 'Regular Glass', 'price' => 2.99, 'offer_price' => 2.49, 'discount' => 17, 'unit_id' => 1],
|
||||
['food_item_id' => 8, 'name' => 'Large Glass', 'price' => 3.99, 'offer_price' => 3.49, 'discount' => 12, 'unit_id' => 1],
|
||||
];
|
||||
|
||||
$foodItemDefaultMap = []; // Track default per food item
|
||||
foreach ($variants as $variant) {
|
||||
$foodItemId = $variant['food_item_id'];
|
||||
// Assign default only if not assigned before
|
||||
$isDefault = isset($foodItemDefaultMap[$foodItemId]) ? false : true;
|
||||
if ($isDefault) {
|
||||
$foodItemDefaultMap[$foodItemId] = true;
|
||||
}
|
||||
|
||||
FoodVariant::create([
|
||||
'restaurant_id' => 1,
|
||||
'food_item_id' => $foodItemId,
|
||||
'name' => $variant['name'],
|
||||
'sku' => 'FV-'.strtoupper(Str::random(8)),
|
||||
'price' => $variant['price'],
|
||||
'offer_price' => $variant['offer_price'],
|
||||
'discount' => $variant['discount'],
|
||||
'unit_id' => $variant['unit_id'],
|
||||
'description' => $variant['name'].' variant for food ID '.$foodItemId,
|
||||
'is_default' => $isDefault,
|
||||
'status' => 1,
|
||||
'offer_start_at' => Carbon::now(),
|
||||
'offer_end_at' => Carbon::now()->addDays(rand(5, 30)),
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Restaurant\Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Modules\Restaurant\Models\Ingredient;
|
||||
use Modules\Restaurant\Models\IngredientDamage;
|
||||
|
||||
class IngredientDamageSeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
$ingredients = Ingredient::limit(5)->get();
|
||||
|
||||
foreach ($ingredients as $ingredient) {
|
||||
IngredientDamage::create([
|
||||
'restaurant_id' => $ingredient->restaurant_id,
|
||||
'ingredient_id' => $ingredient->id,
|
||||
'batch_no' => 'BATCH-'.rand(100, 999),
|
||||
'quantity' => rand(1, 20),
|
||||
'unit_cost' => rand(10, 500),
|
||||
'total_cost' => rand(10, 500) * rand(1, 20),
|
||||
'reason' => ['Spoilage', 'Breakage', 'Expired'][array_rand(['Spoilage', 'Breakage', 'Expired'])],
|
||||
'damage_date' => now()->subDays(rand(0, 30)),
|
||||
'reported_by' => 1, // Admin/User ID
|
||||
'status' => 1,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Restaurant\Database\Seeders;
|
||||
|
||||
use Faker\Factory as Faker;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Modules\Restaurant\Models\Ingredient;
|
||||
use Modules\Restaurant\Models\Supplier;
|
||||
|
||||
class IngredientSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$faker = Faker::create();
|
||||
$restaurantId = 1; // Change or randomize if multi-restaurant setup
|
||||
|
||||
// Try to get existing supplier IDs
|
||||
$supplierIds = Supplier::pluck('id')->toArray();
|
||||
|
||||
$units = [1, 2, 3, 4, 5];
|
||||
$categories = ['Vegetable', 'Meat', 'Dairy', 'Beverage', 'Spices', 'Grains', 'Bakery', 'Seafood', 'Fruits', 'Others'];
|
||||
|
||||
$ingredients = [];
|
||||
|
||||
for ($i = 1; $i <= 50; $i++) {
|
||||
$unit = $faker->randomElement($units);
|
||||
$category = $faker->randomElement($categories);
|
||||
$supplierId = ! empty($supplierIds) ? $faker->randomElement($supplierIds) : null;
|
||||
|
||||
$costPerUnit = $faker->randomFloat(2, 10, 500);
|
||||
$stockQty = $faker->randomFloat(2, 5, 500);
|
||||
$lowStock = $faker->randomFloat(2, 1, 10);
|
||||
|
||||
$ingredients[] = [
|
||||
'restaurant_id' => $restaurantId,
|
||||
'supplier_id' => $supplierId,
|
||||
'name' => ucfirst($faker->word),
|
||||
'unit_id' => $unit,
|
||||
'stock_quantity' => $stockQty,
|
||||
'cost_per_unit' => $costPerUnit,
|
||||
'low_stock_alert' => $lowStock,
|
||||
'last_purchase_price' => $faker->optional()->randomFloat(2, 10, 500),
|
||||
'last_purchase_date' => $faker->optional()->date(),
|
||||
'conversion_factor' => $faker->randomFloat(2, 0.5, 2),
|
||||
'reserved_quantity' => $faker->randomFloat(2, 0, 20),
|
||||
'wastage_quantity' => $faker->randomFloat(2, 0, 10),
|
||||
'category' => $category,
|
||||
'notes' => $faker->optional()->sentence(10),
|
||||
'status' => $faker->randomElement([0, 1]),
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
];
|
||||
}
|
||||
|
||||
Ingredient::insert($ingredients);
|
||||
|
||||
$this->command->info('✅ Seeded 50 ingredients successfully.');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Restaurant\Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Str;
|
||||
use Modules\Restaurant\Models\MenuCategory;
|
||||
|
||||
class MenuCategorySeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$categories = [
|
||||
[
|
||||
'restaurant_id' => 1,
|
||||
'name' => 'Coffee',
|
||||
'icon' => 'coffee.png',
|
||||
'description' => 'Hot and cold coffee beverages made from premium beans.',
|
||||
'priority' => 1,
|
||||
'status' => true,
|
||||
],
|
||||
[
|
||||
'restaurant_id' => 1,
|
||||
'name' => 'Fast Food',
|
||||
'icon' => 'burger.png',
|
||||
'description' => 'Quick bites and delicious fast-food meals.',
|
||||
'priority' => 2,
|
||||
'status' => true,
|
||||
],
|
||||
[
|
||||
'restaurant_id' => 1,
|
||||
'name' => 'Pizza',
|
||||
'icon' => 'pizza.png',
|
||||
'description' => 'Freshly baked pizzas with various toppings.',
|
||||
'priority' => 3,
|
||||
'status' => true,
|
||||
],
|
||||
[
|
||||
'restaurant_id' => 1,
|
||||
'name' => 'Desi Menu',
|
||||
'icon' => 'desi.png',
|
||||
'description' => 'Authentic local dishes with a traditional touch.',
|
||||
'priority' => 4,
|
||||
'status' => true,
|
||||
],
|
||||
[
|
||||
'restaurant_id' => 1,
|
||||
'name' => 'Desserts',
|
||||
'icon' => 'dessert.png',
|
||||
'description' => 'Sweet treats to complete your meal.',
|
||||
'priority' => 5,
|
||||
'status' => true,
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($categories as $cat) {
|
||||
MenuCategory::updateOrCreate(
|
||||
['slug' => Str::slug($cat['name'])],
|
||||
array_merge($cat, ['slug' => Str::slug($cat['name'])])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Restaurant\Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Str;
|
||||
use Modules\Restaurant\Models\MenuCategory;
|
||||
use Modules\Restaurant\Models\MenuSection;
|
||||
|
||||
class MenuSectionSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$sections = [
|
||||
// Coffee
|
||||
[
|
||||
'menu_category' => 'Coffee',
|
||||
'name' => 'Hot Coffee',
|
||||
'description' => 'Classic and premium hot coffee menu.',
|
||||
'priority' => 1,
|
||||
'status' => true,
|
||||
],
|
||||
[
|
||||
'menu_category' => 'Coffee',
|
||||
'name' => 'Cold Coffee',
|
||||
'description' => 'Iced and refreshing cold coffee menu.',
|
||||
'priority' => 2,
|
||||
'status' => true,
|
||||
],
|
||||
|
||||
// Fast Food
|
||||
[
|
||||
'menu_category' => 'Fast Food',
|
||||
'name' => 'Burgers',
|
||||
'description' => 'Delicious burgers made fresh to order.',
|
||||
'priority' => 1,
|
||||
'status' => true,
|
||||
],
|
||||
[
|
||||
'menu_category' => 'Fast Food',
|
||||
'name' => 'Wraps',
|
||||
'description' => 'Tasty wraps filled with fresh ingredients.',
|
||||
'priority' => 2,
|
||||
'status' => true,
|
||||
],
|
||||
|
||||
// Pizza
|
||||
[
|
||||
'menu_category' => 'Pizza',
|
||||
'name' => 'Regular Pizzas',
|
||||
'description' => 'Classic pizzas with standard toppings.',
|
||||
'priority' => 1,
|
||||
'status' => true,
|
||||
],
|
||||
[
|
||||
'menu_category' => 'Pizza',
|
||||
'name' => 'Special Pizzas',
|
||||
'description' => 'Signature pizzas with unique flavors.',
|
||||
'priority' => 2,
|
||||
'status' => true,
|
||||
],
|
||||
|
||||
// Desi Menu
|
||||
[
|
||||
'menu_category' => 'Desi Menu',
|
||||
'name' => 'Rice Items',
|
||||
'description' => 'Traditional rice dishes served with curry.',
|
||||
'priority' => 1,
|
||||
'status' => true,
|
||||
],
|
||||
[
|
||||
'menu_category' => 'Desi Menu',
|
||||
'name' => 'Curry Items',
|
||||
'description' => 'Spicy and flavorful local curries.',
|
||||
'priority' => 2,
|
||||
'status' => true,
|
||||
],
|
||||
|
||||
// Desserts
|
||||
[
|
||||
'menu_category' => 'Desserts',
|
||||
'name' => 'Cakes',
|
||||
'description' => 'Freshly baked cakes for every occasion.',
|
||||
'priority' => 1,
|
||||
'status' => true,
|
||||
],
|
||||
[
|
||||
'menu_category' => 'Desserts',
|
||||
'name' => 'Ice Creams',
|
||||
'description' => 'Cool and creamy ice cream delights.',
|
||||
'priority' => 2,
|
||||
'status' => true,
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($sections as $sec) {
|
||||
$category = MenuCategory::where('name', $sec['menu_category'])->first();
|
||||
|
||||
if ($category) {
|
||||
MenuSection::updateOrCreate(
|
||||
['slug' => Str::slug($sec['name'])],
|
||||
[
|
||||
'restaurant_id' => 1,
|
||||
'menu_category_id' => $category->id,
|
||||
'name' => $sec['name'],
|
||||
'slug' => Str::slug($sec['name']),
|
||||
'description' => $sec['description'],
|
||||
'priority' => $sec['priority'],
|
||||
'status' => $sec['status'],
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Restaurant\Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Modules\Restaurant\Models\MenuType;
|
||||
|
||||
class MenuTypeTableSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$menuTypes = [
|
||||
['name' => 'Party', 'icon' => 'party.jpg', 'status' => 1],
|
||||
['name' => 'Coffee', 'icon' => 'coffee.jpg', 'status' => 1],
|
||||
['name' => 'Dinner', 'icon' => 'dinner.jpg', 'status' => 1],
|
||||
['name' => 'Launch', 'icon' => 'launch.jpg', 'status' => 1],
|
||||
];
|
||||
|
||||
foreach ($menuTypes as $type) {
|
||||
MenuType::create([
|
||||
'restaurant_id' => 1,
|
||||
'name' => $type['name'],
|
||||
'icon' => 'uploads/menu/'.$type['icon'],
|
||||
'status' => $type['status'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Restaurant\Database\Seeders;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Modules\Authentication\Models\User;
|
||||
use Modules\Restaurant\Models\Customer;
|
||||
use Modules\Restaurant\Models\FoodItem;
|
||||
use Modules\Restaurant\Models\Order;
|
||||
use Modules\Restaurant\Models\OrderItem;
|
||||
use Modules\Restaurant\Models\PaymentMethod;
|
||||
use Modules\Restaurant\Models\Table;
|
||||
|
||||
class OrderSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$foods = FoodItem::all();
|
||||
$tables = Table::all();
|
||||
$customers = Customer::all();
|
||||
$paymentMethods = PaymentMethod::all();
|
||||
$waiter = User::first(); // assume 1st user is waiter
|
||||
|
||||
// Prevent running if no data available
|
||||
if ($foods->isEmpty() || $tables->isEmpty() || $customers->isEmpty() || $paymentMethods->isEmpty()) {
|
||||
$this->command->warn('⚠️ Missing related data (foods, tables, customers, or payment methods). Seeder skipped.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (range(1, 100) as $i) {
|
||||
// Pick a random order date within the last 30 days
|
||||
$orderDate = Carbon::now()->subDays(rand(0, 29))->setTime(rand(10, 22), [0, 30][rand(0, 1)]);
|
||||
|
||||
// Create main order
|
||||
$order = Order::create([
|
||||
'restaurant_id' => 1,
|
||||
'order_type' => collect(['dine_in', 'takeaway', 'delivery'])->random(),
|
||||
'order_number' => 'ORD-'.$orderDate->format('Ymd').'-'.rand(1000, 99999),
|
||||
'status' => collect(['pending', 'completed', 'cancelled'])->random(),
|
||||
'order_date' => $orderDate,
|
||||
'table_id' => $tables->random()->id,
|
||||
'payment_method_id' => $paymentMethods->random()->id,
|
||||
'payment_status' => collect([0, 1])->random(),
|
||||
'waiter_id' => $waiter?->id,
|
||||
'customer_id' => $customers->random()->id,
|
||||
'grand_total' => 0,
|
||||
]);
|
||||
|
||||
// Add random items
|
||||
$total = 0;
|
||||
foreach ($foods->random(rand(1, 3)) as $food) {
|
||||
$qty = rand(1, 2);
|
||||
$price = $food->price ?? 100;
|
||||
$lineTotal = $qty * $price;
|
||||
|
||||
OrderItem::create([
|
||||
'restaurant_id' => 1,
|
||||
'order_id' => $order->id,
|
||||
'food_item_id' => $food->id,
|
||||
'quantity' => $qty,
|
||||
'price' => $price,
|
||||
'total' => $lineTotal,
|
||||
]);
|
||||
|
||||
$total += $lineTotal;
|
||||
}
|
||||
|
||||
$order->update(['grand_total' => $total]);
|
||||
}
|
||||
|
||||
$this->command->info('✅ 100 random orders seeded successfully (within the last 30 days).');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Restaurant\Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Modules\Restaurant\Models\PaymentMethod;
|
||||
|
||||
class PaymentMethodSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$methods = ['Cash', 'Card', 'Online'];
|
||||
|
||||
foreach ($methods as $method) {
|
||||
PaymentMethod::create([
|
||||
'restaurant_id' => 1,
|
||||
'name' => $method,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Restaurant\Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Modules\Restaurant\Models\PurchaseItem;
|
||||
use Modules\Restaurant\Models\PurchaseReturn;
|
||||
|
||||
class PurchaseReturnSeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
$purchaseItems = PurchaseItem::limit(5)->get();
|
||||
|
||||
foreach ($purchaseItems as $item) {
|
||||
$returnQty = rand(1, max(1, (int) ($item->received_quantity - $item->returned_quantity)));
|
||||
|
||||
PurchaseReturn::create([
|
||||
'restaurant_id' => $item->restaurant_id,
|
||||
'purchase_id' => $item->purchase_id,
|
||||
'purchase_item_id' => $item->id,
|
||||
'ingredient_id' => $item->ingredient_id,
|
||||
'batch_no' => $item->batch_no,
|
||||
'quantity' => $returnQty,
|
||||
'unit_cost' => $item->unit_price,
|
||||
'total_cost' => $item->unit_price * $returnQty,
|
||||
'reason' => ['Damaged', 'Expired', 'Supplier Return'][array_rand(['Damaged', 'Expired', 'Supplier Return'])],
|
||||
'return_date' => now()->subDays(rand(0, 10)),
|
||||
'processed_by' => 1, // Admin/User ID
|
||||
'status' => 1,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Restaurant\Database\Seeders;
|
||||
|
||||
use Faker\Factory as Faker;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Str;
|
||||
use Modules\Authentication\Models\User;
|
||||
use Modules\Restaurant\Models\Ingredient;
|
||||
use Modules\Restaurant\Models\Purchase;
|
||||
use Modules\Restaurant\Models\PurchaseItem;
|
||||
use Modules\Restaurant\Models\Stock;
|
||||
use Modules\Restaurant\Models\Supplier;
|
||||
|
||||
class PurchaseSeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
$faker = Faker::create();
|
||||
|
||||
$restaurantId = 1; // set dynamically later if needed
|
||||
$supplierIds = Supplier::pluck('id')->toArray();
|
||||
$ingredientIds = Ingredient::pluck('id')->toArray();
|
||||
$userIds = User::pluck('id')->toArray();
|
||||
|
||||
if (empty($supplierIds) || empty($ingredientIds)) {
|
||||
$this->command->warn('⚠️ Skipping PurchaseSeeder: No suppliers or ingredients found.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$purchaseCount = rand(10, 20);
|
||||
|
||||
for ($i = 1; $i <= $purchaseCount; $i++) {
|
||||
$supplierId = $faker->randomElement($supplierIds);
|
||||
$createdBy = ! empty($userIds) ? $faker->randomElement($userIds) : null;
|
||||
|
||||
$purchase = Purchase::create([
|
||||
'restaurant_id' => $restaurantId,
|
||||
'supplier_id' => $supplierId,
|
||||
'invoice_no' => strtoupper(Str::random(8)),
|
||||
'purchase_date' => $faker->dateTimeBetween('-3 months', 'now'),
|
||||
'sub_total' => 0,
|
||||
'discount_amount' => 0,
|
||||
'tax_amount' => 0,
|
||||
'total_amount' => 0,
|
||||
'payment_status' => $faker->randomElement(['paid', 'unpaid', 'partial']),
|
||||
'payment_method' => $faker->randomElement(['cash', 'bank', 'credit']),
|
||||
'purchase_type' => $faker->randomElement(['ingredient', 'equipment', 'others']),
|
||||
'created_by' => $createdBy,
|
||||
'notes' => $faker->optional()->sentence(10),
|
||||
'status' => 1,
|
||||
]);
|
||||
|
||||
$itemCount = rand(2, 6);
|
||||
$subTotal = $taxTotal = $discountTotal = 0;
|
||||
|
||||
for ($j = 1; $j <= $itemCount; $j++) {
|
||||
$ingredientId = $faker->randomElement($ingredientIds);
|
||||
$quantity = $faker->randomFloat(2, 1, 20);
|
||||
$unitPrice = $faker->randomFloat(2, 10, 500);
|
||||
$tax = $faker->randomFloat(2, 0, 10);
|
||||
$discount = $faker->randomFloat(2, 0, 5);
|
||||
|
||||
$totalCost = ($unitPrice * $quantity) + $tax - $discount;
|
||||
|
||||
$item = PurchaseItem::create([
|
||||
'restaurant_id' => $restaurantId,
|
||||
'purchase_id' => $purchase->id,
|
||||
'ingredient_id' => $ingredientId,
|
||||
'quantity' => $quantity,
|
||||
'unit_price' => $unitPrice,
|
||||
'total_cost' => $totalCost,
|
||||
'tax_amount' => $tax,
|
||||
'discount_amount' => $discount,
|
||||
'batch_no' => strtoupper(Str::random(6)),
|
||||
'expiry_date' => $faker->optional()->dateTimeBetween('now', '+1 year'),
|
||||
'received_quantity' => $quantity,
|
||||
'wastage_quantity' => $faker->randomFloat(2, 0, 1),
|
||||
'returned_quantity' => $faker->randomFloat(2, 0, 1),
|
||||
'status' => 1,
|
||||
]);
|
||||
|
||||
// ✅ Stock Adjustment
|
||||
Stock::create([
|
||||
'restaurant_id' => $restaurantId,
|
||||
'ingredient_id' => $ingredientId,
|
||||
'type' => 'purchase',
|
||||
'quantity' => $quantity,
|
||||
'unit_cost' => $unitPrice,
|
||||
'total_cost' => $totalCost,
|
||||
'reference_type' => 'Purchase',
|
||||
'purchase_id' => $purchase->id,
|
||||
'batch_no' => $item->batch_no,
|
||||
'expiry_date' => $item->expiry_date,
|
||||
'added_by' => $createdBy,
|
||||
'remarks' => 'Auto stock-in from purchase #'.$purchase->invoice_no,
|
||||
'status' => 1,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
|
||||
$subTotal += ($unitPrice * $quantity);
|
||||
$taxTotal += $tax;
|
||||
$discountTotal += $discount;
|
||||
}
|
||||
|
||||
$purchase->update([
|
||||
'sub_total' => $subTotal,
|
||||
'tax_amount' => $taxTotal,
|
||||
'discount_amount' => $discountTotal,
|
||||
'total_amount' => ($subTotal + $taxTotal - $discountTotal),
|
||||
]);
|
||||
}
|
||||
|
||||
$this->command->info("✅ Seeded {$purchaseCount} purchases with items and stock adjustments successfully.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Restaurant\Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Modules\Restaurant\Models\QRMenuSetting;
|
||||
|
||||
class QRMenuSettingTableSeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
QRMenuSetting::create([
|
||||
'restaurant_id' => 1,
|
||||
'name' => 'Default QR Menu',
|
||||
'menu_title' => 'Our Menu',
|
||||
'primary_color' => '#FF5722',
|
||||
'secondary_color' => '#FFC107',
|
||||
'bg_color' => '#FFFFFF',
|
||||
'template' => 'template_1',
|
||||
'description' => 'Welcome to our digital menu!',
|
||||
'wifi_name' => 'Restaurant-WiFi',
|
||||
'wifi_ssid' => 'RESTO1234',
|
||||
'wifi_password' => '12345678',
|
||||
'status' => 1, // active/inactive
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Restaurant\Database\Seeders;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class ReservationSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
// Sample restaurant and table IDs
|
||||
$restaurantIds = [1];
|
||||
$tableIds = [1, 2, 3, 4, 5];
|
||||
$customerIds = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
|
||||
|
||||
// Clear old data
|
||||
DB::table('reservations')->truncate();
|
||||
DB::table('reservation_unavailables')->truncate();
|
||||
|
||||
// Seed reservations
|
||||
foreach (range(1, 10) as $i) {
|
||||
$restaurantId = $restaurantIds[array_rand($restaurantIds)];
|
||||
$tableId = $tableIds[array_rand($tableIds)];
|
||||
$customerId = $customerIds[array_rand($customerIds)];
|
||||
|
||||
$date = Carbon::now()->addDays(rand(0, 5))->toDateString();
|
||||
$startTime = Carbon::createFromTime(rand(10, 20), [0, 30][rand(0, 1)]);
|
||||
$endTime = (clone $startTime)->addHours(2);
|
||||
|
||||
DB::table('reservations')->insert([
|
||||
'restaurant_id' => $restaurantId,
|
||||
'table_id' => $tableId,
|
||||
'customer_id' => $customerId,
|
||||
'reservation_date' => $date,
|
||||
'start_time' => $startTime->format('H:i:s'),
|
||||
'end_time' => $endTime->format('H:i:s'),
|
||||
'people_count' => rand(2, 8),
|
||||
'status' => collect(['booked', 'free', 'upcoming', 'cancelled'])->random(),
|
||||
'note' => fake()->sentence(),
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
}
|
||||
|
||||
// Seed unavailable times
|
||||
foreach (range(1, 5) as $i) {
|
||||
$restaurantId = $restaurantIds[array_rand($restaurantIds)];
|
||||
$tableId = $tableIds[array_rand($tableIds)];
|
||||
|
||||
$date = Carbon::now()->addDays(rand(0, 5))->toDateString();
|
||||
$startTime = Carbon::createFromTime(rand(10, 22), [0, 30][rand(0, 1)]);
|
||||
$endTime = (clone $startTime)->addHours(rand(1, 3));
|
||||
|
||||
DB::table('reservation_unavailables')->insert([
|
||||
'restaurant_id' => $restaurantId,
|
||||
'table_id' => $tableId,
|
||||
'date' => $date,
|
||||
'start_time' => $startTime->format('H:i:s'),
|
||||
'end_time' => $endTime->format('H:i:s'),
|
||||
'reason' => fake()->sentence(),
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Restaurant\Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class RestaurantDatabaseSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$this->call([
|
||||
QRMenuSettingTableSeeder::class,
|
||||
FoodCategoryTableSeeder::class,
|
||||
MenuCategorySeeder::class,
|
||||
MenuSectionSeeder::class,
|
||||
MenuTypeTableSeeder::class,
|
||||
AddonTableSeeder::class,
|
||||
UnitSeeder::class,
|
||||
FoodItemTableSeeder::class,
|
||||
AddonFoodSeeder::class,
|
||||
FoodVariantTableSeeder::class,
|
||||
FoodAvailabilityTableSeeder::class,
|
||||
RestaurantScheduleTableSeeder::class,
|
||||
SupplierSeeder::class,
|
||||
TableSeeder::class,
|
||||
PaymentMethodSeeder::class,
|
||||
IngredientSeeder::class,
|
||||
// Food Variant Ingredient
|
||||
FoodVariantIngredientSeeder::class,
|
||||
// Purchase
|
||||
PurchaseSeeder::class,
|
||||
PurchaseReturnSeeder::class,
|
||||
IngredientDamageSeeder::class,
|
||||
ReservationSeeder::class,
|
||||
// Order
|
||||
OrderSeeder::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Restaurant\Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Modules\Restaurant\Models\RestaurantSchedule;
|
||||
use Modules\Restaurant\Models\RestaurantScheduleTime;
|
||||
|
||||
class RestaurantScheduleTableSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$restaurantId = 1; // demo restaurant id
|
||||
|
||||
$days = [
|
||||
'Sunday',
|
||||
'Monday',
|
||||
'Tuesday',
|
||||
'Wednesday',
|
||||
'Thursday',
|
||||
'Friday',
|
||||
'Saturday',
|
||||
];
|
||||
|
||||
// Default demo opening time slots
|
||||
$defaultTimeSlots = [
|
||||
['open_time' => '08:00:00', 'close_time' => '12:00:00'],
|
||||
['open_time' => '13:00:00', 'close_time' => '17:00:00'],
|
||||
['open_time' => '18:00:00', 'close_time' => '23:00:00'],
|
||||
];
|
||||
|
||||
foreach ($days as $day) {
|
||||
|
||||
// Create day-wise schedule
|
||||
$schedule = RestaurantSchedule::create([
|
||||
'restaurant_id' => $restaurantId,
|
||||
'day' => $day,
|
||||
'is_open' => true, // default restaurant is open
|
||||
]);
|
||||
|
||||
// Insert multiple time slots
|
||||
foreach ($defaultTimeSlots as $slot) {
|
||||
RestaurantScheduleTime::create([
|
||||
'restaurant_schedule_id' => $schedule->id,
|
||||
'open_time' => $slot['open_time'],
|
||||
'close_time' => $slot['close_time'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Restaurant\Database\Seeders;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Faker\Factory as Faker;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class SupplierSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$faker = Faker::create();
|
||||
|
||||
$count = rand(10, 50);
|
||||
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
DB::table('suppliers')->insert([
|
||||
'restaurant_id' => 1,
|
||||
'name' => $faker->name,
|
||||
'phone' => $faker->phoneNumber,
|
||||
'company_name' => $faker->company,
|
||||
'contact_person' => $faker->name,
|
||||
'alternate_phone' => $faker->optional()->phoneNumber,
|
||||
'email' => $faker->optional()->safeEmail,
|
||||
'website' => $faker->optional()->url,
|
||||
|
||||
'address' => $faker->address,
|
||||
'city' => $faker->city,
|
||||
'state' => $faker->state,
|
||||
'country' => $faker->country,
|
||||
'postal_code' => $faker->postcode,
|
||||
|
||||
'tax_number' => $faker->optional()->numerify('TAX#######'),
|
||||
'bank_name' => $faker->optional()->company,
|
||||
'bank_account_name' => $faker->optional()->name,
|
||||
'bank_account_number' => $faker->optional()->numerify('##########'),
|
||||
'ifsc_code' => $faker->optional()->bothify('BANK####'),
|
||||
'opening_balance' => $faker->randomFloat(2, 0, 50000),
|
||||
'opening_balance_date' => $faker->optional()->date(),
|
||||
'due' => $faker->randomFloat(2, 0, 10000),
|
||||
'balance' => $faker->randomFloat(2, 0, 10000),
|
||||
|
||||
'supply_type' => $faker->randomElement(['Food', 'Beverage', 'Cleaning', 'Equipment']),
|
||||
'payment_terms' => $faker->randomElement(['Net 7', 'Net 15', 'Net 30', 'COD']),
|
||||
'credit_limit' => $faker->optional()->randomFloat(2, 1000, 50000),
|
||||
|
||||
'rating' => $faker->randomFloat(2, 3, 5),
|
||||
'notes' => $faker->optional()->sentence(10),
|
||||
|
||||
'contract_file' => null,
|
||||
'trade_license' => $faker->optional()->numerify('TL-######'),
|
||||
'nid_number' => $faker->optional()->numerify('NID##########'),
|
||||
|
||||
'status' => $faker->randomElement([1, 2]),
|
||||
'created_at' => Carbon::now(),
|
||||
'updated_at' => Carbon::now(),
|
||||
]);
|
||||
}
|
||||
|
||||
$this->command->info("✅ Seeded {$count} suppliers successfully.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Restaurant\Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Modules\Restaurant\Models\Table;
|
||||
|
||||
class TableSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$sections = ['Main Hall', 'VIP Area', 'Outdoor'];
|
||||
$tableTypes = ['regular', 'vip', 'outdoor', 'booth'];
|
||||
|
||||
foreach (range(1, 10) as $num) {
|
||||
Table::create([
|
||||
'restaurant_id' => 1,
|
||||
'name' => 'T'.str_pad($num, 2, '0', STR_PAD_LEFT),
|
||||
'serial' => 'T'.str_pad($num, 2, '0', STR_PAD_LEFT),
|
||||
'location' => 'Floor 1',
|
||||
'section' => $sections[array_rand($sections)],
|
||||
'table_type' => $tableTypes[array_rand($tableTypes)],
|
||||
'capacity' => rand(2, 6),
|
||||
'is_bookable' => true,
|
||||
'qr_code' => 'QR'.str_pad($num, 2, '0', STR_PAD_LEFT),
|
||||
'image' => null,
|
||||
'position_x' => rand(50, 500),
|
||||
'position_y' => rand(50, 500),
|
||||
'rotation' => rand(0, 360),
|
||||
'z_index' => rand(1, 10),
|
||||
'status' => 1,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Restaurant\Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Modules\Restaurant\Models\Unit;
|
||||
|
||||
class UnitSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$restaurantId = 1; // fixed restaurant_id
|
||||
|
||||
// === Weight Units ===
|
||||
$gram = Unit::create([
|
||||
'restaurant_id' => $restaurantId,
|
||||
'name' => 'Gram',
|
||||
'short_name' => 'g',
|
||||
'type' => 'weight',
|
||||
'is_default' => 1,
|
||||
]);
|
||||
|
||||
Unit::create([
|
||||
'restaurant_id' => $restaurantId,
|
||||
'name' => 'Kilogram',
|
||||
'short_name' => 'kg',
|
||||
'type' => 'weight',
|
||||
'base_unit_id' => $gram->id,
|
||||
'operator' => '*',
|
||||
'operator_value' => 1000,
|
||||
]);
|
||||
|
||||
Unit::create([
|
||||
'restaurant_id' => $restaurantId,
|
||||
'name' => 'Milligram',
|
||||
'short_name' => 'mg',
|
||||
'type' => 'weight',
|
||||
'base_unit_id' => $gram->id,
|
||||
'operator' => '/',
|
||||
'operator_value' => 1000,
|
||||
]);
|
||||
|
||||
Unit::create([
|
||||
'restaurant_id' => $restaurantId,
|
||||
'name' => 'Pound',
|
||||
'short_name' => 'lb',
|
||||
'type' => 'weight',
|
||||
'base_unit_id' => $gram->id,
|
||||
'operator' => '*',
|
||||
'operator_value' => 453.592,
|
||||
]);
|
||||
|
||||
Unit::create([
|
||||
'restaurant_id' => $restaurantId,
|
||||
'name' => 'Ounce',
|
||||
'short_name' => 'oz',
|
||||
'type' => 'weight',
|
||||
'base_unit_id' => $gram->id,
|
||||
'operator' => '*',
|
||||
'operator_value' => 28.3495,
|
||||
]);
|
||||
|
||||
// === Volume Units ===
|
||||
$ml = Unit::create([
|
||||
'restaurant_id' => $restaurantId,
|
||||
'name' => 'Milliliter',
|
||||
'short_name' => 'ml',
|
||||
'type' => 'volume',
|
||||
'is_default' => 1,
|
||||
]);
|
||||
|
||||
Unit::create([
|
||||
'restaurant_id' => $restaurantId,
|
||||
'name' => 'Liter',
|
||||
'short_name' => 'l',
|
||||
'type' => 'volume',
|
||||
'base_unit_id' => $ml->id,
|
||||
'operator' => '*',
|
||||
'operator_value' => 1000,
|
||||
]);
|
||||
|
||||
Unit::create([
|
||||
'restaurant_id' => $restaurantId,
|
||||
'name' => 'Teaspoon',
|
||||
'short_name' => 'tsp',
|
||||
'type' => 'volume',
|
||||
'base_unit_id' => $ml->id,
|
||||
'operator' => '*',
|
||||
'operator_value' => 5,
|
||||
]);
|
||||
|
||||
Unit::create([
|
||||
'restaurant_id' => $restaurantId,
|
||||
'name' => 'Tablespoon',
|
||||
'short_name' => 'tbsp',
|
||||
'type' => 'volume',
|
||||
'base_unit_id' => $ml->id,
|
||||
'operator' => '*',
|
||||
'operator_value' => 15,
|
||||
]);
|
||||
|
||||
// === Count Units ===
|
||||
Unit::create([
|
||||
'restaurant_id' => $restaurantId,
|
||||
'name' => 'Piece',
|
||||
'short_name' => 'pcs',
|
||||
'type' => 'count',
|
||||
'is_default' => 1,
|
||||
]);
|
||||
|
||||
// === Length Units ===
|
||||
$meter = Unit::create([
|
||||
'restaurant_id' => $restaurantId,
|
||||
'name' => 'Meter',
|
||||
'short_name' => 'm',
|
||||
'type' => 'length',
|
||||
'is_default' => 1,
|
||||
]);
|
||||
|
||||
Unit::create([
|
||||
'restaurant_id' => $restaurantId,
|
||||
'name' => 'Centimeter',
|
||||
'short_name' => 'cm',
|
||||
'type' => 'length',
|
||||
'base_unit_id' => $meter->id,
|
||||
'operator' => '/',
|
||||
'operator_value' => 100,
|
||||
]);
|
||||
|
||||
Unit::create([
|
||||
'restaurant_id' => $restaurantId,
|
||||
'name' => 'Millimeter',
|
||||
'short_name' => 'mm',
|
||||
'type' => 'length',
|
||||
'base_unit_id' => $meter->id,
|
||||
'operator' => '/',
|
||||
'operator_value' => 1000,
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user