store/app/Models/Cutting.php
Yoga Pangestu 9539ff7042 refactor: remove StockController and related stock verification logic
- Deleted `data-table-actions.vue` component as it is no longer needed.
- Removed `CuttingResultPriceItem` type and related properties from `cutting.ts`.
- Updated routes in `web.php` to eliminate stock verification routes and permissions.
- Removed `StockTest.php` file and its associated tests for stock verification and management.
- Adjusted `CuttingTest.php` to reflect changes in cutting results handling and removed references to product variants.
2026-07-19 17:29:19 +07:00

119 lines
3.1 KiB
PHP

<?php
namespace App\Models;
use App\Enums\CuttingStatus;
use App\Models\Concerns\HasModuleMedia;
use App\Models\Concerns\HasRejection;
use App\Models\Concerns\InteractsWithActivityLog;
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;
use Illuminate\Validation\ValidationException;
use Spatie\MediaLibrary\HasMedia;
#[Guarded(['id'])]
#[Appends([
'created_at_formatted',
'status_label',
])]
class Cutting extends Model implements HasMedia
{
// 1. Use Trait
use HasFactory, HasModuleMedia, HasRejection, InteractsWithActivityLog, SoftDeletes;
// 2. Casting
protected function casts(): array
{
return [
'cost_per_unit' => 'integer',
'other_cost' => 'integer',
'sewing_cost' => 'integer',
'status' => CuttingStatus::class,
'total_material_cost' => 'integer',
];
}
// 3. Scope (grouped by column, then alphabetical)
// Column Group: status
#[Scope]
protected function completed(Builder $query): void
{
$query->where('status', CuttingStatus::COMPLETED);
}
#[Scope]
protected function inProgress(Builder $query): void
{
$query->where('status', CuttingStatus::IN_PROGRESS);
}
// 4. Attribute
public function createdAtFormatted(): Attribute
{
return Attribute::make(
get: fn () => $this->created_at?->translatedFormat('l, d F Y H:i'),
);
}
public function statusLabel(): Attribute
{
return Attribute::make(
get: fn () => $this->status->label(),
);
}
// 5. Other Methods
public static function mediaModuleName(): string
{
return 'cutting';
}
public function registerMediaCollections(): void
{
$this->addMediaCollection('images');
}
public function ensureEditable(): void
{
if (! $this->status->isEditable()) {
throw ValidationException::withMessages([
'status' => 'Proses cutting tidak dapat diubah.',
]);
}
}
// 6. Relation
public function createdBy(): BelongsTo
{
return $this->belongsTo(User::class, 'created_by_id')->withTrashed();
}
public function materials(): HasMany
{
return $this->hasMany(CuttingMaterial::class);
}
public function combinations(): HasMany
{
return $this->hasMany(CuttingMaterialCombination::class);
}
public function results(): HasMany
{
return $this->hasMany(CuttingResult::class);
}
public function submittedBy(): BelongsTo
{
return $this->belongsTo(User::class, 'submitted_by_id')->withTrashed();
}
}