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' => $this->faker->randomElement(OrderChannel::cases()), 'status' => $this->faker->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')]); } }