parfum/database/seeders/OrderSeeder.php

150 lines
4.4 KiB
PHP

<?php
namespace Database\Seeders;
use App\Enums\OrderChannel;
use App\Enums\OrderStatus;
use App\Models\Customer;
use App\Models\Order;
use App\Models\OrderItem;
use App\Models\Outlet;
use App\Models\Perfume;
use App\Models\Product;
use App\Models\User;
use Illuminate\Database\Seeder;
use Illuminate\Support\Collection;
class OrderSeeder extends Seeder
{
public function run(): void
{
$outlets = Outlet::all();
if ($outlets->isEmpty()) {
$outlets = Outlet::factory(3)->create();
}
$users = User::all();
if ($users->isEmpty()) {
$users = User::factory(5)->create();
}
$customers = Customer::all();
if ($customers->isEmpty()) {
$customers = Customer::factory(20)->create();
}
$perfumes = Perfume::all();
$products = Product::all();
if ($perfumes->isEmpty() && $products->isEmpty()) {
$perfumes = Perfume::factory(10)->create();
}
$orderableItems = collect();
if ($perfumes->isNotEmpty()) {
$orderableItems = $orderableItems->merge($perfumes);
}
if ($products->isNotEmpty()) {
$orderableItems = $orderableItems->merge($products);
}
$startDate = now()->subMonths(6);
$endDate = now();
$orderCount = 0;
for ($date = $startDate->copy(); $date->lte($endDate); $date->addDay()) {
$ordersPerDay = rand(1, 10);
for ($i = 0; $i < $ordersPerDay; $i++) {
$orderCount++;
$outlet = $outlets->random();
$user = $users->random();
$customer = $customers->random();
$status = $this->getRandomStatus();
$orderedAt = $date->copy()->addHours(rand(8, 22))->addMinutes(rand(0, 59));
$order = Order::create([
'outlet_id' => $outlet->id,
'user_id' => $user->id,
'customer_id' => $customer->id,
'voucher_id' => null,
'invoice_number' => 'INV'.$orderedAt->format('Ymd').str_pad($orderCount, 4, '0', STR_PAD_LEFT),
'channel' => OrderChannel::OUTLET,
'status' => $status,
'ordered_at' => $orderedAt,
'created_at' => $orderedAt,
'updated_at' => $orderedAt,
'cogs' => 0,
'subtotal' => 0,
'discount' => 0,
'voucher_discount' => 0,
'total' => 0,
]);
$this->createOrderItems($order, $user, $orderableItems);
}
}
}
private function getRandomStatus(): OrderStatus
{
$rand = rand(1, 100);
if ($rand <= 80) {
return OrderStatus::PAID;
}
if ($rand <= 90) {
return OrderStatus::PENDING;
}
if ($rand <= 95) {
return OrderStatus::CANCELED;
}
return OrderStatus::DRAFT;
}
private function createOrderItems(Order $order, User $user, Collection $orderables): void
{
$itemCount = rand(1, 5);
$totalCogs = 0;
$totalSubtotal = 0;
for ($j = 0; $j < $itemCount; $j++) {
$item = $orderables->random();
$qty = rand(20, 100);
$price = $item->sale_price ?? rand(50000, 150000);
$cogs = $item->cost_price ?? (int) ($price * 0.4);
OrderItem::create([
'order_id' => $order->id,
'user_id' => $user->id,
'orderable_type' => $item->getMorphClass(),
'orderable_id' => $item->id,
'quantity' => $qty,
'unit_price' => $price,
'cogs' => $cogs,
'created_at' => $order->ordered_at,
'updated_at' => $order->ordered_at,
]);
$totalCogs += ($cogs * $qty);
$totalSubtotal += ($price * $qty);
}
$discount = rand(1, 100) > 80 ? rand(5000, 20000) : 0;
if ($discount > $totalSubtotal) {
$discount = 0;
}
$total = $totalSubtotal - $discount;
$order->update([
'cogs' => $totalCogs,
'subtotal' => $totalSubtotal,
'discount' => $discount,
'total' => $total,
]);
}
}