'decimal:2', 'remaining_material' => 'decimal:2', ]; } public function cutting(): BelongsTo { return $this->belongsTo(Cutting::class); } public function rawMaterialPrice(): BelongsTo { return $this->belongsTo(RawMaterialPrice::class); } public function materialUsageFormatted(): Attribute { return Attribute::make( get: fn () => $this->formatQuantity($this->material_usage), ); } public function materialUsageInput(): Attribute { return Attribute::make( get: fn () => $this->formatQuantityInput($this->material_usage), ); } public function remainingMaterialFormatted(): Attribute { return Attribute::make( get: fn () => $this->formatQuantity($this->remaining_material), ); } public function remainingMaterialInput(): Attribute { return Attribute::make( get: fn () => $this->formatQuantityInput($this->remaining_material), ); } public function unitAbbreviation(): Attribute { return Attribute::make( get: fn () => $this->rawMaterialPrice?->rawMaterial?->unit?->abbreviation(), ); } public function usesLengthUnit(): Attribute { return Attribute::make( get: fn () => $this->rawMaterialPrice?->rawMaterial?->unit?->usesLengthUnit() ?? false, ); } public function materialUsageCmFormatted(): Attribute { return Attribute::make( get: fn () => $this->formatCmQuantity($this->material_usage), ); } public function materialUsageCmInput(): Attribute { return Attribute::make( get: fn () => $this->formatCmQuantityInput($this->material_usage), ); } public function remainingMaterialCmFormatted(): Attribute { return Attribute::make( get: fn () => $this->formatCmQuantity($this->remaining_material), ); } public function remainingMaterialCmInput(): Attribute { return Attribute::make( get: fn () => $this->formatCmQuantityInput($this->remaining_material), ); } public function materialUsageInCm(): ?float { $unit = $this->rawMaterialPrice?->rawMaterial?->unit; if ($unit === null) { return null; } return $unit->toCm((float) $this->material_usage); } public function remainingMaterialInCm(): ?float { $unit = $this->rawMaterialPrice?->rawMaterial?->unit; if ($unit === null) { return null; } return $unit->toCm((float) $this->remaining_material); } public function materialCost(): int { $price = $this->rawMaterialPrice; if ($price === null) { return 0; } return (int) round((float) $this->material_usage * (int) $price->price); } private function formatCmQuantity(float|string|null $value): ?string { $unit = $this->rawMaterialPrice?->rawMaterial?->unit; if ($unit === null) { return null; } if (! $unit->usesLengthUnit()) { return $this->formatQuantity($value); } $cm = $unit->toCm((float) $value); if ($cm === null) { return null; } $formatted = rtrim(rtrim(number_format($cm, 2, ',', '.'), '0'), ','); return "{$formatted} cm"; } private function formatCmQuantityInput(float|string|null $value): ?string { $unit = $this->rawMaterialPrice?->rawMaterial?->unit; if ($unit === null) { return null; } if (! $unit->usesLengthUnit()) { return $this->formatQuantityInput($value); } $cm = $unit->toCm((float) $value); if ($cm === null) { return null; } return rtrim(rtrim(number_format($cm, 2, '.', ''), '0'), '.'); } private function formatQuantity(float|string|null $value): string { $formatted = rtrim(rtrim(number_format((float) $value, 2, ',', '.'), '0'), ','); return "{$formatted} {$this->unitAbbreviation}"; } private function formatQuantityInput(float|string|null $value): string { return rtrim(rtrim(number_format((float) $value, 2, '.', ''), '0'), '.'); } }