feat: Add Redemption and Reward factories, refactor existing factories to use explicit with methods, and update UserSeeder.

This commit is contained in:
Yoga Pangestu 2026-01-02 13:50:19 +07:00
parent c5672366eb
commit f657a5273f
35 changed files with 438 additions and 224 deletions

View File

@ -35,28 +35,28 @@ public function getSlugOptions(): SlugOptions
->saveSlugsTo('slug');
}
public function items(): MorphMany
{
return $this->morphMany(OrderItem::class, 'orderable');
}
public function outlets(): BelongsToMany
{
return $this->belongsToMany(Outlet::class)->withPivot('stock');
}
public function warehouses(): BelongsToMany
{
return $this->belongsToMany(Warehouse::class)->withPivot('stock');
}
public function purchaseItems(): MorphMany
{
return $this->morphMany(PurchaseItem::class, 'purchasable');
}
public function items(): MorphMany
{
return $this->morphMany(OrderItem::class, 'orderable');
}
public function restockItems(): MorphMany
{
return $this->morphMany(RestockItem::class, 'restockable');
}
public function warehouses(): BelongsToMany
{
return $this->belongsToMany(Warehouse::class)->withPivot('stock');
}
}

View File

@ -48,13 +48,13 @@ public function getSlugOptions(): SlugOptions
->saveSlugsTo('slug');
}
public function perfumes(): BelongsToMany
{
return $this->belongsToMany(Perfume::class);
}
public function articles(): BelongsToMany
{
return $this->belongsToMany(Article::class);
}
public function perfumes(): BelongsToMany
{
return $this->belongsToMany(Perfume::class);
}
}

View File

@ -37,13 +37,13 @@ public function yesterday(Builder $query): void
$query->whereDate('created_at', today()->subDay());
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
public function orders(): HasMany
{
return $this->hasMany(Order::class);
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
}

View File

@ -23,16 +23,6 @@ protected function casts(): array
];
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
public function tier(): BelongsTo
{
return $this->belongsTo(Tier::class);
}
#[Scope]
protected function scopeForSpending(Builder $query, $totalSpending): void
{
@ -43,4 +33,14 @@ protected function scopeForSpending(Builder $query, $totalSpending): void
->orWhere('max_spending', '>=', $totalSpending);
});
}
public function tier(): BelongsTo
{
return $this->belongsTo(Tier::class);
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
}

View File

@ -52,33 +52,33 @@ public function yesterday(Builder $query): void
$query->whereDate('created_at', today()->subDay());
}
public function outlet(): BelongsTo
{
return $this->belongsTo(Outlet::class);
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
public function customer(): BelongsTo
{
return $this->belongsTo(Customer::class);
}
public function voucher(): BelongsTo
{
return $this->belongsTo(Voucher::class);
}
public function items(): HasMany
{
return $this->hasMany(OrderItem::class);
}
public function outlet(): BelongsTo
{
return $this->belongsTo(Outlet::class);
}
public function payments(): HasMany
{
return $this->hasMany(Payment::class);
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
public function voucher(): BelongsTo
{
return $this->belongsTo(Voucher::class);
}
}

View File

@ -41,16 +41,16 @@ public function order(): BelongsTo
return $this->belongsTo(Order::class);
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
public function orderable(): MorphTo
{
return $this->morphTo()->withTrashed();
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
public function volumes(): HasMany
{
return $this->hasMany(VolumeItem::class);

View File

@ -45,9 +45,14 @@ public function operational(Builder $query): void
$query->where('status', OutletStatus::OPERATIONAL->value);
}
public function openingHours(): HasMany
public function bottles(): BelongsToMany
{
return $this->hasMany(OpeningHour::class);
return $this->belongsToMany(Bottle::class)->withPivot('stock');
}
public function expenses(): HasMany
{
return $this->hasMany(Expense::class);
}
public function facilities(): HasMany
@ -55,9 +60,14 @@ public function facilities(): HasMany
return $this->hasMany(Facility::class);
}
public function vouchers(): BelongsToMany
public function openingHours(): HasMany
{
return $this->belongsToMany(Voucher::class);
return $this->hasMany(OpeningHour::class);
}
public function orders(): HasMany
{
return $this->hasMany(Order::class);
}
public function perfumes(): BelongsToMany
@ -70,29 +80,14 @@ public function products(): BelongsToMany
return $this->belongsToMany(Product::class)->withPivot('stock');
}
public function bottles(): BelongsToMany
{
return $this->belongsToMany(Bottle::class)->withPivot('stock');
}
public function expenses(): HasMany
{
return $this->hasMany(Expense::class);
}
public function users(): BelongsToMany
{
return $this->belongsToMany(User::class);
}
public function purchases(): HasMany
{
return $this->hasMany(Purchase::class);
}
public function orders(): HasMany
public function restocks(): HasMany
{
return $this->hasMany(Order::class);
return $this->hasMany(Restock::class);
}
public function stockOpname(): HasMany
@ -100,8 +95,13 @@ public function stockOpname(): HasMany
return $this->hasMany(StockOpname::class);
}
public function restocks(): HasMany
public function users(): BelongsToMany
{
return $this->hasMany(Restock::class);
return $this->belongsToMany(User::class);
}
public function vouchers(): BelongsToMany
{
return $this->belongsToMany(Voucher::class);
}
}

View File

@ -54,13 +54,13 @@ public function forCurrentUser(Builder $query): void
}
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
public function adjustments(): HasMany
{
return $this->hasMany(PayrollAdjustment::class);
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
}

View File

@ -48,28 +48,28 @@ public function categories(): BelongsToMany
return $this->belongsToMany(Category::class);
}
public function items(): MorphMany
{
return $this->morphMany(OrderItem::class, 'orderable');
}
public function outlets(): BelongsToMany
{
return $this->belongsToMany(Outlet::class)->withPivot('stock');
}
public function warehouses(): BelongsToMany
{
return $this->belongsToMany(Warehouse::class)->withPivot('stock');
}
public function purchaseItems(): MorphMany
{
return $this->morphMany(PurchaseItem::class, 'purchasable');
}
public function items(): MorphMany
{
return $this->morphMany(OrderItem::class, 'orderable');
}
public function restockItems(): MorphMany
{
return $this->morphMany(RestockItem::class, 'restockable');
}
public function warehouses(): BelongsToMany
{
return $this->belongsToMany(Warehouse::class)->withPivot('stock');
}
}

View File

@ -35,28 +35,28 @@ public function getSlugOptions(): SlugOptions
->saveSlugsTo('slug');
}
public function items(): MorphMany
{
return $this->morphMany(OrderItem::class, 'orderable');
}
public function outlets(): BelongsToMany
{
return $this->belongsToMany(Outlet::class)->withPivot('stock');
}
public function warehouses(): BelongsToMany
{
return $this->belongsToMany(Warehouse::class)->withPivot('stock');
}
public function purchaseItems(): MorphMany
{
return $this->morphMany(PurchaseItem::class, 'purchasable');
}
public function items(): MorphMany
{
return $this->morphMany(OrderItem::class, 'orderable');
}
public function restockItems(): MorphMany
{
return $this->morphMany(RestockItem::class, 'restockable');
}
public function warehouses(): BelongsToMany
{
return $this->belongsToMany(Warehouse::class)->withPivot('stock');
}
}

View File

@ -39,21 +39,6 @@ public static function isOverlap(int $minSpending, ?int $maxSpending, ?int $igno
});
}
public function memberships(): HasMany
{
return $this->hasMany(Membership::class);
}
public function vouchers(): BelongsToMany
{
return $this->belongsToMany(Voucher::class);
}
public function rewards(): BelongsToMany
{
return $this->belongsToMany(Reward::class);
}
public static function getHighestTier()
{
return self::orderByDesc('min_spending')->first();
@ -142,4 +127,19 @@ public static function canDeleteTier(int $tierId): array
'message' => 'Tidak dapat menghapus tier tengah karena akan mengacaukan sistem belanja. Tier harus membentuk rantai yang kontinyu.',
];
}
public function memberships(): HasMany
{
return $this->hasMany(Membership::class);
}
public function rewards(): BelongsToMany
{
return $this->belongsToMany(Reward::class);
}
public function vouchers(): BelongsToMany
{
return $this->belongsToMany(Voucher::class);
}
}

View File

@ -57,44 +57,6 @@ protected function withoutDeveloper(Builder $query): void
});
}
// HasOne relationships (alphabetical)
public function customer(): HasOne
{
return $this->hasOne(Customer::class);
}
public function employee(): HasOne
{
return $this->hasOne(Employee::class);
}
public function membership(): HasOne
{
return $this->hasOne(Membership::class);
}
public function referralCode(): HasOne
{
return $this->hasOne(ReferralCode::class);
}
public function referralUsage(): HasOne
{
return $this->hasOne(ReferralUsage::class);
}
// BelongsToMany relationships (alphabetical)
public function outlets(): BelongsToMany
{
return $this->belongsToMany(Outlet::class);
}
public function vouchers(): BelongsToMany
{
return $this->belongsToMany(Voucher::class);
}
// HasMany relationships (alphabetical)
public function articles(): HasMany
{
return $this->hasMany(Article::class, 'author_id');
@ -105,6 +67,16 @@ public function broadcasts(): HasMany
return $this->hasMany(Broadcast::class);
}
public function customer(): HasOne
{
return $this->hasOne(Customer::class);
}
public function employee(): HasOne
{
return $this->hasOne(Employee::class);
}
public function expenses(): HasMany
{
return $this->hasMany(Expense::class);
@ -115,11 +87,21 @@ public function items(): HasMany
return $this->hasMany(OrderItem::class);
}
public function membership(): HasOne
{
return $this->hasOne(Membership::class);
}
public function orders(): HasMany
{
return $this->hasMany(Order::class);
}
public function outlets(): BelongsToMany
{
return $this->belongsToMany(Outlet::class);
}
public function payments(): HasMany
{
return $this->hasMany(Payment::class);
@ -150,6 +132,16 @@ public function redemptions(): HasMany
return $this->hasMany(Redemption::class);
}
public function referralCode(): HasOne
{
return $this->hasOne(ReferralCode::class);
}
public function referralUsage(): HasOne
{
return $this->hasOne(ReferralUsage::class);
}
public function salaryHistories(): HasMany
{
return $this->hasMany(SalaryHistory::class);
@ -164,4 +156,9 @@ public function verifiedRedemptions(): HasMany
{
return $this->hasMany(Redemption::class, 'verified_by');
}
public function vouchers(): BelongsToMany
{
return $this->belongsToMany(Voucher::class);
}
}

View File

@ -18,6 +18,11 @@ class Warehouse extends Model
protected $cascadeDeletes = ['perfumes', 'products', 'bottles', 'purchases', 'restocks'];
public function bottles(): BelongsToMany
{
return $this->belongsToMany(Bottle::class)->withPivot('stock');
}
public function perfumes(): BelongsToMany
{
return $this->belongsToMany(Perfume::class)->withPivot('stock');
@ -28,11 +33,6 @@ public function products(): BelongsToMany
return $this->belongsToMany(Product::class)->withPivot('stock');
}
public function bottles(): BelongsToMany
{
return $this->belongsToMany(Bottle::class)->withPivot('stock');
}
public function purchases(): HasMany
{
return $this->hasMany(Purchase::class);

View File

@ -11,15 +11,17 @@ class BottleFactory extends Factory
public function definition(): array
{
$costPrice = $this->faker->randomNumber(2);
return [
'name' => $this->faker->word(),
'slug' => $this->faker->slug(),
'size' => $this->faker->randomNumber(2),
'cost_price' => $this->faker->randomNumber(2),
'sale_price' => $this->faker->randomNumber(2),
'description' => $this->faker->sentence(),
];
}
public function withDescription(): Factory
{
return $this->state(fn () => ['description' => $this->faker->sentence()]);
}
}

View File

@ -14,7 +14,6 @@ public function definition(): array
return [
'name' => $this->faker->unique()->company(),
'slug' => $this->faker->slug(),
'description' => $this->faker->optional()->text(),
'sort_order' => function () {
$max = Category::max('sort_order') ?? 0;
@ -22,4 +21,9 @@ public function definition(): array
},
];
}
public function withDescription(): Factory
{
return $this->state(fn () => ['description' => $this->faker->text()]);
}
}

View File

@ -23,6 +23,11 @@ public function definition(): array
];
}
public function withAddress(): Factory
{
return $this->state(fn () => ['address' => $this->faker->address()]);
}
public function male(): Factory
{
return $this->state(fn () => ['gender' => Gender::MALE]);

View File

@ -24,15 +24,23 @@ public function definition(): array
$this->faker->numerify('0812 #### #####'),
]),
'base_salary' => $this->faker->randomNumber(6),
'address' => $this->faker->address(),
'birthdate' => $this->faker->dateTimeBetween('-60 years', '-18 years')->format('Y-m-d'),
'hire_date' => $this->faker->date(),
'resign_date' => $this->faker->optional()->date(),
'gender' => $this->faker->randomElement(Gender::cases()),
'status' => $this->faker->randomElement(EmploymentStatus::cases()),
];
}
public function withAddress(): Factory
{
return $this->state(fn () => ['address' => $this->faker->address()]);
}
public function resigned(): Factory
{
return $this->state(fn () => ['resign_date' => $this->faker->date()]);
}
public function male(): Factory
{
return $this->state(fn () => ['gender' => Gender::MALE]);

View File

@ -5,6 +5,7 @@
use App\Models\Membership;
use App\Models\Tier;
use App\Models\User;
use DateTime;
use Illuminate\Database\Eloquent\Factories\Factory;
class MembershipFactory extends Factory
@ -18,7 +19,11 @@ public function definition(): array
'tier_id' => Tier::factory(),
'total_spending' => $this->faker->numberBetween(0, 5000000),
'reward_points' => $this->faker->numberBetween(0, 1000),
'last_transaction_at' => $this->faker->optional()->dateTimeBetween('-30 days', 'now'),
];
}
public function withLastTransaction(?DateTime $date = null): Factory
{
return $this->state(fn () => ['last_transaction_at' => $date ?? now()]);
}
}

View File

@ -2,8 +2,11 @@
namespace Database\Factories;
use App\Models\Bottle;
use App\Models\Order;
use App\Models\OrderItem;
use App\Models\Perfume;
use App\Models\Product;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
@ -17,13 +20,45 @@ public function definition(): array
$quantity = $this->faker->numberBetween(1, 5);
return [
'order_id' => Order::factory(),
'user_id' => User::factory(),
'orderable_type' => null,
'orderable_id' => null,
'cogs' => (int) ($unitPrice * 0.4),
'unit_price' => $unitPrice,
'quantity' => $quantity,
];
}
public function forOrder(?Order $order = null): Factory
{
return $this->state(fn () => ['order_id' => $order?->id ?? Order::factory()]);
}
public function forProduct(?Product $product = null): Factory
{
$product = $product ?? Product::factory()->create();
return $this->state(fn () => [
'orderable_type' => $product->getMorphClass(),
'orderable_id' => $product->id,
]);
}
public function forPerfume(?Perfume $perfume = null): Factory
{
$perfume = $perfume ?? Perfume::factory()->create();
return $this->state(fn () => [
'orderable_type' => $perfume->getMorphClass(),
'orderable_id' => $perfume->id,
]);
}
public function forBottle(?Bottle $bottle = null): Factory
{
$bottle = $bottle ?? Bottle::factory()->create();
return $this->state(fn () => [
'orderable_type' => $bottle->getMorphClass(),
'orderable_id' => $bottle->id,
]);
}
}

View File

@ -21,13 +21,26 @@ public function definition(): array
$this->faker->numerify('0812 #### #####'),
]),
'address' => $this->faker->address(),
'landmark' => $this->faker->streetName(),
'maps_url' => 'https://goo.gl/maps/'.$this->faker->regexify('[A-Za-z0-9]{6,10}'),
'opened_date' => $this->faker->date(),
'status' => $this->faker->randomElement(OutletStatus::cases()),
];
}
public function withLandmark(): Factory
{
return $this->state(fn () => ['landmark' => $this->faker->streetName()]);
}
public function withMapsUrl(): Factory
{
return $this->state(fn () => ['maps_url' => 'https://goo.gl/maps/'.$this->faker->regexify('[A-Za-z0-9]{6,10}')]);
}
public function closed(): Factory
{
return $this->state(fn () => ['closed_date' => $this->faker->date()]);
}
public function operational(): Factory
{
return $this->state(fn () => ['status' => OutletStatus::OPERATIONAL]);

View File

@ -7,6 +7,7 @@
use App\Models\Order;
use App\Models\Payment;
use App\Models\User;
use DateTime;
use Illuminate\Database\Eloquent\Factories\Factory;
class PaymentFactory extends Factory
@ -20,11 +21,19 @@ public function definition(): array
'user_id' => User::factory(),
'method' => $this->faker->randomElement(PaymentMethod::cases()),
'amount' => $this->faker->numberBetween(20000, 400000),
'paid_at' => $this->faker->dateTimeBetween('-7 days', 'now'),
'status' => $this->faker->randomElement(PaymentStatus::cases()),
];
}
public function withPaidAt(?DateTime $paidAt = null): Factory
{
return $this->state(fn () => ['paid_at' => $paidAt ?? now()]);
}
public function withStatus(PaymentStatus $status): Factory
{
return $this->state(fn () => ['status' => $status]);
}
public function cash(): Factory
{
return $this->state(fn () => ['method' => PaymentMethod::CASH]);

View File

@ -5,6 +5,7 @@
use App\Enums\IsPaid;
use App\Models\Payroll;
use App\Models\User;
use DateTime;
use Illuminate\Database\Eloquent\Factories\Factory;
class PayrollFactory extends Factory
@ -17,8 +18,6 @@ public function definition(): array
$bonus = $this->faker->numberBetween(0, 2000000);
$deduction = $this->faker->numberBetween(0, 500000);
$isPaid = $this->faker->randomElement(IsPaid::cases());
return [
'user_id' => User::factory(),
'period_month' => $this->faker->date('Y-m'),
@ -26,13 +25,23 @@ public function definition(): array
'bonus' => $bonus,
'deduction' => $deduction,
'total_salary' => $base + $bonus - $deduction,
'is_paid' => $isPaid,
'paid_at' => $isPaid === IsPaid::PAID
? $this->faker->dateTimeBetween('-3 days', 'now')
: null,
'is_paid' => IsPaid::NOT_PAID,
];
}
public function withPaidAt(?DateTime $paidAt = null): Factory
{
return $this->state(fn () => [
'is_paid' => IsPaid::PAID,
'paid_at' => $paidAt ?? now(),
]);
}
public function withPeriodMonth(string $periodMonth): Factory
{
return $this->state(fn () => ['period_month' => $periodMonth]);
}
public function paid(): Factory
{
return $this->state(fn () => [

View File

@ -24,13 +24,28 @@ public function definition(): array
'concentration' => $this->faker->randomElement(Concentration::cases()),
'cost_price' => $this->faker->numberBetween(50000, 250000),
'sale_price' => $this->faker->numberBetween(80000, 400000),
'base_notes' => $this->faker->optional()->words(3, true),
'middle_notes' => $this->faker->optional()->words(3, true),
'top_notes' => $this->faker->optional()->words(3, true),
'description' => $this->faker->optional()->paragraph(),
];
}
public function withNotes(): Factory
{
return $this->state(fn () => [
'base_notes' => $this->faker->words(3, true),
'middle_notes' => $this->faker->words(3, true),
'top_notes' => $this->faker->words(3, true),
]);
}
public function withDescription(): Factory
{
return $this->state(fn () => ['description' => $this->faker->paragraph()]);
}
public function withoutBrand(): Factory
{
return $this->state(fn () => ['brand_id' => null]);
}
public function extrait(): Factory
{
return $this->state(fn () => ['concentration' => Concentration::EXTRAIT_DE_PERFUME]);

View File

@ -20,7 +20,11 @@ public function definition(): array
'sku' => strtoupper($this->faker->unique()->bothify('PRD-#####')),
'cost_price' => $this->faker->numberBetween(20000, 150000),
'sale_price' => $this->faker->numberBetween(30000, 200000),
'description' => $this->faker->optional()->paragraph(),
];
}
public function withDescription(): Factory
{
return $this->state(fn () => ['description' => $this->faker->paragraph()]);
}
}

View File

@ -0,0 +1,43 @@
<?php
namespace Database\Factories;
use App\Enums\RedemptionStatus;
use App\Models\Redemption;
use App\Models\Reward;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
class RedemptionFactory extends Factory
{
protected $model = Redemption::class;
public function definition(): array
{
return [
'user_id' => User::factory(),
'reward_id' => Reward::factory(),
'code' => Str::upper(Str::random(10)),
'points_spent' => 100,
'status' => RedemptionStatus::WAITING_PICKUP,
'expires_at' => $this->faker->dateTimeBetween('+1 week', '+1 month'),
];
}
public function verified(User $verifier): Factory
{
return $this->state(fn () => [
'status' => RedemptionStatus::PICKED_UP,
'verified_at' => now(),
'verified_by' => $verifier->id,
]);
}
public function expired(): Factory
{
return $this->state(fn () => [
'status' => RedemptionStatus::EXPIRED,
]);
}
}

View File

@ -7,18 +7,10 @@
use App\Models\Warehouse;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Restock>
*/
class RestockFactory extends Factory
{
protected $model = Restock::class;
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [

View File

@ -10,18 +10,10 @@
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\RestockItem>
*/
class RestockItemFactory extends Factory
{
protected $model = RestockItem::class;
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
$restockableType = fake()->randomElement([Perfume::class, Product::class, Bottle::class]);

View File

@ -0,0 +1,44 @@
<?php
namespace Database\Factories;
use App\Enums\IsShow;
use App\Enums\RewardCategory;
use App\Models\Reward;
use Illuminate\Database\Eloquent\Factories\Factory;
class RewardFactory extends Factory
{
protected $model = Reward::class;
public function definition(): array
{
return [
'name' => $this->faker->words(2, true),
'points' => $this->faker->numberBetween(10, 500),
'category' => RewardCategory::REGULAR,
'is_show' => IsShow::SHOW,
'start_date' => $this->faker->dateTimeBetween('now', '+1 week')->format('Y-m-d'),
];
}
public function withStock(int $stock): Factory
{
return $this->state(fn () => ['stock' => $stock]);
}
public function withEndDate(string $date): Factory
{
return $this->state(fn () => ['end_date' => $date]);
}
public function show(): Factory
{
return $this->state(fn () => ['is_show' => IsShow::SHOW]);
}
public function hidden(): Factory
{
return $this->state(fn () => ['is_show' => IsShow::HIDDEN]);
}
}

View File

@ -14,7 +14,11 @@ public function definition(): array
return [
'name' => $this->faker->name(),
'min_spending' => $this->faker->randomNumber(),
'max_spending' => $this->faker->optional()->randomNumber(),
];
}
public function withMaxSpending(int $amount): Factory
{
return $this->state(fn () => ['max_spending' => $amount]);
}
}

View File

@ -30,4 +30,9 @@ public function inactive(): Factory
{
return $this->state(fn () => ['status' => UserStatus::INACTIVE]);
}
public function verified(): Factory
{
return $this->state(fn () => ['email_verified_at' => now()]);
}
}

View File

@ -21,20 +21,39 @@ public function definition(): array
'code' => Str::upper(Str::random(8)),
'tags' => $this->faker->words(1, true),
'type' => $type,
'discount_amount' => $type === VoucherType::PERCENTAGE->value
'discount_amount' => $type === VoucherType::PERCENTAGE
? $this->faker->numberBetween(5, 50)
: $this->faker->numberBetween(10000, 100000),
'min_purchase' => $this->faker->optional()->numberBetween(50000, 200000),
'max_discount' => $type === VoucherType::PERCENTAGE->value ? $this->faker->numberBetween(10000, 50000) : null,
'quota' => $this->faker->optional()->numberBetween(50, 500),
'limit_per_user' => $this->faker->optional()->numberBetween(1, 5),
'limit_per_user' => 1,
'summary' => $this->faker->sentence(),
'start_date' => $this->faker->dateTimeBetween('tomorrow', '+1 week')->format('Y-m-d'),
'end_date' => $this->faker->optional()->dateTimeBetween('+1 day', '+2 months')?->format('Y-m-d'),
'is_show' => $this->faker->randomElement(IsShow::values()),
'is_show' => IsShow::SHOW,
];
}
public function withMinPurchase(int $amount): Factory
{
return $this->state(fn () => ['min_purchase' => $amount]);
}
public function withMaxDiscount(int $amount): Factory
{
return $this->state(fn () => ['max_discount' => $amount]);
}
public function withQuota(int $quota): Factory
{
return $this->state(fn () => [
'quota' => $quota,
'available_count' => $quota,
]);
}
public function withEndDate(string $date): Factory
{
return $this->state(fn () => ['end_date' => $date]);
}
public function show(): Factory
{
return $this->state(fn () => ['is_show' => IsShow::SHOW]);

View File

@ -5,23 +5,19 @@
use App\Models\Warehouse;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Warehouse>
*/
class WarehouseFactory extends Factory
{
protected $model = Warehouse::class;
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'name' => fake()->company().' Warehouse',
'description' => fake()->optional()->sentence(),
];
}
public function withDescription(): Factory
{
return $this->state(fn () => ['description' => fake()->sentence()]);
}
}

View File

@ -2,6 +2,7 @@
namespace Database\Seeders;
use App\Enums\CategoryType;
use App\Models\Category;
use Illuminate\Database\Seeder;
use Illuminate\Support\Str;
@ -11,16 +12,20 @@ class CategorySeeder extends Seeder
public function run(): void
{
$categories = [
['name' => 'Floral', 'description' => 'Perfume with floral scents', 'sort_order' => 1],
['name' => 'Citrus', 'description' => 'Fresh citrus fragrances', 'sort_order' => 2],
['name' => 'Woody', 'description' => 'Warm woody notes', 'sort_order' => 3],
['name' => 'Oriental', 'description' => 'Spicy and exotic oriental scents', 'sort_order' => 4],
['name' => 'Fruity', 'description' => 'Sweet and fresh fruity fragrances', 'sort_order' => 5],
['name' => 'Aquatic', 'description' => 'Light, oceanic, and fresh scents', 'sort_order' => 6],
['name' => 'Gourmand', 'description' => 'Edible, sweet and dessert-like scents', 'sort_order' => 7],
['name' => 'Green', 'description' => 'Fresh, leafy, and herbal notes', 'sort_order' => 8],
['name' => 'Chypre', 'description' => 'Classic blend of citrus, oakmoss, and labdanum', 'sort_order' => 9],
['name' => 'Musk', 'description' => 'Warm, sensual musky fragrances', 'sort_order' => 10],
['name' => 'Floral', 'description' => 'Perfume with floral scents', 'sort_order' => 1, 'type' => CategoryType::PERFUME],
['name' => 'Citrus', 'description' => 'Fresh citrus fragrances', 'sort_order' => 2, 'type' => CategoryType::PERFUME],
['name' => 'Woody', 'description' => 'Warm woody notes', 'sort_order' => 3, 'type' => CategoryType::PERFUME],
['name' => 'Oriental', 'description' => 'Spicy and exotic oriental scents', 'sort_order' => 4, 'type' => CategoryType::PERFUME],
['name' => 'Fruity', 'description' => 'Sweet and fresh fruity fragrances', 'sort_order' => 5, 'type' => CategoryType::PERFUME],
['name' => 'Aquatic', 'description' => 'Light, oceanic, and fresh scents', 'sort_order' => 6, 'type' => CategoryType::PERFUME],
['name' => 'Gourmand', 'description' => 'Edible, sweet and dessert-like scents', 'sort_order' => 7, 'type' => CategoryType::PERFUME],
['name' => 'Green', 'description' => 'Fresh, leafy, and herbal notes', 'sort_order' => 8, 'type' => CategoryType::PERFUME],
['name' => 'Chypre', 'description' => 'Classic blend of citrus, oakmoss, and labdanum', 'sort_order' => 9, 'type' => CategoryType::PERFUME],
['name' => 'Musk', 'description' => 'Warm, sensual musky fragrances', 'sort_order' => 10, 'type' => CategoryType::PERFUME],
['name' => 'Tips n Tricks', 'description' => 'Tips and tricks for using perfumes', 'sort_order' => 11, 'type' => CategoryType::ARTICLE],
['name' => 'Perfume Review', 'description' => 'Reviews of perfumes', 'sort_order' => 12, 'type' => CategoryType::ARTICLE],
['name' => 'Perfume Set', 'description' => 'Perfume sets', 'sort_order' => 13, 'type' => CategoryType::ARTICLE],
['name' => 'How To', 'description' => 'How to use perfumes', 'sort_order' => 14, 'type' => CategoryType::ARTICLE],
];
foreach ($categories as $category) {
@ -29,6 +34,7 @@ public function run(): void
'slug' => Str::slug($category['name']),
'description' => $category['description'],
'sort_order' => $category['sort_order'],
'type' => $category['type'],
]);
}
}

View File

@ -46,8 +46,10 @@ public function run(): void
foreach ($outlets as $data) {
$outlet = Outlet::create([
...$data,
'maps_url' => null,
'status' => OutletStatus::OPERATIONAL,
'opened_date' => now()->toDateString(),
'closed_date' => null,
]);
$hours = collect(Day::cases())->map(fn ($day) => [

View File

@ -5,6 +5,7 @@
use App\Enums\EmploymentStatus;
use App\Enums\Gender;
use App\Enums\UserRole;
use App\Enums\UserStatus;
use App\Models\Employee;
use App\Models\Outlet;
use App\Models\ReferralCode;
@ -23,6 +24,8 @@ public function run(): void
'email' => 'project.pangestuyoga@gmail.com',
'username' => 'pangestu',
'password' => Hash::make(config('myconfig.password_default')),
'status' => UserStatus::ACTIVE,
'email_verified_at' => now(),
]);
Employee::create([
@ -50,6 +53,8 @@ public function run(): void
'email' => 'mulyadi@gmail.com',
'username' => 'mulyadi',
'password' => Hash::make(config('myconfig.password_default')),
'status' => UserStatus::ACTIVE,
'email_verified_at' => now(),
]);
Employee::create([