diff --git a/app/Models/Additional.php b/app/Models/Additional.php new file mode 100644 index 0000000..9c93acd --- /dev/null +++ b/app/Models/Additional.php @@ -0,0 +1,23 @@ +hasMany(DetailAdditional::class, 'id_additional'); + } +} diff --git a/app/Models/BookingFoto.php b/app/Models/BookingFoto.php new file mode 100644 index 0000000..1047d9d --- /dev/null +++ b/app/Models/BookingFoto.php @@ -0,0 +1,41 @@ +belongsTo(Pelanggan::class, 'id_pelanggan'); + } + + public function paketFoto() + { + return $this->belongsTo(PaketFoto::class, 'id_paket'); + } + + public function detailAdditional() + { + return $this->hasMany(DetailAdditional::class, 'id_booking'); + } +} diff --git a/app/Models/Buket.php b/app/Models/Buket.php new file mode 100644 index 0000000..59b994e --- /dev/null +++ b/app/Models/Buket.php @@ -0,0 +1,28 @@ +hasMany(TransaksiBuket::class, 'id_buket'); + } +} diff --git a/app/Models/DetailAdditional.php b/app/Models/DetailAdditional.php new file mode 100644 index 0000000..f7fc096 --- /dev/null +++ b/app/Models/DetailAdditional.php @@ -0,0 +1,31 @@ +belongsTo(BookingFoto::class, 'id_booking'); + } + + public function additional() + { + return $this->belongsTo(Additional::class, 'id_additional'); + } +} diff --git a/app/Models/PaketFoto.php b/app/Models/PaketFoto.php new file mode 100644 index 0000000..4bd7e9a --- /dev/null +++ b/app/Models/PaketFoto.php @@ -0,0 +1,27 @@ +hasMany(BookingFoto::class, 'id_paket'); + } +} diff --git a/app/Models/Pelanggan.php b/app/Models/Pelanggan.php new file mode 100644 index 0000000..99f1b36 --- /dev/null +++ b/app/Models/Pelanggan.php @@ -0,0 +1,30 @@ +hasMany(TransaksiBuket::class, 'id_pelanggan'); + } + + public function bookingFoto() + { + return $this->hasMany(BookingFoto::class, 'id_pelanggan'); + } +} diff --git a/app/Models/TransaksiBuket.php b/app/Models/TransaksiBuket.php new file mode 100644 index 0000000..b14a919 --- /dev/null +++ b/app/Models/TransaksiBuket.php @@ -0,0 +1,36 @@ +belongsTo(Pelanggan::class, 'id_pelanggan'); + } + + public function buket() + { + return $this->belongsTo(Buket::class, 'id_buket'); + } +} diff --git a/app/Models/User.php b/app/Models/User.php index 749c7b7..6496b9b 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -2,47 +2,29 @@ namespace App\Models; -// use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; class User extends Authenticatable { - /** @use HasFactory<\Database\Factories\UserFactory> */ use HasFactory, Notifiable; - /** - * The attributes that are mass assignable. - * - * @var list - */ + protected $table = 'users'; + protected $primaryKey = 'id_user'; + protected $fillable = [ - 'name', + 'nama', + 'username', 'email', 'password', + 'no_wa', + 'alamat', + 'role', ]; - /** - * The attributes that should be hidden for serialization. - * - * @var list - */ protected $hidden = [ 'password', 'remember_token', ]; - - /** - * Get the attributes that should be cast. - * - * @return array - */ - protected function casts(): array - { - return [ - 'email_verified_at' => 'datetime', - 'password' => 'hashed', - ]; - } } diff --git a/database/migrations/0001_01_01_000000_create_users_table.php b/database/migrations/0001_01_01_000000_create_users_table.php index 05fb5d9..2f27299 100644 --- a/database/migrations/0001_01_01_000000_create_users_table.php +++ b/database/migrations/0001_01_01_000000_create_users_table.php @@ -12,21 +12,16 @@ public function up(): void { Schema::create('users', function (Blueprint $table) { - $table->id(); - $table->string('name'); + $table->id('id_user'); // Primary Key custom sesuai ERD + $table->string('nama'); + $table->string('username')->unique(); $table->string('email')->unique(); - $table->timestamp('email_verified_at')->nullable(); $table->string('password'); - $table->rememberToken(); + $table->string('no_wa', 20)->nullable(); + $table->text('alamat')->nullable(); + $table->enum('role', ['admin', 'pemilik']); // Enum Role $table->timestamps(); }); - - Schema::create('password_reset_tokens', function (Blueprint $table) { - $table->string('email')->primary(); - $table->string('token'); - $table->timestamp('created_at')->nullable(); - }); - Schema::create('sessions', function (Blueprint $table) { $table->string('id')->primary(); $table->foreignId('user_id')->nullable()->index(); @@ -43,7 +38,6 @@ public function up(): void public function down(): void { Schema::dropIfExists('users'); - Schema::dropIfExists('password_reset_tokens'); Schema::dropIfExists('sessions'); } }; diff --git a/database/migrations/2025_12_26_150422_create_bukets_table.php b/database/migrations/2025_12_26_150422_create_bukets_table.php new file mode 100644 index 0000000..83274e3 --- /dev/null +++ b/database/migrations/2025_12_26_150422_create_bukets_table.php @@ -0,0 +1,34 @@ +id('id_buket'); + $table->string('nama'); + $table->text('deskripsi')->nullable(); + $table->decimal('harga', 10, 2); // Format uang + $table->string('foto')->nullable(); + // Enum sesuai diskusi Wireframe & ERD + $table->enum('kategori', ['single', 'fresh', 'premium_fresh', 'artificial']); + $table->enum('ukuran', ['S', 'M', 'L']); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('bukets'); + } +}; diff --git a/database/migrations/2025_12_26_150455_create_paket_fotos_table.php b/database/migrations/2025_12_26_150455_create_paket_fotos_table.php new file mode 100644 index 0000000..339af58 --- /dev/null +++ b/database/migrations/2025_12_26_150455_create_paket_fotos_table.php @@ -0,0 +1,32 @@ +id('id_paket'); + $table->string('nama'); + $table->text('deskripsi')->nullable(); + $table->decimal('harga', 10, 2); + $table->string('foto')->nullable(); + $table->integer('durasi'); // Dalam menit + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('paket_fotos'); + } +}; diff --git a/database/migrations/2025_12_26_150512_create_additionals_table.php b/database/migrations/2025_12_26_150512_create_additionals_table.php new file mode 100644 index 0000000..4f5494a --- /dev/null +++ b/database/migrations/2025_12_26_150512_create_additionals_table.php @@ -0,0 +1,29 @@ +id('id_additional'); + $table->string('nama'); + $table->decimal('harga', 10, 2); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('additionals'); + } +}; diff --git a/database/migrations/2025_12_26_150527_create_pelanggans_table.php b/database/migrations/2025_12_26_150527_create_pelanggans_table.php new file mode 100644 index 0000000..eafaf04 --- /dev/null +++ b/database/migrations/2025_12_26_150527_create_pelanggans_table.php @@ -0,0 +1,29 @@ +id('id_pelanggan'); + $table->string('nama'); + $table->string('no_wa', 20); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('pelanggans'); + } +}; diff --git a/database/migrations/2025_12_26_150607_create_transaksi_bukets_table.php b/database/migrations/2025_12_26_150607_create_transaksi_bukets_table.php new file mode 100644 index 0000000..2d10797 --- /dev/null +++ b/database/migrations/2025_12_26_150607_create_transaksi_bukets_table.php @@ -0,0 +1,41 @@ +id('id_transaksi'); + $table->string('no_invoice')->unique(); // Contoh: INV-BKT-001 + + // Foreign Keys + $table->foreignId('id_pelanggan')->constrained('pelanggans', 'id_pelanggan')->onDelete('cascade'); + $table->foreignId('id_buket')->constrained('bukets', 'id_buket')->onDelete('cascade'); + + $table->text('request')->nullable(); // Catatan khusus + $table->dateTime('tgl_ambil'); + $table->decimal('total_bayar', 12, 2); + $table->string('bukti_bayar')->nullable(); + + // Enum Status Final + $table->enum('status_transaksi', ['menunggu_verifikasi', 'diproses', 'selesai', 'dibatalkan'])->default('menunggu_verifikasi'); + + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('transaksi_bukets'); + } +}; diff --git a/database/migrations/2025_12_26_150621_create_booking_fotos_table.php b/database/migrations/2025_12_26_150621_create_booking_fotos_table.php new file mode 100644 index 0000000..17d9b56 --- /dev/null +++ b/database/migrations/2025_12_26_150621_create_booking_fotos_table.php @@ -0,0 +1,42 @@ +id('id_booking'); + $table->string('no_invoice')->unique(); // Contoh: INV-FOTO-001 + + // Foreign Keys + $table->foreignId('id_pelanggan')->constrained('pelanggans', 'id_pelanggan')->onDelete('cascade'); + $table->foreignId('id_paket')->constrained('paket_fotos', 'id_paket')->onDelete('cascade'); + + $table->date('tgl_booking'); + $table->time('jam_mulai'); + $table->time('jam_selesai'); + $table->decimal('total_bayar', 12, 2); + $table->string('bukti_bayar')->nullable(); + + // Enum Status Final + $table->enum('status_booking', ['menunggu_verifikasi', 'diproses', 'selesai', 'dibatalkan'])->default('menunggu_verifikasi'); + + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('booking_fotos'); + } +}; diff --git a/database/migrations/2025_12_26_150637_create_detail_additionals_table.php b/database/migrations/2025_12_26_150637_create_detail_additionals_table.php new file mode 100644 index 0000000..140f16e --- /dev/null +++ b/database/migrations/2025_12_26_150637_create_detail_additionals_table.php @@ -0,0 +1,34 @@ +id('id_detail_additional'); + + // Foreign Keys + $table->foreignId('id_booking')->constrained('booking_fotos', 'id_booking')->onDelete('cascade'); + $table->foreignId('id_additional')->constrained('additionals', 'id_additional')->onDelete('cascade'); + + $table->integer('qty'); + $table->decimal('subtotal', 12, 2); // Harga Additional * Qty + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('detail_additionals'); + } +}; diff --git a/database/seeders/AdditionalSeeder.php b/database/seeders/AdditionalSeeder.php new file mode 100644 index 0000000..c5e8903 --- /dev/null +++ b/database/seeders/AdditionalSeeder.php @@ -0,0 +1,22 @@ + 'Timer', 'harga' => 5000], + ['nama' => 'Kostum boneka', 'harga' => 35000], + ['nama' => 'Bando Kucing', 'harga' => 10000], + ['nama' => 'Spotlight', 'harga' => 15000], + ['nama' => 'Cetak', 'harga' => 5000], + ]; + + DB::table('additionals')->insert($data); + } +} diff --git a/database/seeders/BuketSeeder.php b/database/seeders/BuketSeeder.php new file mode 100644 index 0000000..8b724c0 --- /dev/null +++ b/database/seeders/BuketSeeder.php @@ -0,0 +1,41 @@ + 'Buket Mawar Merah Premium', + 'harga' => 150000, + 'deskripsi' => 'Buket mawar merah segar isi 10 tangkai dengan wrapping premium.', + 'kategori' => 'fresh', + 'ukuran' => 'S', + 'foto' => 'img/buket/buket1.jpg', + ], + [ + 'nama' => 'Snack Bouquet Choco', + 'harga' => 75000, + 'deskripsi' => 'Buket isi beng-beng, pocky, dan coklat silverqueen.', + 'kategori' => 'single', + 'ukuran' => 'M', + 'foto' => 'img/buket/buket2.jpg', + ], + [ + 'nama' => 'Money Bouquet 500k', + 'harga' => 550000, // Harga jasa + uang + 'deskripsi' => 'Buket uang pecahan 50rb total 500rb, jasa rangkai free kartu ucapan.', + 'kategori' => 'artificial', + 'ukuran' => 'L', + 'foto' => 'img/buket/buket3.jpg', + ], + ]; + + DB::table('bukets')->insert($data); + } +} diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 6b901f8..80fe3b3 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -2,24 +2,18 @@ namespace Database\Seeders; -use App\Models\User; -use Illuminate\Database\Console\Seeds\WithoutModelEvents; use Illuminate\Database\Seeder; class DatabaseSeeder extends Seeder { - use WithoutModelEvents; - - /** - * Seed the application's database. - */ public function run(): void { - // User::factory(10)->create(); - - User::factory()->create([ - 'name' => 'Test User', - 'email' => 'test@example.com', + $this->call([ + UserSeeder::class, // Akun Admin + BuketSeeder::class, // Produk + PaketFotoSeeder::class, // Produk + AdditionalSeeder::class, // Tambahan + PelangganSeeder::class, // Customer Dummy ]); } } diff --git a/database/seeders/PaketFotoSeeder.php b/database/seeders/PaketFotoSeeder.php new file mode 100644 index 0000000..6852029 --- /dev/null +++ b/database/seeders/PaketFotoSeeder.php @@ -0,0 +1,38 @@ + 'Wisuda Basic', + 'harga' => 250000, + 'deskripsi' => 'Foto wisuda outdoor 1 jam, 10 edit file, all file mentah.', + 'foto' => 'img/foto/foto1.jpeg', + 'durasi' => '60', + ], + [ + 'nama' => 'Couple Studio Session', + 'harga' => 350000, + 'deskripsi' => 'Foto studio couple 45 menit, 2 cetak 10R, 5 edit file.', + 'foto' => 'img/foto/foto2.jpeg', + 'durasi' => '45', + ], + [ + 'nama' => 'Group Photoshoot (Max 10 Orang)', + 'harga' => 500000, + 'deskripsi' => 'Foto grup, cocok untuk angkatan atau keluarga besar. Durasi 2 jam.', + 'foto' => 'img/foto/foto3.jpeg', + 'durasi' => '120', + ], + ]; + + DB::table('paket_fotos')->insert($data); + } +} diff --git a/database/seeders/PelangganSeeder.php b/database/seeders/PelangganSeeder.php new file mode 100644 index 0000000..9c89c66 --- /dev/null +++ b/database/seeders/PelangganSeeder.php @@ -0,0 +1,25 @@ + 'Siti Aminah', + 'no_wa' => '081234567890', + ], + [ + 'nama' => 'Budi Santoso', + 'no_wa' => '089876543210', + ], + ]; + + DB::table('pelanggans')->insert($data); + } +} diff --git a/database/seeders/UserSeeder.php b/database/seeders/UserSeeder.php new file mode 100644 index 0000000..71746bb --- /dev/null +++ b/database/seeders/UserSeeder.php @@ -0,0 +1,35 @@ +insert([ + 'nama' => 'Bilqis', + 'username' => 'admin1', + 'email' => 'admin@flodo.com', + 'password' => Hash::make('password123'), + 'no_wa' => '0893781263', + 'alamat' => 'Kauman', + 'role' => 'admin', + 'created_at' => now(), + 'updated_at' => now(), + ], [ + 'nama' => 'Debby', + 'username' => 'ownerdebby', + 'email' => 'debby@flodo.com', + 'password' => Hash::make('password123'), + 'no_wa' => '0893781263', + 'alamat' => 'Kauman', + 'role' => 'owner', + 'created_at' => now(), + 'updated_at' => now(), + ]); + } +}