您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

CustomerResource.php 9.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. <?php
  2. namespace App\Filament\Resources;
  3. use App\Actions\Banking\CreateCurrencyFromAccount;
  4. use App\Filament\Resources\CustomerResource\Pages;
  5. use App\Filament\Resources\CustomerResource\RelationManagers;
  6. use App\Models\Banking\Account;
  7. use App\Models\Contact;
  8. use Filament\Forms;
  9. use Filament\Resources\Form;
  10. use Filament\Resources\Resource;
  11. use Filament\Resources\Table;
  12. use Filament\Tables;
  13. use Illuminate\Database\Eloquent\Builder;
  14. use Illuminate\Database\Eloquent\SoftDeletingScope;
  15. use Illuminate\Support\Facades\Auth;
  16. use Illuminate\Support\Facades\DB;
  17. class CustomerResource extends Resource
  18. {
  19. protected static ?string $model = Contact::class;
  20. protected static ?string $navigationIcon = 'heroicon-o-collection';
  21. protected static ?string $navigationGroup = 'Sales';
  22. protected static ?string $navigationLabel = 'Customers';
  23. protected static ?string $modelLabel = 'customer';
  24. public static function getEloquentQuery(): Builder
  25. {
  26. return parent::getEloquentQuery()
  27. ->where('type', 'customer')
  28. ->where('company_id', Auth::user()->currentCompany->id);
  29. }
  30. public static function form(Form $form): Form
  31. {
  32. return $form
  33. ->schema([
  34. Forms\Components\Section::make('General')
  35. ->schema([
  36. Forms\Components\Radio::make('entity')
  37. ->options([
  38. 'company' => 'Company',
  39. 'individual' => 'Individual',
  40. ])
  41. ->inline()
  42. ->default('company')
  43. ->required()
  44. ->columnSpanFull(),
  45. Forms\Components\TextInput::make('name')
  46. ->maxLength(100)
  47. ->placeholder('Enter Name')
  48. ->required(),
  49. Forms\Components\TextInput::make('email')
  50. ->email()
  51. ->placeholder('Enter Email')
  52. ->nullable(),
  53. Forms\Components\TextInput::make('phone')
  54. ->label('Phone')
  55. ->tel()
  56. ->placeholder('Enter Phone')
  57. ->maxLength(20),
  58. Forms\Components\TextInput::make('website')
  59. ->maxLength(100)
  60. ->prefix('https://')
  61. ->placeholder('Enter Website')
  62. ->nullable(),
  63. Forms\Components\TextInput::make('reference')
  64. ->maxLength(100)
  65. ->placeholder('Enter Reference')
  66. ->nullable(),
  67. ])->columns(2),
  68. Forms\Components\Section::make('Billing')
  69. ->schema([
  70. Forms\Components\TextInput::make('tax_number')
  71. ->maxLength(100)
  72. ->placeholder('Enter Tax Number')
  73. ->nullable(),
  74. Forms\Components\Select::make('currency_code')
  75. ->label('Currency')
  76. ->relationship('currency', 'name', static fn (Builder $query) => $query->where('company_id', Auth::user()->currentCompany->id))
  77. ->preload()
  78. ->default(Account::getDefaultCurrencyCode())
  79. ->searchable()
  80. ->reactive()
  81. ->required()
  82. ->createOptionForm([
  83. Forms\Components\Select::make('currency.code')
  84. ->label('Code')
  85. ->searchable()
  86. ->options(Account::getCurrencyCodes())
  87. ->reactive()
  88. ->afterStateUpdated(static function (callable $set, $state) {
  89. $code = $state;
  90. $name = config("money.{$code}.name");
  91. $set('currency.name', $name);
  92. })
  93. ->required(),
  94. Forms\Components\TextInput::make('currency.name')
  95. ->label('Name')
  96. ->maxLength(100)
  97. ->required(),
  98. Forms\Components\TextInput::make('currency.rate')
  99. ->label('Rate')
  100. ->numeric()
  101. ->mask(static fn (Forms\Components\TextInput\Mask $mask) => $mask
  102. ->numeric()
  103. ->decimalPlaces(4)
  104. ->signed(false)
  105. ->padFractionalZeros(false)
  106. ->normalizeZeros(false)
  107. ->minValue(0.0001)
  108. ->maxValue(999999.9999)
  109. ->lazyPlaceholder(false))
  110. ->required(),
  111. ])->createOptionAction(static function (Forms\Components\Actions\Action $action) {
  112. return $action
  113. ->label('Add Currency')
  114. ->modalHeading('Add Currency')
  115. ->modalButton('Add')
  116. ->action(static function (array $data) {
  117. return DB::transaction(static function () use ($data) {
  118. $code = $data['currency']['code'];
  119. $name = $data['currency']['name'];
  120. $rate = $data['currency']['rate'];
  121. return (new CreateCurrencyFromAccount())->create($code, $name, $rate);
  122. });
  123. });
  124. }),
  125. ])->columns(2),
  126. Forms\Components\Section::make('Address')
  127. ->schema([
  128. Forms\Components\Textarea::make('address')
  129. ->label('Address')
  130. ->maxLength(100)
  131. ->placeholder('Enter Address')
  132. ->columnSpanFull()
  133. ->nullable(),
  134. Forms\Components\TextInput::make('city')
  135. ->label('Town/City')
  136. ->maxLength(100)
  137. ->placeholder('Enter Town/City')
  138. ->nullable(),
  139. Forms\Components\TextInput::make('zip_code')
  140. ->label('Postal/Zip Code')
  141. ->maxLength(100)
  142. ->placeholder('Enter Postal/Zip Code')
  143. ->nullable(),
  144. Forms\Components\TextInput::make('state')
  145. ->label('Province/State')
  146. ->maxLength(100)
  147. ->placeholder('Enter Province/State')
  148. ->required(),
  149. Forms\Components\TextInput::make('country')
  150. ->label('Country')
  151. ->maxLength(100)
  152. ->placeholder('Enter Country')
  153. ->required(),
  154. ])->columns(2),
  155. ]);
  156. }
  157. public static function table(Table $table): Table
  158. {
  159. return $table
  160. ->columns([
  161. Tables\Columns\TextColumn::make('name')
  162. ->weight('semibold')
  163. ->searchable()
  164. ->sortable(),
  165. Tables\Columns\TextColumn::make('tax_number')
  166. ->searchable()
  167. ->sortable(),
  168. Tables\Columns\TextColumn::make('email')
  169. ->searchable(),
  170. Tables\Columns\TextColumn::make('phone')
  171. ->searchable(),
  172. Tables\Columns\TextColumn::make('country')
  173. ->searchable()
  174. ->sortable(),
  175. Tables\Columns\TextColumn::make('currency.name')
  176. ->searchable()
  177. ->sortable(),
  178. ])
  179. ->filters([
  180. //
  181. ])
  182. ->actions([
  183. Tables\Actions\EditAction::make(),
  184. ])
  185. ->bulkActions([
  186. Tables\Actions\DeleteBulkAction::make(),
  187. ]);
  188. }
  189. public static function getRelations(): array
  190. {
  191. return [
  192. //
  193. ];
  194. }
  195. public static function getPages(): array
  196. {
  197. return [
  198. 'index' => Pages\ListCustomers::route('/'),
  199. 'create' => Pages\CreateCustomer::route('/create'),
  200. 'edit' => Pages\EditCustomer::route('/{record}/edit'),
  201. ];
  202. }
  203. }