Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

AccountChart.php 6.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. <?php
  2. namespace App\Filament\Company\Pages\Accounting;
  3. use App\Enums\Accounting\AccountCategory;
  4. use App\Models\Accounting\Account as ChartModel;
  5. use App\Models\Accounting\AccountSubtype;
  6. use App\Utilities\Accounting\AccountCode;
  7. use App\Utilities\Currency\CurrencyAccessor;
  8. use Filament\Actions\Action;
  9. use Filament\Actions\CreateAction;
  10. use Filament\Actions\EditAction;
  11. use Filament\Forms\Components\Select;
  12. use Filament\Forms\Components\Textarea;
  13. use Filament\Forms\Components\TextInput;
  14. use Filament\Forms\Form;
  15. use Filament\Forms\Get;
  16. use Filament\Forms\Set;
  17. use Filament\Pages\Page;
  18. use Filament\Support\Enums\MaxWidth;
  19. use Illuminate\Support\Collection;
  20. use Livewire\Attributes\Computed;
  21. use Livewire\Attributes\Url;
  22. class AccountChart extends Page
  23. {
  24. protected static ?string $navigationIcon = 'heroicon-o-clipboard-document-list';
  25. protected static ?string $title = 'Chart of Accounts';
  26. protected static ?string $navigationGroup = 'Accounting';
  27. protected static ?string $slug = 'accounting/chart';
  28. protected static string $view = 'filament.company.pages.accounting.chart';
  29. public ?ChartModel $chart = null;
  30. #[Url]
  31. public ?string $activeTab = null;
  32. public function mount(): void
  33. {
  34. $this->activeTab = $this->activeTab ?? AccountCategory::Asset->value;
  35. }
  36. protected function configureAction(Action $action): void
  37. {
  38. $action
  39. ->modalWidth(MaxWidth::TwoExtraLarge)
  40. ->stickyModalHeader()
  41. ->stickyModalFooter();
  42. }
  43. #[Computed]
  44. public function categories(): Collection
  45. {
  46. return AccountSubtype::withCount('accounts')
  47. ->get()
  48. ->groupBy('category');
  49. }
  50. public function editChartAction(): Action
  51. {
  52. return EditAction::make()
  53. ->iconButton()
  54. ->record($this->chart)
  55. ->name('editChart')
  56. ->label('Edit account')
  57. ->modalHeading('Edit Account')
  58. ->icon('heroicon-m-pencil-square')
  59. ->mountUsing(function (array $arguments, Form $form) {
  60. $chartId = $arguments['chart'];
  61. $this->chart = ChartModel::find($chartId);
  62. $form
  63. ->fill($this->chart->toArray())
  64. ->operation('edit')
  65. ->model($this->chart); // This is needed for form relationships to work (maybe a bug in Filament regarding passed arguments related to timing)
  66. })
  67. ->form($this->getChartForm());
  68. }
  69. public function createChartAction(): Action
  70. {
  71. return CreateAction::make()
  72. ->link()
  73. ->name('createChart')
  74. ->form($this->getChartForm())
  75. ->model(ChartModel::class)
  76. ->label('Add a new account')
  77. ->icon('heroicon-o-plus-circle')
  78. ->mountUsing(function (array $arguments, Form $form) {
  79. $subtypeId = $arguments['subtype'];
  80. $this->chart = new ChartModel([
  81. 'subtype_id' => $subtypeId,
  82. ]);
  83. if ($subtypeId) {
  84. $companyId = auth()->user()->currentCompany->id;
  85. $generatedCode = AccountCode::generate($companyId, $subtypeId);
  86. $this->chart->code = $generatedCode;
  87. }
  88. $form->fill($this->chart->toArray())
  89. ->operation('create');
  90. });
  91. }
  92. private function getChartForm(bool $useActiveTab = true): array
  93. {
  94. return [
  95. Select::make('subtype_id')
  96. ->label('Type')
  97. ->required()
  98. ->live()
  99. ->disabled(static fn (string $operation, ?ChartModel $record) => $operation === 'edit' && $record?->default === true)
  100. ->options($this->getChartSubtypeOptions($useActiveTab))
  101. ->afterStateUpdated(static function (?string $state, Set $set): void {
  102. if ($state) {
  103. $companyId = auth()->user()->currentCompany->id;
  104. $generatedCode = AccountCode::generate($companyId, $state);
  105. $set('code', $generatedCode);
  106. }
  107. }),
  108. TextInput::make('code')
  109. ->label('Code')
  110. ->required()
  111. ->validationAttribute('account code')
  112. ->unique(table: ChartModel::class, column: 'code', ignoreRecord: true)
  113. ->validateAccountCode(static fn (Get $get) => $get('subtype_id')),
  114. TextInput::make('name')
  115. ->label('Name')
  116. ->required(),
  117. Select::make('currency_code')
  118. ->localizeLabel('Currency')
  119. ->relationship('currency', 'name')
  120. ->default(CurrencyAccessor::getDefaultCurrency())
  121. ->preload()
  122. ->searchable()
  123. ->visible(function (Get $get): bool {
  124. return filled($get('subtype_id')) && AccountSubtype::find($get('subtype_id'))->multi_currency;
  125. })
  126. ->live(),
  127. Textarea::make('description')
  128. ->label('Description')
  129. ->autosize(),
  130. ];
  131. }
  132. private function getChartSubtypeOptions($useActiveTab = true): array
  133. {
  134. $subtypes = $useActiveTab ?
  135. AccountSubtype::where('category', $this->activeTab)->get() :
  136. AccountSubtype::all();
  137. return $subtypes->groupBy(fn (AccountSubtype $subtype) => $subtype->type->getLabel())
  138. ->map(fn (Collection $subtypes, string $type) => $subtypes->mapWithKeys(static fn (AccountSubtype $subtype) => [$subtype->id => $subtype->name]))
  139. ->toArray();
  140. }
  141. protected function getHeaderActions(): array
  142. {
  143. return [
  144. CreateAction::make()
  145. ->button()
  146. ->label('Add New Account')
  147. ->model(ChartModel::class)
  148. ->form($this->getChartForm(false)),
  149. ];
  150. }
  151. public function getCategoryLabel($categoryValue): string
  152. {
  153. return AccountCategory::from($categoryValue)->getLabel();
  154. }
  155. }