| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 | 
							- <?php
 - 
 - namespace App\Filament\Company\Pages\Accounting;
 - 
 - use App\Enums\Accounting\AccountCategory;
 - use App\Enums\Banking\BankAccountType;
 - use App\Filament\Forms\Components\CreateCurrencySelect;
 - use App\Models\Accounting\Account;
 - use App\Models\Accounting\AccountSubtype;
 - use App\Utilities\Accounting\AccountCode;
 - use Filament\Actions\Action;
 - use Filament\Actions\CreateAction;
 - use Filament\Actions\EditAction;
 - use Filament\Forms\Components\Checkbox;
 - use Filament\Forms\Components\Component;
 - use Filament\Forms\Components\Group;
 - use Filament\Forms\Components\Select;
 - use Filament\Forms\Components\Textarea;
 - use Filament\Forms\Components\TextInput;
 - use Filament\Forms\Form;
 - use Filament\Forms\Get;
 - use Filament\Forms\Set;
 - use Filament\Pages\Page;
 - use Filament\Support\Enums\MaxWidth;
 - use Illuminate\Support\Collection;
 - use Illuminate\Support\Facades\Auth;
 - use Illuminate\Validation\Rules\Unique;
 - use Livewire\Attributes\Computed;
 - use Livewire\Attributes\Url;
 - 
 - class AccountChart extends Page
 - {
 -     protected static ?string $title = 'Chart of Accounts';
 - 
 -     protected static ?string $slug = 'accounting/chart';
 - 
 -     protected static string $view = 'filament.company.pages.accounting.chart';
 - 
 -     #[Url]
 -     public ?string $activeTab = AccountCategory::Asset->value;
 - 
 -     protected function configureAction(Action $action): void
 -     {
 -         $action
 -             ->modal()
 -             ->slideOver()
 -             ->modalWidth(MaxWidth::TwoExtraLarge);
 -     }
 - 
 -     #[Computed]
 -     public function categories(): Collection
 -     {
 -         return AccountSubtype::withCount('accounts')
 -             ->with('accounts')
 -             ->with('accounts.adjustment')
 -             ->get()
 -             ->groupBy('category');
 -     }
 - 
 -     public function editChartAction(): Action
 -     {
 -         return EditAction::make()
 -             ->iconButton()
 -             ->name('editChart')
 -             ->label('Edit account')
 -             ->modalHeading('Edit Account')
 -             ->icon('heroicon-m-pencil-square')
 -             ->record(fn (array $arguments) => Account::find($arguments['chart']))
 -             ->form(fn (Form $form) => $this->getChartForm($form)->operation('edit'));
 -     }
 - 
 -     public function createChartAction(): Action
 -     {
 -         return CreateAction::make()
 -             ->link()
 -             ->name('createChart')
 -             ->model(Account::class)
 -             ->label('Add a new account')
 -             ->icon('heroicon-o-plus-circle')
 -             ->form(fn (Form $form) => $this->getChartForm($form)->operation('create'))
 -             ->fillForm(fn (array $arguments): array => $this->getChartFormDefaults($arguments['subtype']));
 -     }
 - 
 -     private function getChartFormDefaults(int $subtypeId): array
 -     {
 -         $accountSubtype = AccountSubtype::find($subtypeId);
 -         $generatedCode = AccountCode::generate($accountSubtype);
 - 
 -         return [
 -             'subtype_id' => $subtypeId,
 -             'code' => $generatedCode,
 -         ];
 -     }
 - 
 -     private function getChartForm(Form $form, bool $useActiveTab = true): Form
 -     {
 -         return $form
 -             ->schema([
 -                 $this->getTypeFormComponent($useActiveTab),
 -                 $this->getCodeFormComponent(),
 -                 $this->getNameFormComponent(),
 -                 ...$this->getBankAccountFormComponents(),
 -                 $this->getCurrencyFormComponent(),
 -                 $this->getDescriptionFormComponent(),
 -                 $this->getArchiveFormComponent(),
 -             ]);
 -     }
 - 
 -     protected function getTypeFormComponent(bool $useActiveTab = true): Component
 -     {
 -         return Select::make('subtype_id')
 -             ->label('Type')
 -             ->required()
 -             ->live()
 -             ->disabledOn('edit')
 -             ->options($this->getChartSubtypeOptions($useActiveTab))
 -             ->afterStateUpdated(static function (?string $state, Set $set): void {
 -                 if ($state) {
 -                     $accountSubtype = AccountSubtype::find($state);
 -                     $generatedCode = AccountCode::generate($accountSubtype);
 -                     $set('code', $generatedCode);
 - 
 -                     $set('is_bank_account', false);
 -                     $set('bankAccount.type', null);
 -                     $set('bankAccount.number', null);
 -                 }
 -             });
 -     }
 - 
 -     protected function getCodeFormComponent(): Component
 -     {
 -         return TextInput::make('code')
 -             ->label('Code')
 -             ->required()
 -             ->hiddenOn('edit')
 -             ->validationAttribute('account code')
 -             ->unique(table: Account::class, column: 'code', ignoreRecord: true)
 -             ->validateAccountCode(static fn (Get $get) => $get('subtype_id'));
 -     }
 - 
 -     protected function getBankAccountFormComponents(): array
 -     {
 -         return [
 -             Checkbox::make('is_bank_account')
 -                 ->live()
 -                 ->visible(function (Get $get, string $operation) {
 -                     if ($operation === 'edit') {
 -                         return false;
 -                     }
 - 
 -                     $subtype = $get('subtype_id');
 -                     if (empty($subtype)) {
 -                         return false;
 -                     }
 - 
 -                     $accountSubtype = AccountSubtype::find($subtype);
 - 
 -                     if (! $accountSubtype) {
 -                         return false;
 -                     }
 - 
 -                     return in_array($accountSubtype->category, [
 -                         AccountCategory::Asset,
 -                         AccountCategory::Liability,
 -                     ]) && $accountSubtype->multi_currency;
 -                 })
 -                 ->afterStateUpdated(static function ($state, Get $get, Set $set) {
 -                     if ($state) {
 -                         $subtypeId = $get('subtype_id');
 - 
 -                         if (empty($subtypeId)) {
 -                             return;
 -                         }
 - 
 -                         $subtype = AccountSubtype::find($subtypeId);
 - 
 -                         if (! $subtype) {
 -                             return;
 -                         }
 - 
 -                         // Set default bank account type based on account category
 -                         if ($subtype->category === AccountCategory::Asset) {
 -                             $set('bankAccount.type', BankAccountType::Depository->value);
 -                         } elseif ($subtype->category === AccountCategory::Liability) {
 -                             $set('bankAccount.type', BankAccountType::Credit->value);
 -                         }
 -                     } else {
 -                         // Clear bank account fields
 -                         $set('bankAccount.type', null);
 -                         $set('bankAccount.number', null);
 -                     }
 -                 }),
 -             Group::make()
 -                 ->relationship('bankAccount')
 -                 ->schema([
 -                     Select::make('type')
 -                         ->label('Bank account type')
 -                         ->options(function (Get $get) {
 -                             $subtype = $get('../subtype_id');
 - 
 -                             if (empty($subtype)) {
 -                                 return [];
 -                             }
 - 
 -                             $accountSubtype = AccountSubtype::find($subtype);
 - 
 -                             if (! $accountSubtype) {
 -                                 return [];
 -                             }
 - 
 -                             if ($accountSubtype->category === AccountCategory::Asset) {
 -                                 return [
 -                                     BankAccountType::Depository->value => BankAccountType::Depository->getLabel(),
 -                                     BankAccountType::Investment->value => BankAccountType::Investment->getLabel(),
 -                                 ];
 -                             } elseif ($accountSubtype->category === AccountCategory::Liability) {
 -                                 return [
 -                                     BankAccountType::Credit->value => BankAccountType::Credit->getLabel(),
 -                                     BankAccountType::Loan->value => BankAccountType::Loan->getLabel(),
 -                                 ];
 -                             }
 - 
 -                             return [];
 -                         })
 -                         ->searchable()
 -                         ->columnSpan(1)
 -                         ->disabledOn('edit')
 -                         ->required(),
 -                     TextInput::make('number')
 -                         ->label('Bank account number')
 -                         ->unique(ignoreRecord: true, modifyRuleUsing: static function (Unique $rule, $state) {
 -                             $companyId = Auth::user()->currentCompany->id;
 - 
 -                             return $rule->where('company_id', $companyId)->where('number', $state);
 -                         })
 -                         ->maxLength(20)
 -                         ->validationAttribute('account number'),
 -                 ])
 -                 ->visible(static function (Get $get, ?Account $record, string $operation) {
 -                     if ($operation === 'create') {
 -                         return (bool) $get('is_bank_account');
 -                     }
 - 
 -                     if ($operation === 'edit' && $record) {
 -                         return (bool) $record->bankAccount;
 -                     }
 - 
 -                     return false;
 -                 }),
 -         ];
 -     }
 - 
 -     protected function getNameFormComponent(): Component
 -     {
 -         return TextInput::make('name')
 -             ->label('Name')
 -             ->required();
 -     }
 - 
 -     protected function getCurrencyFormComponent(): Component
 -     {
 -         return CreateCurrencySelect::make('currency_code')
 -             ->disabledOn('edit')
 -             ->required(false)
 -             ->requiredIfAccepted('is_bank_account')
 -             ->validationMessages([
 -                 'required_if_accepted' => 'The currency is required for bank accounts.',
 -             ])
 -             ->visible(function (Get $get): bool {
 -                 return filled($get('subtype_id')) && AccountSubtype::find($get('subtype_id'))->multi_currency;
 -             });
 -     }
 - 
 -     protected function getDescriptionFormComponent(): Component
 -     {
 -         return Textarea::make('description')
 -             ->label('Description');
 -     }
 - 
 -     protected function getArchiveFormComponent(): Component
 -     {
 -         return Checkbox::make('archived')
 -             ->label('Archive account')
 -             ->helperText('Archived accounts will not be available for selection in transactions.')
 -             ->hiddenOn('create');
 -     }
 - 
 -     private function getChartSubtypeOptions($useActiveTab = true): array
 -     {
 -         $subtypes = $useActiveTab ?
 -             AccountSubtype::where('category', $this->activeTab)->get() :
 -             AccountSubtype::all();
 - 
 -         return $subtypes->groupBy(fn (AccountSubtype $subtype) => $subtype->type->getLabel())
 -             ->map(fn (Collection $subtypes, string $type) => $subtypes->mapWithKeys(static fn (AccountSubtype $subtype) => [$subtype->id => $subtype->name]))
 -             ->toArray();
 -     }
 - 
 -     protected function getHeaderActions(): array
 -     {
 -         return [
 -             CreateAction::make()
 -                 ->button()
 -                 ->label('Add new account')
 -                 ->model(Account::class)
 -                 ->form(fn (Form $form) => $this->getChartForm($form, false)->operation('create')),
 -         ];
 -     }
 - 
 -     public function getCategoryLabel($categoryValue): string
 -     {
 -         return AccountCategory::from($categoryValue)->getPluralLabel();
 -     }
 - }
 
 
  |