| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 | <?php
namespace App\Models\Setting;
use App\Concerns\Blamable;
use App\Concerns\CompanyOwned;
use App\Enums\Accounting\DocumentDiscountMethod;
use App\Enums\Accounting\DocumentType;
use App\Enums\Setting\Font;
use App\Enums\Setting\PaymentTerms;
use App\Enums\Setting\Template;
use Database\Factories\Setting\DocumentDefaultFactory;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Casts\AsArrayObject;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage;
class DocumentDefault extends Model
{
    use Blamable;
    use CompanyOwned;
    use HasFactory;
    protected $table = 'document_defaults';
    protected $fillable = [
        'company_id',
        'type',
        'logo',
        'show_logo',
        'number_prefix',
        'payment_terms',
        'discount_method',
        'header',
        'subheader',
        'terms',
        'footer',
        'accent_color',
        'font',
        'template',
        'item_name',
        'unit_name',
        'price_name',
        'amount_name',
        'created_by',
        'updated_by',
    ];
    protected $casts = [
        'type' => DocumentType::class,
        'show_logo' => 'boolean',
        'payment_terms' => PaymentTerms::class,
        'discount_method' => DocumentDiscountMethod::class,
        'font' => Font::class,
        'template' => Template::class,
        'item_name' => AsArrayObject::class,
        'unit_name' => AsArrayObject::class,
        'price_name' => AsArrayObject::class,
        'amount_name' => AsArrayObject::class,
    ];
    protected $appends = [
        'logo_url',
    ];
    protected function logoUrl(): Attribute
    {
        return Attribute::get(static function (mixed $value, array $attributes): ?string {
            return $attributes['logo'] ? Storage::disk('public')->url($attributes['logo']) : null;
        });
    }
    public function scopeType(Builder $query, string | DocumentType $type): Builder
    {
        return $query->where('type', $type);
    }
    public function scopeInvoice(Builder $query): Builder
    {
        return $query->type(DocumentType::Invoice);
    }
    public function scopeRecurringInvoice(Builder $query): Builder
    {
        return $query->type(DocumentType::RecurringInvoice);
    }
    public function scopeBill(Builder $query): Builder
    {
        return $query->type(DocumentType::Bill);
    }
    public function scopeEstimate(Builder $query): Builder
    {
        return $query->type(DocumentType::Estimate);
    }
    public function getNumberNext(?string $prefix = null, int | string | null $next = null): string
    {
        $numberPrefix = $prefix ?? $this->number_prefix ?? '';
        $numberNext = (string) ($next ?? (static::getBaseNumber() + 1));
        return $numberPrefix . $numberNext;
    }
    public static function getBaseNumber(): int
    {
        return 1000;
    }
    public static function getAvailableItemNameOptions(): array
    {
        $options = [
            'items' => 'Items',
            'products' => 'Products',
            'services' => 'Services',
            'other' => 'Other',
        ];
        return array_map(translate(...), $options);
    }
    public static function getAvailableUnitNameOptions(): array
    {
        $options = [
            'quantity' => 'Quantity',
            'hours' => 'Hours',
            'other' => 'Other',
        ];
        return array_map(translate(...), $options);
    }
    public static function getAvailablePriceNameOptions(): array
    {
        $options = [
            'price' => 'Price',
            'rate' => 'Rate',
            'other' => 'Other',
        ];
        return array_map(translate(...), $options);
    }
    public static function getAvailableAmountNameOptions(): array
    {
        $options = [
            'amount' => 'Amount',
            'total' => 'Total',
            'other' => 'Other',
        ];
        return array_map(translate(...), $options);
    }
    public function getLabelOptionFor(string $optionType, ?string $optionValue)
    {
        $optionValue = $optionValue ?? $this->{$optionType}['option'];
        if (! $optionValue) {
            return null;
        }
        $options = match ($optionType) {
            'item_name' => static::getAvailableItemNameOptions(),
            'unit_name' => static::getAvailableUnitNameOptions(),
            'price_name' => static::getAvailablePriceNameOptions(),
            'amount_name' => static::getAvailableAmountNameOptions(),
            default => [],
        };
        return $options[$optionValue] ?? null;
    }
    public function resolveColumnLabel(string $column, string $default, ?array $data = null): string
    {
        if ($data) {
            $custom = $data[$column]['custom'] ?? null;
            $option = $data[$column]['option'] ?? null;
        } else {
            $custom = $this->{$column}['custom'] ?? null;
            $option = $this->{$column}['option'] ?? null;
        }
        if ($custom) {
            return $custom;
        }
        return $this->getLabelOptionFor($column, $option) ?? $default;
    }
    protected static function newFactory(): Factory
    {
        return DocumentDefaultFactory::new();
    }
}
 |