Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

CurrencyResource.php 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. <?php
  2. namespace App\Filament\Resources;
  3. use App\Filament\Resources\CurrencyResource\Pages;
  4. use App\Filament\Resources\CurrencyResource\RelationManagers;
  5. use App\Models\Banking\Account;
  6. use App\Models\Setting\Currency;
  7. use Closure;
  8. use Exception;
  9. use Filament\Forms;
  10. use Filament\Notifications\Notification;
  11. use Filament\Resources\Form;
  12. use Filament\Resources\Resource;
  13. use Filament\Resources\Table;
  14. use Filament\Tables;
  15. use Illuminate\Database\Eloquent\Builder;
  16. use Illuminate\Database\Eloquent\Model;
  17. use Illuminate\Database\Eloquent\SoftDeletingScope;
  18. use Illuminate\Support\Collection;
  19. use Illuminate\Support\Facades\Auth;
  20. class CurrencyResource extends Resource
  21. {
  22. protected static ?string $model = Currency::class;
  23. protected static ?string $navigationIcon = 'heroicon-o-currency-dollar';
  24. protected static ?string $navigationGroup = 'Settings';
  25. public static function getEloquentQuery(): Builder
  26. {
  27. return parent::getEloquentQuery()->where('company_id', Auth::user()->currentCompany->id);
  28. }
  29. public static function form(Form $form): Form
  30. {
  31. return $form
  32. ->schema([
  33. Forms\Components\Section::make('General')
  34. ->schema([
  35. Forms\Components\Select::make('code')
  36. ->label('Code')
  37. ->options(Currency::getCurrencyCodes())
  38. ->searchable()
  39. ->placeholder('- Select Code -')
  40. ->reactive()
  41. ->afterStateUpdated(static function (Closure $set, $state) {
  42. $code = $state;
  43. $name = config("money.{$code}.name");
  44. $precision = config("money.{$code}.precision");
  45. $symbol = config("money.{$code}.symbol");
  46. $symbol_first = config("money.{$code}.symbol_first");
  47. $decimal_mark = config("money.{$code}.decimal_mark");
  48. $thousands_separator = config("money.{$code}.thousands_separator");
  49. $set('name', $name);
  50. $set('precision', $precision);
  51. $set('symbol', $symbol);
  52. $set('symbol_first', $symbol_first);
  53. $set('decimal_mark', $decimal_mark);
  54. $set('thousands_separator', $thousands_separator);
  55. })
  56. ->required(),
  57. Forms\Components\TextInput::make('name')
  58. ->translateLabel()
  59. ->placeholder('Enter Name')
  60. ->maxLength(100)
  61. ->required(),
  62. Forms\Components\TextInput::make('rate')
  63. ->label('Rate')
  64. ->placeholder('Enter Rate')
  65. ->dehydrateStateUsing(static fn (Closure $get, $state): bool => $get('enabled') === true ? '1' : $state) // rate is 1 when enabled is true
  66. ->numeric()
  67. ->disabled(static fn (Closure $get): bool => $get('enabled') === true) // disabled is true when enabled is true
  68. ->mask(static fn (Forms\Components\TextInput\Mask $mask) => $mask
  69. ->numeric()
  70. ->decimalPlaces(4)
  71. ->signed(false)
  72. ->padFractionalZeros(false)
  73. ->normalizeZeros(false)
  74. ->minValue(0.0001)
  75. ->maxValue(999999.9999)
  76. ->lazyPlaceholder(false))
  77. ->required(),
  78. Forms\Components\Select::make('precision')
  79. ->label('Precision')
  80. ->searchable()
  81. ->placeholder('- Select Precision -')
  82. ->options(['0', '1', '2', '3', '4'])
  83. ->required(),
  84. Forms\Components\TextInput::make('symbol')
  85. ->label('Symbol')
  86. ->placeholder('Enter Symbol')
  87. ->maxLength(5)
  88. ->required(),
  89. Forms\Components\Select::make('symbol_first')
  90. ->label('Symbol Position')
  91. ->searchable()
  92. ->boolean('Before Amount', 'After Amount', '- Select Symbol Position -')
  93. ->required(),
  94. Forms\Components\TextInput::make('decimal_mark')
  95. ->label('Decimal Separator')
  96. ->placeholder('Enter Decimal Separator')
  97. ->maxLength(1)
  98. ->required(),
  99. Forms\Components\TextInput::make('thousands_separator')
  100. ->label('Thousands Separator')
  101. ->placeholder('Enter Thousands Separator')
  102. ->maxLength(1)
  103. ->required(),
  104. Forms\Components\Toggle::make('enabled')
  105. ->label('Default Currency')
  106. ->reactive()
  107. ->inline()
  108. ->afterStateUpdated(static fn (Closure $set, $state) => $state ? $set('rate', '1') : $set('rate', null))
  109. ->default(false),
  110. ])->columns(),
  111. ]);
  112. }
  113. /**
  114. * @throws Exception
  115. */
  116. public static function table(Table $table): Table
  117. {
  118. return $table
  119. ->columns([
  120. Tables\Columns\TextColumn::make('name')
  121. ->label('Name')
  122. ->weight('semibold')
  123. ->icon(static fn (Currency $record) => $record->enabled ? 'heroicon-o-lock-closed' : null)
  124. ->tooltip(static fn (Currency $record) => $record->enabled ? 'Default Currency' : null)
  125. ->iconPosition('after')
  126. ->searchable()
  127. ->sortable(),
  128. Tables\Columns\TextColumn::make('code')
  129. ->label('Code')
  130. ->searchable()
  131. ->sortable(),
  132. Tables\Columns\TextColumn::make('symbol')
  133. ->label('Symbol')
  134. ->searchable()
  135. ->sortable(),
  136. Tables\Columns\TextColumn::make('rate')
  137. ->label('Rate')
  138. ->formatStateUsing(static fn ($state) => str_contains($state, '.') ? rtrim(rtrim($state, '0'), '.') : null)
  139. ->searchable()
  140. ->sortable(),
  141. ])
  142. ->filters([
  143. //
  144. ])
  145. ->actions([
  146. Tables\Actions\EditAction::make(),
  147. Tables\Actions\DeleteAction::make()
  148. ->before(static function (Tables\Actions\DeleteAction $action, Currency $record) {
  149. $defaultCurrency = $record->enabled;
  150. $accountUsesCurrency = Account::where('currency_code', $record->code)->exists();
  151. if ($defaultCurrency) {
  152. Notification::make()
  153. ->danger()
  154. ->title('Action Denied')
  155. ->body(__('The :name currency is currently set as the default currency and cannot be deleted. Please set a different currency as your default before attempting to delete this one.', ['name' => $record->name]))
  156. ->persistent()
  157. ->send();
  158. $action->cancel();
  159. } elseif ($accountUsesCurrency) {
  160. Notification::make()
  161. ->danger()
  162. ->title('Action Denied')
  163. ->body(__('The :name currency is currently in use by one or more accounts and cannot be deleted. Please remove this currency from all accounts before attempting to delete it.', ['name' => $record->name]))
  164. ->persistent()
  165. ->send();
  166. $action->cancel();
  167. }
  168. }),
  169. ])
  170. ->bulkActions([
  171. Tables\Actions\DeleteBulkAction::make()
  172. ->before(static function (Tables\Actions\DeleteBulkAction $action, Collection $records) {
  173. foreach ($records as $record) {
  174. $defaultCurrency = $record->enabled;
  175. $accountUsesCurrency = Account::where('currency_code', $record->code)->exists();
  176. if ($defaultCurrency) {
  177. Notification::make()
  178. ->danger()
  179. ->title('Action Denied')
  180. ->body(__('The :name currency is currently set as the default currency and cannot be deleted. Please set a different currency as your default before attempting to delete this one.', ['name' => $record->name]))
  181. ->persistent()
  182. ->send();
  183. $action->cancel();
  184. } elseif ($accountUsesCurrency) {
  185. Notification::make()
  186. ->danger()
  187. ->title('Action Denied')
  188. ->body(__('The :name currency is currently in use by one or more accounts and cannot be deleted. Please remove this currency from all accounts before attempting to delete it.', ['name' => $record->name]))
  189. ->persistent()
  190. ->send();
  191. $action->cancel();
  192. }
  193. }
  194. }),
  195. ]);
  196. }
  197. public static function getRelations(): array
  198. {
  199. return [
  200. //
  201. ];
  202. }
  203. public static function getPages(): array
  204. {
  205. return [
  206. 'index' => Pages\ListCurrencies::route('/'),
  207. 'create' => Pages\CreateCurrency::route('/create'),
  208. 'edit' => Pages\EditCurrency::route('/{record}/edit'),
  209. ];
  210. }
  211. }