- menyesuaikan model jika ada yang salah seperti kurangnya trait SoftDeletes, casting yang salah, relasi yang kurang dan lainnya - memperbaiki enum di migrasi
197 lines
5.9 KiB
PHP
197 lines
5.9 KiB
PHP
<?php
|
|
|
|
namespace Database\Factories;
|
|
|
|
use App\Enums\OrderChannel;
|
|
use App\Enums\OrderStatus;
|
|
use App\Models\Customer;
|
|
use App\Models\Order;
|
|
use App\Models\Outlet;
|
|
use App\Models\User;
|
|
use App\Models\Voucher;
|
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
|
|
|
class OrderFactory extends Factory
|
|
{
|
|
protected $model = Order::class;
|
|
|
|
public function definition(): array
|
|
{
|
|
$subtotal = $this->faker->numberBetween(50000, 1000000);
|
|
$discount = $this->faker->numberBetween(0, (int) ($subtotal * 0.3)); // Max 30% discount
|
|
$total = $subtotal - $discount;
|
|
$cogs = (int) ($subtotal * 0.4); // COGS is typically 40% of subtotal
|
|
|
|
// Generate invoice number: INV + YYYYMMDD + 4 digit sequence
|
|
// For testing, use random sequence to ensure uniqueness
|
|
$sequence = $this->faker->numberBetween(1, 9999);
|
|
$invoiceNumber = 'INV'.now()->format('Ymd').str_pad($sequence, 4, '0', STR_PAD_LEFT);
|
|
|
|
return [
|
|
'outlet_id' => Outlet::factory(),
|
|
'user_id' => User::factory(),
|
|
'customer_id' => null,
|
|
'voucher_id' => null,
|
|
'invoice_number' => $invoiceNumber,
|
|
'cogs' => $cogs,
|
|
'subtotal' => $subtotal,
|
|
'discount' => $discount,
|
|
'total' => $total,
|
|
'channel' => fake()->randomElement(OrderChannel::cases()),
|
|
'status' => fake()->randomElement(OrderStatus::cases()),
|
|
'ordered_at' => $this->faker->dateTimeBetween('-1 year', 'now'),
|
|
];
|
|
}
|
|
|
|
public function draft(): Factory
|
|
{
|
|
return $this->state(fn () => ['status' => OrderStatus::DRAFT]);
|
|
}
|
|
|
|
public function pending(): Factory
|
|
{
|
|
return $this->state(fn () => ['status' => OrderStatus::PENDING]);
|
|
}
|
|
|
|
public function partial(): Factory
|
|
{
|
|
return $this->state(fn () => ['status' => OrderStatus::PARTIAL]);
|
|
}
|
|
|
|
public function paid(): Factory
|
|
{
|
|
return $this->state(fn () => ['status' => OrderStatus::PAID]);
|
|
}
|
|
|
|
public function overdue(): Factory
|
|
{
|
|
return $this->state(fn () => ['status' => OrderStatus::OVERDUE]);
|
|
}
|
|
|
|
public function canceled(): Factory
|
|
{
|
|
return $this->state(fn () => ['status' => OrderStatus::CANCELED]);
|
|
}
|
|
|
|
public function outlet(): Factory
|
|
{
|
|
return $this->state(fn () => ['channel' => OrderChannel::OUTLET]);
|
|
}
|
|
|
|
public function shopee(): Factory
|
|
{
|
|
return $this->state(fn () => ['channel' => OrderChannel::SHOPEE]);
|
|
}
|
|
|
|
public function tokopedia(): Factory
|
|
{
|
|
return $this->state(fn () => ['channel' => OrderChannel::TOKOPEDIA]);
|
|
}
|
|
|
|
public function website(): Factory
|
|
{
|
|
return $this->state(fn () => ['channel' => OrderChannel::WEBSITE]);
|
|
}
|
|
|
|
public function instagram(): Factory
|
|
{
|
|
return $this->state(fn () => ['channel' => OrderChannel::INSTAGRAM]);
|
|
}
|
|
|
|
public function whatsapp(): Factory
|
|
{
|
|
return $this->state(fn () => ['channel' => OrderChannel::WHATSAPP]);
|
|
}
|
|
|
|
public function other(): Factory
|
|
{
|
|
return $this->state(fn () => ['channel' => OrderChannel::OTHER]);
|
|
}
|
|
|
|
public function withCustomer(?Customer $customer = null): Factory
|
|
{
|
|
return $this->state(fn () => ['customer_id' => $customer?->id ?? Customer::factory()]);
|
|
}
|
|
|
|
public function withVoucher(?Voucher $voucher = null): Factory
|
|
{
|
|
return $this->state(fn () => ['voucher_id' => $voucher?->id ?? Voucher::factory()]);
|
|
}
|
|
|
|
public function withOutlet(?Outlet $outlet = null): Factory
|
|
{
|
|
return $this->state(fn () => ['outlet_id' => $outlet?->id ?? Outlet::factory()]);
|
|
}
|
|
|
|
public function withUser(?User $user = null): Factory
|
|
{
|
|
return $this->state(fn () => ['user_id' => $user?->id ?? User::factory()]);
|
|
}
|
|
|
|
public function withAmounts(int $subtotal, ?int $discount = null, ?int $cogs = null): Factory
|
|
{
|
|
return $this->state(function (array $attributes) use ($subtotal, $discount, $cogs) {
|
|
$discount = $discount ?? $this->faker->numberBetween(0, (int) ($subtotal * 0.3));
|
|
$total = $subtotal - $discount;
|
|
$cogs = $cogs ?? (int) ($subtotal * 0.4);
|
|
|
|
return [
|
|
'subtotal' => $subtotal,
|
|
'discount' => $discount,
|
|
'total' => $total,
|
|
'cogs' => $cogs,
|
|
];
|
|
});
|
|
}
|
|
|
|
public function withDiscount(int $discount): Factory
|
|
{
|
|
return $this->state(function (array $attributes) use ($discount) {
|
|
$subtotal = $attributes['subtotal'] ?? $this->faker->numberBetween(50000, 1000000);
|
|
$total = $subtotal - $discount;
|
|
|
|
return [
|
|
'discount' => $discount,
|
|
'total' => max(0, $total),
|
|
];
|
|
});
|
|
}
|
|
|
|
public function withoutDiscount(): Factory
|
|
{
|
|
return $this->state(function (array $attributes) {
|
|
$subtotal = $attributes['subtotal'] ?? $this->faker->numberBetween(50000, 1000000);
|
|
|
|
return [
|
|
'discount' => 0,
|
|
'total' => $subtotal,
|
|
];
|
|
});
|
|
}
|
|
|
|
public function today(): Factory
|
|
{
|
|
return $this->state(fn () => ['ordered_at' => now(), 'created_at' => now()]);
|
|
}
|
|
|
|
public function yesterday(): Factory
|
|
{
|
|
return $this->state(fn () => tap(now()->subDay(), fn ($d) => null) && ['ordered_at' => $d = now()->subDay(), 'created_at' => $d]);
|
|
}
|
|
|
|
public function thisWeek(): Factory
|
|
{
|
|
return $this->state(fn () => ['ordered_at' => $this->faker->dateTimeBetween('-7 days', 'now')]);
|
|
}
|
|
|
|
public function thisMonth(): Factory
|
|
{
|
|
return $this->state(fn () => ['ordered_at' => $this->faker->dateTimeBetween('-30 days', 'now')]);
|
|
}
|
|
|
|
public function lastMonth(): Factory
|
|
{
|
|
return $this->state(fn () => ['ordered_at' => $this->faker->dateTimeBetween('-60 days', '-30 days')]);
|
|
}
|
|
}
|