Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

MacroServiceProvider.php 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. <?php
  2. namespace App\Providers;
  3. use Akaunting\Money\Currency;
  4. use Akaunting\Money\Money;
  5. use App\Enums\Setting\DateFormat;
  6. use App\Models\Accounting\AccountSubtype;
  7. use App\Models\Setting\Localization;
  8. use App\Utilities\Accounting\AccountCode;
  9. use App\Utilities\Currency\CurrencyAccessor;
  10. use BackedEnum;
  11. use Closure;
  12. use Filament\Forms\Components\Field;
  13. use Filament\Forms\Components\TextInput;
  14. use Filament\Tables\Columns\TextColumn;
  15. use Illuminate\Support\Carbon;
  16. use Illuminate\Support\ServiceProvider;
  17. use Illuminate\Support\Str;
  18. class MacroServiceProvider extends ServiceProvider
  19. {
  20. /**
  21. * Register services.
  22. */
  23. public function register(): void
  24. {
  25. //
  26. }
  27. /**
  28. * Bootstrap services.
  29. */
  30. public function boot(): void
  31. {
  32. TextInput::macro('money', function (string | Closure | null $currency = null): static {
  33. $this->extraAttributes(['wire:key' => Str::random()])
  34. ->prefix(static function (TextInput $component) use ($currency) {
  35. $currency = $component->evaluate($currency);
  36. return currency($currency)->getPrefix();
  37. })
  38. ->suffix(static function (TextInput $component) use ($currency) {
  39. $currency = $component->evaluate($currency);
  40. return currency($currency)->getSuffix();
  41. })
  42. ->mask(static function (TextInput $component) use ($currency) {
  43. $currency = $component->evaluate($currency);
  44. return moneyMask($currency);
  45. });
  46. return $this;
  47. });
  48. TextColumn::macro('localizeDate', function (): static {
  49. $localization = Localization::firstOrFail();
  50. $dateFormat = $localization->date_format->value ?? DateFormat::DEFAULT;
  51. $timezone = $localization->timezone ?? Carbon::now()->timezoneName;
  52. $this->date($dateFormat, $timezone);
  53. return $this;
  54. });
  55. TextColumn::macro('currency', function (string | Closure | null $currency = null, ?bool $convert = null): static {
  56. $this->formatStateUsing(static function (TextColumn $column, $state) use ($currency, $convert): ?string {
  57. if (blank($state)) {
  58. return null;
  59. }
  60. $currency = $column->evaluate($currency);
  61. $convert = $column->evaluate($convert);
  62. return money($state, $currency, $convert)->format();
  63. });
  64. return $this;
  65. });
  66. TextInput::macro('rate', function (string | Closure | null $computation = null): static {
  67. $this->extraAttributes(['wire:key' => Str::random()])
  68. ->prefix(static function (TextInput $component) use ($computation) {
  69. $computation = $component->evaluate($computation);
  70. return ratePrefix(computation: $computation);
  71. })
  72. ->suffix(static function (TextInput $component) use ($computation) {
  73. $computation = $component->evaluate($computation);
  74. return rateSuffix(computation: $computation);
  75. })
  76. ->mask(static function (TextInput $component) use ($computation) {
  77. $computation = $component->evaluate($computation);
  78. return rateMask(computation: $computation);
  79. })
  80. ->rule(static function (TextInput $component) use ($computation) {
  81. return static function (string $attribute, $value, Closure $fail) use ($computation, $component) {
  82. $computation = $component->evaluate($computation);
  83. $numericValue = (float) $value;
  84. if ($computation instanceof BackedEnum) {
  85. $computation = $computation->value;
  86. }
  87. if ($computation === 'percentage' || $computation === 'compound') {
  88. if ($numericValue < 0 || $numericValue > 100) {
  89. $fail(translate('The rate must be between 0 and 100.'));
  90. }
  91. } elseif ($computation === 'fixed' && $numericValue < 0) {
  92. $fail(translate('The rate must be greater than 0.'));
  93. }
  94. };
  95. });
  96. return $this;
  97. });
  98. Field::macro('validateAccountCode', function (string | Closure | null $subtype = null): static {
  99. $this
  100. ->rules([
  101. fn (Field $component): Closure => static function (string $attribute, $value, Closure $fail) use ($subtype, $component) {
  102. $subtype = $component->evaluate($subtype);
  103. $chartSubtype = AccountSubtype::find($subtype);
  104. $type = $chartSubtype->type;
  105. if (! AccountCode::isValidCode($value, $type)) {
  106. $message = AccountCode::getMessage($type);
  107. $fail($message);
  108. }
  109. },
  110. ]);
  111. return $this;
  112. });
  113. TextColumn::macro('rate', function (string | Closure | null $computation = null): static {
  114. $this->formatStateUsing(static function (TextColumn $column, $state) use ($computation): ?string {
  115. $computation = $column->evaluate($computation);
  116. return rateFormat(state: $state, computation: $computation);
  117. });
  118. return $this;
  119. });
  120. Field::macro('softRequired', function (): static {
  121. $this
  122. ->required()
  123. ->markAsRequired(false);
  124. return $this;
  125. });
  126. Money::macro('swapAmountFor', function ($newCurrency) {
  127. $oldCurrency = $this->currency->getCurrency();
  128. $balanceInMajorUnits = $this->getAmount();
  129. $oldRate = currency($oldCurrency)->getRate();
  130. $newRate = currency($newCurrency)->getRate();
  131. $ratio = $newRate / $oldRate;
  132. $convertedBalance = bcmul($balanceInMajorUnits, $ratio, 2);
  133. return (int) round($convertedBalance);
  134. });
  135. Money::macro('formatWithCode', function (bool $codeBefore = false) {
  136. $formatted = $this->format();
  137. $currencyCode = $this->currency->getCurrency();
  138. if ($currencyCode === CurrencyAccessor::getDefaultCurrency()) {
  139. return $formatted;
  140. }
  141. if ($codeBefore) {
  142. return $currencyCode . ' ' . $formatted;
  143. }
  144. return $formatted . ' ' . $currencyCode;
  145. });
  146. Currency::macro('getEntity', function () {
  147. $currencyCode = $this->getCurrency();
  148. $entity = config("money.currencies.{$currencyCode}.entity");
  149. return $entity ?? $currencyCode;
  150. });
  151. Currency::macro('getCodePrefix', function () {
  152. if ($this->isSymbolFirst()) {
  153. return '';
  154. }
  155. return ' ' . $this->getCurrency();
  156. });
  157. Currency::macro('getCodeSuffix', function () {
  158. if ($this->isSymbolFirst()) {
  159. return ' ' . $this->getCurrency();
  160. }
  161. return '';
  162. });
  163. }
  164. }