diff --git a/app/Enums/CashTransactionType.php b/app/Enums/CashTransactionType.php index be61fd6..9963f45 100644 --- a/app/Enums/CashTransactionType.php +++ b/app/Enums/CashTransactionType.php @@ -9,7 +9,17 @@ enum CashTransactionType: string use HasValues; case DEPOSIT = 'deposit'; - case WITHDRAWAL = 'withdrawal'; case EXPENSE = 'expense'; case TRANSFER = 'transfer'; + case WITHDRAWAL = 'withdrawal'; + + public function label(): string + { + return match ($this) { + self::DEPOSIT => 'Setoran', + self::EXPENSE => 'Pengeluaran', + self::TRANSFER => 'Transfer', + self::WITHDRAWAL => 'Penarikan', + }; + } } diff --git a/app/Enums/CuttingStatus.php b/app/Enums/CuttingStatus.php index d573596..851b395 100644 --- a/app/Enums/CuttingStatus.php +++ b/app/Enums/CuttingStatus.php @@ -8,7 +8,16 @@ enum CuttingStatus: string { use HasValues; - case IN_PROGRESS = 'in_progress'; - case COMPLETED = 'completed'; case CANCELLED = 'cancelled'; + case COMPLETED = 'completed'; + case IN_PROGRESS = 'in_progress'; + + public function label(): string + { + return match ($this) { + self::CANCELLED => 'Dibatalkan', + self::COMPLETED => 'Selesai', + self::IN_PROGRESS => 'Dalam Proses', + }; + } } diff --git a/app/Enums/EmployeeAdvanceStatus.php b/app/Enums/EmployeeAdvanceStatus.php index 66be07b..7dc5ccd 100644 --- a/app/Enums/EmployeeAdvanceStatus.php +++ b/app/Enums/EmployeeAdvanceStatus.php @@ -8,9 +8,20 @@ enum EmployeeAdvanceStatus: string { use HasValues; - case PENDING = 'pending'; case APPROVED = 'approved'; - case PAID = 'paid'; - case REJECTED = 'rejected'; case CANCELLED = 'cancelled'; + case PAID = 'paid'; + case PENDING = 'pending'; + case REJECTED = 'rejected'; + + public function label(): string + { + return match ($this) { + self::APPROVED => 'Disetujui', + self::CANCELLED => 'Dibatalkan', + self::PAID => 'Dibayar', + self::PENDING => 'Menunggu', + self::REJECTED => 'Ditolak', + }; + } } diff --git a/app/Enums/EmploymentStatus.php b/app/Enums/EmploymentStatus.php index 4f020b7..fcefcad 100644 --- a/app/Enums/EmploymentStatus.php +++ b/app/Enums/EmploymentStatus.php @@ -8,9 +8,20 @@ enum EmploymentStatus: string { use HasValues; - case FULL_TIME = 'full_time'; - case PART_TIME = 'part_time'; case CONTRACT = 'contract'; + case FULL_TIME = 'full_time'; case INTERNSHIP = 'internship'; + case PART_TIME = 'part_time'; case RESIGNED = 'resigned'; + + public function label(): string + { + return match ($this) { + self::CONTRACT => 'Kontrak', + self::FULL_TIME => 'Penuh Waktu', + self::INTERNSHIP => 'Magang', + self::PART_TIME => 'Paruh Waktu', + self::RESIGNED => 'Keluar', + }; + } } diff --git a/app/Enums/Gender.php b/app/Enums/Gender.php index 7dc1a92..caeb892 100644 --- a/app/Enums/Gender.php +++ b/app/Enums/Gender.php @@ -8,6 +8,14 @@ enum Gender: string { use HasValues; - case MALE = 'male'; case FEMALE = 'female'; + case MALE = 'male'; + + public function label(): string + { + return match ($this) { + self::FEMALE => 'Perempuan', + self::MALE => 'Laki-laki', + }; + } } diff --git a/app/Enums/LeaveRequestStatus.php b/app/Enums/LeaveRequestStatus.php index d15a697..a6eabb7 100644 --- a/app/Enums/LeaveRequestStatus.php +++ b/app/Enums/LeaveRequestStatus.php @@ -8,8 +8,18 @@ enum LeaveRequestStatus: string { use HasValues; - case PENDING = 'pending'; case APPROVED = 'approved'; - case REJECTED = 'rejected'; case CANCELLED = 'cancelled'; + case PENDING = 'pending'; + case REJECTED = 'rejected'; + + public function label(): string + { + return match ($this) { + self::APPROVED => 'Disetujui', + self::CANCELLED => 'Dibatalkan', + self::PENDING => 'Menunggu', + self::REJECTED => 'Ditolak', + }; + } } diff --git a/app/Enums/PayrollAdjustmentType.php b/app/Enums/PayrollAdjustmentType.php index fd0e617..b44af2f 100644 --- a/app/Enums/PayrollAdjustmentType.php +++ b/app/Enums/PayrollAdjustmentType.php @@ -10,4 +10,12 @@ enum PayrollAdjustmentType: string case BONUS = 'bonus'; case DEDUCTION = 'deduction'; + + public function label(): string + { + return match ($this) { + self::BONUS => 'Bonus', + self::DEDUCTION => 'Potongan', + }; + } } diff --git a/app/Enums/PayrollPeriodStatus.php b/app/Enums/PayrollPeriodStatus.php index 3fa561c..806962c 100644 --- a/app/Enums/PayrollPeriodStatus.php +++ b/app/Enums/PayrollPeriodStatus.php @@ -8,6 +8,14 @@ enum PayrollPeriodStatus: string { use HasValues; - case OPEN = 'open'; case CLOSED = 'closed'; + case OPEN = 'open'; + + public function label(): string + { + return match ($this) { + self::CLOSED => 'Tutup', + self::OPEN => 'Buka', + }; + } } diff --git a/app/Enums/PayrollStatus.php b/app/Enums/PayrollStatus.php index 41e431f..43ed285 100644 --- a/app/Enums/PayrollStatus.php +++ b/app/Enums/PayrollStatus.php @@ -8,7 +8,16 @@ enum PayrollStatus: string { use HasValues; - case UNPAID = 'unpaid'; - case PAID = 'paid'; case CANCELLED = 'cancelled'; + case PAID = 'paid'; + case UNPAID = 'unpaid'; + + public function label(): string + { + return match ($this) { + self::CANCELLED => 'Dibatalkan', + self::PAID => 'Dibayar', + self::UNPAID => 'Belum Dibayar', + }; + } } diff --git a/app/Enums/RawMaterialUnit.php b/app/Enums/RawMaterialUnit.php index effc0ba..38ee581 100644 --- a/app/Enums/RawMaterialUnit.php +++ b/app/Enums/RawMaterialUnit.php @@ -11,4 +11,13 @@ enum RawMaterialUnit: string case KG = 'kg'; case METER = 'meter'; case YARD = 'yard'; + + public function label(): string + { + return match ($this) { + self::KG => 'Kg', + self::METER => 'Meter', + self::YARD => 'Yard', + }; + } } diff --git a/app/Enums/StokOpnameStatus.php b/app/Enums/StokOpnameStatus.php index 3bbf5a9..1dc21fa 100644 --- a/app/Enums/StokOpnameStatus.php +++ b/app/Enums/StokOpnameStatus.php @@ -8,9 +8,20 @@ enum StokOpnameStatus: string { use HasValues; + case CANCELLED = 'cancelled'; + case COMPLETED = 'completed'; case DRAFT = 'draft'; case IN_PROGRESS = 'in_progress'; - case COMPLETED = 'completed'; case VERIFIED = 'verified'; - case CANCELLED = 'cancelled'; + + public function label(): string + { + return match ($this) { + self::CANCELLED => 'Dibatalkan', + self::COMPLETED => 'Selesai', + self::DRAFT => 'Draft', + self::IN_PROGRESS => 'Dalam Proses', + self::VERIFIED => 'Terverifikasi', + }; + } } diff --git a/app/Models/Attendance.php b/app/Models/Attendance.php index 7e7b254..e3fd4da 100644 --- a/app/Models/Attendance.php +++ b/app/Models/Attendance.php @@ -3,6 +3,7 @@ namespace App\Models; use Illuminate\Database\Eloquent\Attributes\Guarded; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -29,6 +30,13 @@ protected function casts(): array ]; } + protected function attendanceDate(): Attribute + { + return Attribute::make( + get: fn ($value) => $value?->translatedFormat('l, d F Y'), + ); + } + public function employee(): BelongsTo { return $this->belongsTo(Employee::class); diff --git a/app/Models/CashAccount.php b/app/Models/CashAccount.php index 69b9da6..7826f05 100644 --- a/app/Models/CashAccount.php +++ b/app/Models/CashAccount.php @@ -2,13 +2,16 @@ namespace App\Models; +use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; +#[Appends(['formatted_balance', 'formatted_name'])] #[Guarded(['id'])] class CashAccount extends Model { @@ -21,6 +24,20 @@ protected function casts(): array ]; } + protected function formattedBalance(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->balance, 0, ',', '.'), + ); + } + + protected function formattedName(): Attribute + { + return Attribute::make( + get: fn () => ucfirst($this->name), + ); + } + public function cashTransactions(): HasMany { return $this->hasMany(CashTransaction::class); diff --git a/app/Models/CashTransaction.php b/app/Models/CashTransaction.php index 7db5655..0e7b9c5 100644 --- a/app/Models/CashTransaction.php +++ b/app/Models/CashTransaction.php @@ -3,9 +3,11 @@ namespace App\Models; use App\Enums\CashTransactionType; +use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; use Illuminate\Database\Eloquent\Attributes\Scope; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -16,6 +18,7 @@ use Spatie\MediaLibrary\HasMedia; use Spatie\MediaLibrary\InteractsWithMedia; +#[Appends(['formatted_amount', 'type_label'])] #[Guarded(['id'])] class CashTransaction extends Model implements HasMedia { @@ -30,6 +33,20 @@ protected function casts(): array ]; } + protected function formattedAmount(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->amount, 0, ',', '.'), + ); + } + + protected function typeLabel(): Attribute + { + return Attribute::make( + get: fn () => $this->type->label(), + ); + } + #[Scope] protected function deposit(Builder $query): void { diff --git a/app/Models/Category.php b/app/Models/Category.php index 080a51e..527720f 100644 --- a/app/Models/Category.php +++ b/app/Models/Category.php @@ -2,19 +2,29 @@ namespace App\Models; +use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\SoftDeletes; use Spatie\Sluggable\Attributes\Sluggable; +#[Appends(['formatted_name'])] #[Guarded(['id'])] #[Sluggable(from: 'name', to: 'slug')] class Category extends Model { use HasFactory, SoftDeletes; + protected function formattedName(): Attribute + { + return Attribute::make( + get: fn () => ucfirst($this->name), + ); + } + public function products(): BelongsToMany { return $this->belongsToMany(Product::class, 'product_categories') diff --git a/app/Models/Customer.php b/app/Models/Customer.php index 225d998..d1c42ae 100644 --- a/app/Models/Customer.php +++ b/app/Models/Customer.php @@ -2,17 +2,37 @@ namespace App\Models; +use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; +#[Appends(['formatted_name', 'formatted_phone_number'])] #[Guarded(['id'])] class Customer extends Model { use HasFactory, SoftDeletes; + protected function formattedName(): Attribute + { + return Attribute::make( + get: fn () => ucfirst($this->name), + ); + } + + protected function formattedPhoneNumber(): Attribute + { + return Attribute::make( + get: fn () => $this->phone_number + ? substr($this->phone_number, 0, 4) . ' ' . substr($this->phone_number, 4, 4) . ' ' . substr($this->phone_number, 8) + : null, + set: fn (?string $value) => $value ? preg_replace('/\s/', '', $value) : null, + ); + } + public function orders(): HasMany { return $this->hasMany(Order::class); diff --git a/app/Models/Cutting.php b/app/Models/Cutting.php index eec63fa..7d46e30 100644 --- a/app/Models/Cutting.php +++ b/app/Models/Cutting.php @@ -3,9 +3,11 @@ namespace App\Models; use App\Enums\CuttingStatus; +use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; use Illuminate\Database\Eloquent\Attributes\Scope; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -14,6 +16,7 @@ use Spatie\MediaLibrary\HasMedia; use Spatie\MediaLibrary\InteractsWithMedia; +#[Appends(['formatted_cost_per_unit', 'formatted_other_cost', 'formatted_sewing_cost', 'status_label', 'formatted_total_material_cost'])] #[Guarded(['id'])] class Cutting extends Model implements HasMedia { @@ -30,6 +33,41 @@ protected function casts(): array ]; } + protected function formattedCostPerUnit(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->cost_per_unit, 0, ',', '.'), + ); + } + + protected function formattedOtherCost(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->other_cost, 0, ',', '.'), + ); + } + + protected function formattedSewingCost(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->sewing_cost, 0, ',', '.'), + ); + } + + protected function statusLabel(): Attribute + { + return Attribute::make( + get: fn () => $this->status->label(), + ); + } + + protected function formattedTotalMaterialCost(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->total_material_cost, 0, ',', '.'), + ); + } + #[Scope] protected function cancelled(Builder $query): void { diff --git a/app/Models/Employee.php b/app/Models/Employee.php index dba50a1..fc75bbc 100644 --- a/app/Models/Employee.php +++ b/app/Models/Employee.php @@ -3,15 +3,18 @@ namespace App\Models; use App\Enums\EmploymentStatus; +use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; use Illuminate\Database\Eloquent\Attributes\Scope; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; +#[Appends(['formatted_base_salary', 'employment_status_label', 'formatted_join_date', 'formatted_resign_date'])] #[Guarded(['id'])] class Employee extends Model { @@ -27,6 +30,34 @@ protected function casts(): array ]; } + protected function formattedBaseSalary(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->base_salary, 0, ',', '.'), + ); + } + + protected function employmentStatusLabel(): Attribute + { + return Attribute::make( + get: fn () => $this->employment_status->label(), + ); + } + + protected function formattedJoinDate(): Attribute + { + return Attribute::make( + get: fn () => $this->join_date?->translatedFormat('l, d F Y'), + ); + } + + protected function formattedResignDate(): Attribute + { + return Attribute::make( + get: fn () => $this->resign_date?->translatedFormat('l, d F Y'), + ); + } + #[Scope] protected function contract(Builder $query): void { diff --git a/app/Models/EmployeeAdvance.php b/app/Models/EmployeeAdvance.php index e6a5822..3125adf 100644 --- a/app/Models/EmployeeAdvance.php +++ b/app/Models/EmployeeAdvance.php @@ -3,14 +3,17 @@ namespace App\Models; use App\Enums\EmployeeAdvanceStatus; +use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; use Illuminate\Database\Eloquent\Attributes\Scope; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\SoftDeletes; +#[Appends(['formatted_amount', 'formatted_due_date', 'formatted_paid_amount', 'status_label'])] #[Guarded(['id'])] class EmployeeAdvance extends Model { @@ -28,6 +31,34 @@ protected function casts(): array ]; } + protected function formattedAmount(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->amount, 0, ',', '.'), + ); + } + + protected function formattedDueDate(): Attribute + { + return Attribute::make( + get: fn () => $this->due_date?->translatedFormat('l, d F Y'), + ); + } + + protected function formattedPaidAmount(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->paid_amount, 0, ',', '.'), + ); + } + + protected function statusLabel(): Attribute + { + return Attribute::make( + get: fn () => $this->status->label(), + ); + } + #[Scope] protected function approved(Builder $query): void { diff --git a/app/Models/Expense.php b/app/Models/Expense.php index 2f5ddd8..47dd5b7 100644 --- a/app/Models/Expense.php +++ b/app/Models/Expense.php @@ -2,7 +2,9 @@ namespace App\Models; +use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -10,6 +12,7 @@ use Spatie\MediaLibrary\HasMedia; use Spatie\MediaLibrary\InteractsWithMedia; +#[Appends(['formatted_amount', 'formatted_date'])] #[Guarded(['id'])] class Expense extends Model implements HasMedia { @@ -19,9 +22,24 @@ protected function casts(): array { return [ 'amount' => 'integer', + 'date' => 'date:Y-m-d', ]; } + protected function formattedAmount(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->amount, 0, ',', '.'), + ); + } + + protected function formattedDate(): Attribute + { + return Attribute::make( + get: fn () => $this->date?->translatedFormat('l, d F Y'), + ); + } + public function cashTransaction(): BelongsTo { return $this->belongsTo(CashTransaction::class); diff --git a/app/Models/LeaveRequest.php b/app/Models/LeaveRequest.php index 13a9ff0..ec735da 100644 --- a/app/Models/LeaveRequest.php +++ b/app/Models/LeaveRequest.php @@ -3,14 +3,17 @@ namespace App\Models; use App\Enums\LeaveRequestStatus; +use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; use Illuminate\Database\Eloquent\Attributes\Scope; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\SoftDeletes; +#[Appends(['formatted_end_date', 'formatted_start_date', 'status_label'])] #[Guarded(['id'])] class LeaveRequest extends Model { @@ -27,6 +30,27 @@ protected function casts(): array ]; } + protected function formattedEndDate(): Attribute + { + return Attribute::make( + get: fn () => $this->end_date?->translatedFormat('l, d F Y'), + ); + } + + protected function formattedStartDate(): Attribute + { + return Attribute::make( + get: fn () => $this->start_date?->translatedFormat('l, d F Y'), + ); + } + + protected function statusLabel(): Attribute + { + return Attribute::make( + get: fn () => $this->status->label(), + ); + } + #[Scope] protected function approved(Builder $query): void { diff --git a/app/Models/Order.php b/app/Models/Order.php index ac4bdde..ac1766f 100644 --- a/app/Models/Order.php +++ b/app/Models/Order.php @@ -6,9 +6,11 @@ use App\Enums\OrderStatus; use App\Enums\PaymentType; use App\Enums\PriceType; +use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; use Illuminate\Database\Eloquent\Attributes\Scope; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -17,6 +19,7 @@ use Spatie\MediaLibrary\HasMedia; use Spatie\MediaLibrary\InteractsWithMedia; +#[Appends(['channel_label', 'formatted_cogs', 'formatted_discount', 'formatted_nego_price', 'payment_type_label', 'status_label', 'formatted_subtotal', 'formatted_total_amount'])] #[Guarded(['id'])] class Order extends Model implements HasMedia { @@ -39,6 +42,62 @@ protected function casts(): array ]; } + protected function channelLabel(): Attribute + { + return Attribute::make( + get: fn () => $this->channel->label(), + ); + } + + protected function formattedCogs(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->cogs, 0, ',', '.'), + ); + } + + protected function formattedDiscount(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->discount, 0, ',', '.'), + ); + } + + protected function formattedNegoPrice(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->nego_price, 0, ',', '.'), + ); + } + + protected function paymentTypeLabel(): Attribute + { + return Attribute::make( + get: fn () => $this->payment_type->label(), + ); + } + + protected function statusLabel(): Attribute + { + return Attribute::make( + get: fn () => $this->status->label(), + ); + } + + protected function formattedSubtotal(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->subtotal, 0, ',', '.'), + ); + } + + protected function formattedTotalAmount(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->total_amount, 0, ',', '.'), + ); + } + #[Scope] protected function cancelled(Builder $query): void { diff --git a/app/Models/OrderItem.php b/app/Models/OrderItem.php index 12c3244..773bf5f 100644 --- a/app/Models/OrderItem.php +++ b/app/Models/OrderItem.php @@ -3,14 +3,17 @@ namespace App\Models; use App\Enums\ProductStockQuality; +use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; use Illuminate\Database\Eloquent\Attributes\Scope; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\SoftDeletes; +#[Appends(['stock_quality_label', 'formatted_subtotal', 'formatted_unit_price'])] #[Guarded(['id'])] class OrderItem extends Model { @@ -26,6 +29,27 @@ protected function casts(): array ]; } + protected function stockQualityLabel(): Attribute + { + return Attribute::make( + get: fn () => $this->stock_quality->label(), + ); + } + + protected function formattedSubtotal(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->subtotal, 0, ',', '.'), + ); + } + + protected function formattedUnitPrice(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->unit_price, 0, ',', '.'), + ); + } + #[Scope] protected function good(Builder $query): void { diff --git a/app/Models/Payroll.php b/app/Models/Payroll.php index dad12ca..03adde4 100644 --- a/app/Models/Payroll.php +++ b/app/Models/Payroll.php @@ -3,6 +3,7 @@ namespace App\Models; use App\Enums\PayrollStatus; +use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; use Illuminate\Database\Eloquent\Attributes\Scope; use Illuminate\Database\Eloquent\Builder; @@ -13,6 +14,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; +#[Appends(['formatted_base_salary', 'formatted_bonus_amount', 'formatted_deduction_amount', 'status_label', 'formatted_total_amount'])] #[Guarded(['id'])] class Payroll extends Model { @@ -30,10 +32,45 @@ protected function casts(): array ]; } + protected function formattedBaseSalary(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->base_salary, 0, ',', '.'), + ); + } + + protected function formattedBonusAmount(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->bonus_amount, 0, ',', '.'), + ); + } + + protected function formattedDeductionAmount(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->deduction_amount, 0, ',', '.'), + ); + } + protected function formattedAmount(): Attribute { return Attribute::make( - get: fn () => 'Rp '.number_format($this->total_amount, 0, ',', '.'), + get: fn () => 'Rp ' . number_format($this->attributes['total_amount'] ?? 0, 0, ',', '.'), + ); + } + + protected function statusLabel(): Attribute + { + return Attribute::make( + get: fn () => $this->status->label(), + ); + } + + protected function formattedTotalAmount(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->total_amount, 0, ',', '.'), ); } diff --git a/app/Models/PayrollAdjustment.php b/app/Models/PayrollAdjustment.php index 61749de..07d940a 100644 --- a/app/Models/PayrollAdjustment.php +++ b/app/Models/PayrollAdjustment.php @@ -3,14 +3,17 @@ namespace App\Models; use App\Enums\PayrollAdjustmentType; +use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; use Illuminate\Database\Eloquent\Attributes\Scope; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\SoftDeletes; +#[Appends(['formatted_amount', 'type_label'])] #[Guarded(['id'])] class PayrollAdjustment extends Model { @@ -24,6 +27,20 @@ protected function casts(): array ]; } + protected function formattedAmount(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->amount, 0, ',', '.'), + ); + } + + protected function typeLabel(): Attribute + { + return Attribute::make( + get: fn () => $this->type->label(), + ); + } + #[Scope] protected function bonus(Builder $query): void { diff --git a/app/Models/PayrollPeriod.php b/app/Models/PayrollPeriod.php index a55bc52..07ed945 100644 --- a/app/Models/PayrollPeriod.php +++ b/app/Models/PayrollPeriod.php @@ -3,15 +3,18 @@ namespace App\Models; use App\Enums\PayrollPeriodStatus; +use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; use Illuminate\Database\Eloquent\Attributes\Scope; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; +#[Appends(['status_label'])] #[Guarded(['id'])] class PayrollPeriod extends Model { @@ -27,6 +30,13 @@ protected function casts(): array ]; } + protected function statusLabel(): Attribute + { + return Attribute::make( + get: fn () => $this->status->label(), + ); + } + #[Scope] protected function closed(Builder $query): void { diff --git a/app/Models/Product.php b/app/Models/Product.php index cad4783..d6be07b 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -3,9 +3,11 @@ namespace App\Models; use App\Enums\ProductStatus; +use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; use Illuminate\Database\Eloquent\Attributes\Scope; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsToMany; @@ -13,6 +15,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; use Spatie\Sluggable\Attributes\Sluggable; +#[Appends(['formatted_name', 'status_label'])] #[Guarded(['id'])] #[Sluggable(from: 'name', to: 'slug')] class Product extends Model @@ -26,6 +29,20 @@ protected function casts(): array ]; } + protected function formattedName(): Attribute + { + return Attribute::make( + get: fn () => ucfirst($this->name), + ); + } + + protected function statusLabel(): Attribute + { + return Attribute::make( + get: fn () => $this->status->label(), + ); + } + #[Scope] protected function active(Builder $query): void { diff --git a/app/Models/ProductPrice.php b/app/Models/ProductPrice.php index 41e9ee0..bb457e0 100644 --- a/app/Models/ProductPrice.php +++ b/app/Models/ProductPrice.php @@ -12,8 +12,8 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; +#[Appends(['formatted_price', 'type_label'])] #[Guarded(['id'])] -#[Appends(['type_label'])] class ProductPrice extends Model { use HasFactory; @@ -26,6 +26,13 @@ protected function casts(): array ]; } + protected function formattedPrice(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->price, 0, ',', '.'), + ); + } + #[Scope] protected function retail(Builder $query): void { diff --git a/app/Models/ProductVariant.php b/app/Models/ProductVariant.php index 9abbefa..97f10b7 100644 --- a/app/Models/ProductVariant.php +++ b/app/Models/ProductVariant.php @@ -2,7 +2,9 @@ namespace App\Models; +use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -11,6 +13,7 @@ use Spatie\MediaLibrary\HasMedia; use Spatie\MediaLibrary\InteractsWithMedia; +#[Appends(['formatted_name'])] #[Guarded(['id'])] class ProductVariant extends Model implements HasMedia { @@ -25,6 +28,13 @@ protected function casts(): array ]; } + protected function formattedName(): Attribute + { + return Attribute::make( + get: fn () => ucfirst($this->name), + ); + } + public function orderItems(): HasMany { return $this->hasMany(OrderItem::class); diff --git a/app/Models/Purchase.php b/app/Models/Purchase.php index f69d25a..fd995d9 100644 --- a/app/Models/Purchase.php +++ b/app/Models/Purchase.php @@ -2,7 +2,9 @@ namespace App\Models; +use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -11,6 +13,7 @@ use Spatie\MediaLibrary\HasMedia; use Spatie\MediaLibrary\InteractsWithMedia; +#[Appends(['formatted_discount', 'formatted_shipping_cost', 'formatted_subtotal', 'formatted_total'])] #[Guarded(['id'])] class Purchase extends Model implements HasMedia { @@ -26,6 +29,34 @@ protected function casts(): array ]; } + protected function formattedDiscount(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->discount, 0, ',', '.'), + ); + } + + protected function formattedShippingCost(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->shipping_cost, 0, ',', '.'), + ); + } + + protected function formattedSubtotal(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->subtotal, 0, ',', '.'), + ); + } + + protected function formattedTotal(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->total, 0, ',', '.'), + ); + } + public function createdBy(): BelongsTo { return $this->belongsTo(User::class, 'created_by_id'); diff --git a/app/Models/PurchaseItem.php b/app/Models/PurchaseItem.php index 20d2276..264e45f 100644 --- a/app/Models/PurchaseItem.php +++ b/app/Models/PurchaseItem.php @@ -2,12 +2,15 @@ namespace App\Models; +use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\SoftDeletes; +#[Appends(['formatted_subtotal', 'formatted_unit_price'])] #[Guarded(['id'])] class PurchaseItem extends Model { @@ -22,6 +25,20 @@ protected function casts(): array ]; } + protected function formattedSubtotal(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->subtotal, 0, ',', '.'), + ); + } + + protected function formattedUnitPrice(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->unit_price, 0, ',', '.'), + ); + } + public function purchase(): BelongsTo { return $this->belongsTo(Purchase::class); diff --git a/app/Models/RawMaterial.php b/app/Models/RawMaterial.php index b1156e5..299d748 100644 --- a/app/Models/RawMaterial.php +++ b/app/Models/RawMaterial.php @@ -3,14 +3,17 @@ namespace App\Models; use App\Enums\RawMaterialUnit; +use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; use Illuminate\Database\Eloquent\Attributes\Scope; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; +#[Appends(['formatted_name', 'unit_label'])] #[Guarded(['id'])] class RawMaterial extends Model { @@ -24,6 +27,20 @@ protected function casts(): array ]; } + protected function formattedName(): Attribute + { + return Attribute::make( + get: fn () => ucfirst($this->name), + ); + } + + protected function unitLabel(): Attribute + { + return Attribute::make( + get: fn () => $this->unit->label(), + ); + } + #[Scope] protected function kg(Builder $query): void { diff --git a/app/Models/RawMaterialPrice.php b/app/Models/RawMaterialPrice.php index 1c0261a..9522431 100644 --- a/app/Models/RawMaterialPrice.php +++ b/app/Models/RawMaterialPrice.php @@ -3,7 +3,9 @@ namespace App\Models; use App\Services\S3PresignedService; +use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -12,6 +14,7 @@ use Spatie\MediaLibrary\HasMedia; use Spatie\MediaLibrary\InteractsWithMedia; +#[Appends(['formatted_price'])] #[Guarded(['id'])] class RawMaterialPrice extends Model implements HasMedia { @@ -25,6 +28,13 @@ protected function casts(): array ]; } + protected function formattedPrice(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->price, 0, ',', '.'), + ); + } + public function cuttingMaterials(): HasMany { return $this->hasMany(CuttingMaterial::class); diff --git a/app/Models/Restock.php b/app/Models/Restock.php index a46717b..f0bf58d 100644 --- a/app/Models/Restock.php +++ b/app/Models/Restock.php @@ -3,9 +3,11 @@ namespace App\Models; use App\Enums\ProductStockQuality; +use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; use Illuminate\Database\Eloquent\Attributes\Scope; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -14,6 +16,7 @@ use Spatie\MediaLibrary\HasMedia; use Spatie\MediaLibrary\InteractsWithMedia; +#[Appends(['stock_type_label', 'formatted_subtotal', 'formatted_total'])] #[Guarded(['id'])] class Restock extends Model implements HasMedia { @@ -28,6 +31,27 @@ protected function casts(): array ]; } + protected function stockTypeLabel(): Attribute + { + return Attribute::make( + get: fn () => $this->stock_type->label(), + ); + } + + protected function formattedSubtotal(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->subtotal, 0, ',', '.'), + ); + } + + protected function formattedTotal(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->total, 0, ',', '.'), + ); + } + #[Scope] protected function good(Builder $query): void { diff --git a/app/Models/RestockItem.php b/app/Models/RestockItem.php index 9d36aab..43e64a6 100644 --- a/app/Models/RestockItem.php +++ b/app/Models/RestockItem.php @@ -2,12 +2,15 @@ namespace App\Models; +use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\SoftDeletes; +#[Appends(['formatted_subtotal', 'formatted_unit_price'])] #[Guarded(['id'])] class RestockItem extends Model { @@ -22,6 +25,20 @@ protected function casts(): array ]; } + protected function formattedSubtotal(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->subtotal, 0, ',', '.'), + ); + } + + protected function formattedUnitPrice(): Attribute + { + return Attribute::make( + get: fn () => 'Rp ' . number_format($this->unit_price, 0, ',', '.'), + ); + } + public function productVariant(): BelongsTo { return $this->belongsTo(ProductVariant::class); diff --git a/app/Models/StokOpname.php b/app/Models/StokOpname.php index 55ff1ab..29d9874 100644 --- a/app/Models/StokOpname.php +++ b/app/Models/StokOpname.php @@ -3,15 +3,18 @@ namespace App\Models; use App\Enums\StokOpnameStatus; +use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; use Illuminate\Database\Eloquent\Attributes\Scope; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; +#[Appends(['formatted_opname_date', 'status_label'])] #[Guarded(['id'])] class StokOpname extends Model { @@ -25,6 +28,20 @@ protected function casts(): array ]; } + protected function formattedOpnameDate(): Attribute + { + return Attribute::make( + get: fn () => $this->opname_date?->translatedFormat('l, d F Y'), + ); + } + + protected function statusLabel(): Attribute + { + return Attribute::make( + get: fn () => $this->status->label(), + ); + } + #[Scope] protected function cancelled(Builder $query): void { diff --git a/app/Models/StokOpnameItem.php b/app/Models/StokOpnameItem.php index 24c5d7e..13022b8 100644 --- a/app/Models/StokOpnameItem.php +++ b/app/Models/StokOpnameItem.php @@ -3,13 +3,16 @@ namespace App\Models; use App\Enums\ProductStockQuality; +use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; use Illuminate\Database\Eloquent\Attributes\Scope; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; +#[Appends(['stock_quality_label'])] #[Guarded(['id'])] class StokOpnameItem extends Model { @@ -25,6 +28,13 @@ protected function casts(): array ]; } + protected function stockQualityLabel(): Attribute + { + return Attribute::make( + get: fn () => $this->stock_quality->label(), + ); + } + #[Scope] protected function good(Builder $query): void { diff --git a/app/Models/Supplier.php b/app/Models/Supplier.php index 6c7fbf2..aecbb3c 100644 --- a/app/Models/Supplier.php +++ b/app/Models/Supplier.php @@ -2,17 +2,37 @@ namespace App\Models; +use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; +#[Appends(['formatted_name', 'formatted_phone_number'])] #[Guarded(['id'])] class Supplier extends Model { use HasFactory, SoftDeletes; + protected function formattedName(): Attribute + { + return Attribute::make( + get: fn () => ucfirst($this->name), + ); + } + + protected function formattedPhoneNumber(): Attribute + { + return Attribute::make( + get: fn () => $this->phone_number + ? substr($this->phone_number, 0, 4) . ' ' . substr($this->phone_number, 4, 4) . ' ' . substr($this->phone_number, 8) + : null, + set: fn (?string $value) => $value ? preg_replace('/\s/', '', $value) : null, + ); + } + public function purchases(): HasMany { return $this->hasMany(Purchase::class); diff --git a/app/Models/User.php b/app/Models/User.php index b613ec5..0c54243 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -17,8 +17,8 @@ use NotificationChannels\WebPush\HasPushSubscriptions; use Spatie\Permission\Traits\HasRoles; +#[Appends(['full_name', 'name'])] #[Guarded(['id'])] -#[Appends(['full_name'])] class User extends Authenticatable { use HasFactory, HasPushSubscriptions, HasRoles, Notifiable, SoftDeletes, TwoFactorAuthenticatable; @@ -34,10 +34,11 @@ protected function casts(): array ]; } - #[Scope] - protected function active(Builder $query): void + protected function email(): Attribute { - $query->where('is_active', true); + return Attribute::make( + set: fn (string $value) => strtolower($value), + ); } protected function name(): Attribute @@ -54,6 +55,12 @@ protected function fullName(): Attribute ); } + #[Scope] + protected function active(Builder $query): void + { + $query->where('is_active', true); + } + public function attendances(): HasMany { return $this->hasMany(Attendance::class); diff --git a/app/Models/UserProfile.php b/app/Models/UserProfile.php index feb731e..82eed55 100644 --- a/app/Models/UserProfile.php +++ b/app/Models/UserProfile.php @@ -3,14 +3,17 @@ namespace App\Models; use App\Enums\Gender; +use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; use Illuminate\Database\Eloquent\Attributes\Scope; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\SoftDeletes; +#[Appends(['formatted_birth_date', 'gender_label', 'formatted_phone_number'])] #[Guarded(['id'])] class UserProfile extends Model { @@ -24,6 +27,30 @@ protected function casts(): array ]; } + protected function formattedBirthDate(): Attribute + { + return Attribute::make( + get: fn () => $this->birth_date?->translatedFormat('l, d F Y'), + ); + } + + protected function genderLabel(): Attribute + { + return Attribute::make( + get: fn () => $this->gender->label(), + ); + } + + protected function formattedPhoneNumber(): Attribute + { + return Attribute::make( + get: fn () => $this->phone_number + ? substr($this->phone_number, 0, 4) . ' ' . substr($this->phone_number, 4, 4) . ' ' . substr($this->phone_number, 8) + : null, + set: fn (?string $value) => $value ? preg_replace('/\s/', '', $value) : null, + ); + } + #[Scope] protected function female(Builder $query): void {