選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

CreateAdjustmentSelect.php 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. <?php
  2. namespace App\Filament\Forms\Components;
  3. use App\Enums\Accounting\AdjustmentCategory;
  4. use App\Enums\Accounting\AdjustmentComputation;
  5. use App\Enums\Accounting\AdjustmentScope;
  6. use App\Enums\Accounting\AdjustmentType;
  7. use App\Models\Accounting\Adjustment;
  8. use Filament\Forms\Components\Actions\Action;
  9. use Filament\Forms\Components\Checkbox;
  10. use Filament\Forms\Components\DateTimePicker;
  11. use Filament\Forms\Components\Group;
  12. use Filament\Forms\Components\Select;
  13. use Filament\Forms\Components\Textarea;
  14. use Filament\Forms\Components\TextInput;
  15. use Filament\Forms\Get;
  16. use Filament\Support\Enums\MaxWidth;
  17. use Illuminate\Database\Eloquent\Builder;
  18. use Illuminate\Support\Facades\DB;
  19. class CreateAdjustmentSelect extends Select
  20. {
  21. protected ?AdjustmentCategory $category = null;
  22. protected ?AdjustmentType $type = null;
  23. public function category(AdjustmentCategory $category): static
  24. {
  25. $this->category = $category;
  26. return $this;
  27. }
  28. public function type(AdjustmentType $type): static
  29. {
  30. $this->type = $type;
  31. return $this;
  32. }
  33. public function getCategory(): ?AdjustmentCategory
  34. {
  35. return $this->category;
  36. }
  37. public function getType(): ?AdjustmentType
  38. {
  39. return $this->type;
  40. }
  41. protected function setUp(): void
  42. {
  43. parent::setUp();
  44. $this
  45. ->searchable()
  46. ->preload()
  47. ->createOptionForm($this->createAdjustmentForm())
  48. ->createOptionAction(fn (Action $action) => $this->createAdjustmentAction($action));
  49. $this->relationship(
  50. name: 'adjustments',
  51. titleAttribute: 'name',
  52. modifyQueryUsing: function (Builder $query) {
  53. if ($this->category) {
  54. $query->where('category', $this->category);
  55. }
  56. if ($this->type) {
  57. $query->where('type', $this->type);
  58. }
  59. return $query->orderBy('name');
  60. },
  61. );
  62. $this->createOptionUsing(static function (array $data, CreateAdjustmentSelect $component) {
  63. return DB::transaction(static function () use ($data, $component) {
  64. $category = $data['category'] ?? $component->getCategory();
  65. $type = $data['type'] ?? $component->getType();
  66. $adjustment = Adjustment::create([
  67. 'name' => $data['name'],
  68. 'description' => $data['description'] ?? null,
  69. 'category' => $category,
  70. 'type' => $type,
  71. 'computation' => $data['computation'],
  72. 'rate' => $data['rate'],
  73. 'scope' => $data['scope'] ?? null,
  74. 'recoverable' => $data['recoverable'] ?? false,
  75. 'start_date' => $data['start_date'] ?? null,
  76. 'end_date' => $data['end_date'] ?? null,
  77. ]);
  78. return $adjustment->getKey();
  79. });
  80. });
  81. }
  82. protected function createAdjustmentForm(): array
  83. {
  84. return [
  85. TextInput::make('name')
  86. ->label('Name')
  87. ->required()
  88. ->maxLength(255),
  89. Textarea::make('description')
  90. ->label('Description'),
  91. Select::make('category')
  92. ->label('Category')
  93. ->options(AdjustmentCategory::class)
  94. ->default(AdjustmentCategory::Tax)
  95. ->hidden(fn () => (bool) $this->getCategory())
  96. ->live()
  97. ->required(),
  98. Select::make('type')
  99. ->label('Type')
  100. ->options(AdjustmentType::class)
  101. ->default(AdjustmentType::Sales)
  102. ->hidden(fn () => (bool) $this->getType())
  103. ->live()
  104. ->required(),
  105. Select::make('computation')
  106. ->label('Computation')
  107. ->options(AdjustmentComputation::class)
  108. ->default(AdjustmentComputation::Percentage)
  109. ->live()
  110. ->required(),
  111. TextInput::make('rate')
  112. ->label('Rate')
  113. ->rate(static fn (Get $get) => $get('computation'))
  114. ->required(),
  115. Select::make('scope')
  116. ->label('Scope')
  117. ->options(AdjustmentScope::class),
  118. Checkbox::make('recoverable')
  119. ->label('Recoverable')
  120. ->default(false)
  121. ->helperText('When enabled, tax is tracked separately as claimable from the government. Non-recoverable taxes are treated as part of the expense.')
  122. ->visible(function (Get $get) {
  123. $category = $this->getCategory() ?? AdjustmentCategory::parse($get('category'));
  124. $type = $this->getType() ?? AdjustmentType::parse($get('type'));
  125. return $category->isTax() && $type->isPurchase();
  126. }),
  127. Group::make()
  128. ->schema([
  129. DateTimePicker::make('start_date'),
  130. DateTimePicker::make('end_date')
  131. ->after('start_date'),
  132. ])
  133. ->visible(function (Get $get) {
  134. $category = $this->getCategory() ?? AdjustmentCategory::parse($get('category'));
  135. return $category->isDiscount();
  136. }),
  137. ];
  138. }
  139. protected function createAdjustmentAction(Action $action): Action
  140. {
  141. $categoryLabel = $this->getCategory()?->getLabel() ?? 'Adjustment';
  142. $typeLabel = $this->getType()?->getLabel() ?? '';
  143. $label = trim($typeLabel . ' ' . $categoryLabel);
  144. return $action
  145. ->label('Create ' . $label)
  146. ->slideOver()
  147. ->modalWidth(MaxWidth::ExtraLarge)
  148. ->modalHeading('Create a new ' . strtolower($label));
  149. }
  150. }