Andrew Wallo 5 달 전
부모
커밋
564830a41c

+ 1
- 0
app/Filament/Company/Clusters/Settings/Pages/CompanyProfile.php 파일 보기

201
                 Hidden::make('type')
201
                 Hidden::make('type')
202
                     ->default('general'),
202
                     ->default('general'),
203
                 AddressFields::make()
203
                 AddressFields::make()
204
+                    ->required()
204
                     ->softRequired()
205
                     ->softRequired()
205
                     ->disabledCountry(is_demo_environment()),
206
                     ->disabledCountry(is_demo_environment()),
206
             ])
207
             ])

+ 6
- 6
app/Filament/Company/Resources/Purchases/VendorResource.php 파일 보기

80
                             ]),
80
                             ]),
81
                         CustomSection::make('Primary Contact')
81
                         CustomSection::make('Primary Contact')
82
                             ->relationship('contact')
82
                             ->relationship('contact')
83
+                            ->saveRelationshipsUsing(null)
84
+                            ->saveRelationshipsBeforeChildrenUsing(null)
85
+                            ->dehydrated(true)
83
                             ->contained(false)
86
                             ->contained(false)
84
                             ->schema([
87
                             ->schema([
85
                                 Forms\Components\Hidden::make('is_primary')
88
                                 Forms\Components\Hidden::make('is_primary')
86
                                     ->default(true),
89
                                     ->default(true),
87
                                 Forms\Components\TextInput::make('first_name')
90
                                 Forms\Components\TextInput::make('first_name')
88
                                     ->label('First name')
91
                                     ->label('First name')
89
-                                    ->required()
90
                                     ->maxLength(255),
92
                                     ->maxLength(255),
91
                                 Forms\Components\TextInput::make('last_name')
93
                                 Forms\Components\TextInput::make('last_name')
92
                                     ->label('Last name')
94
                                     ->label('Last name')
93
-                                    ->required()
94
                                     ->maxLength(255),
95
                                     ->maxLength(255),
95
                                 Forms\Components\TextInput::make('email')
96
                                 Forms\Components\TextInput::make('email')
96
                                     ->label('Email')
97
                                     ->label('Email')
97
-                                    ->required()
98
                                     ->email()
98
                                     ->email()
99
                                     ->columnSpanFull()
99
                                     ->columnSpanFull()
100
                                     ->maxLength(255),
100
                                     ->maxLength(255),
110
                                             ->schema([
110
                                             ->schema([
111
                                                 Forms\Components\TextInput::make('number')
111
                                                 Forms\Components\TextInput::make('number')
112
                                                     ->label('Phone')
112
                                                     ->label('Phone')
113
-                                                    ->required()
114
                                                     ->maxLength(15),
113
                                                     ->maxLength(15),
115
                                             ])->maxItems(1),
114
                                             ])->maxItems(1),
116
                                         Forms\Components\Builder\Block::make('mobile')
115
                                         Forms\Components\Builder\Block::make('mobile')
117
                                             ->schema([
116
                                             ->schema([
118
                                                 Forms\Components\TextInput::make('number')
117
                                                 Forms\Components\TextInput::make('number')
119
                                                     ->label('Mobile')
118
                                                     ->label('Mobile')
120
-                                                    ->required()
121
                                                     ->maxLength(15),
119
                                                     ->maxLength(15),
122
                                             ])->maxItems(1),
120
                                             ])->maxItems(1),
123
                                         Forms\Components\Builder\Block::make('toll_free')
121
                                         Forms\Components\Builder\Block::make('toll_free')
124
                                             ->schema([
122
                                             ->schema([
125
                                                 Forms\Components\TextInput::make('number')
123
                                                 Forms\Components\TextInput::make('number')
126
                                                     ->label('Toll free')
124
                                                     ->label('Toll free')
127
-                                                    ->required()
128
                                                     ->maxLength(15),
125
                                                     ->maxLength(15),
129
                                             ])->maxItems(1),
126
                                             ])->maxItems(1),
130
                                         Forms\Components\Builder\Block::make('fax')
127
                                         Forms\Components\Builder\Block::make('fax')
143
                     ])->columns(1),
140
                     ])->columns(1),
144
                 Forms\Components\Section::make('Address Information')
141
                 Forms\Components\Section::make('Address Information')
145
                     ->relationship('address')
142
                     ->relationship('address')
143
+                    ->saveRelationshipsUsing(null)
144
+                    ->saveRelationshipsBeforeChildrenUsing(null)
145
+                    ->dehydrated(true)
146
                     ->schema([
146
                     ->schema([
147
                         Forms\Components\Hidden::make('type')
147
                         Forms\Components\Hidden::make('type')
148
                             ->default('general'),
148
                             ->default('general'),

+ 32
- 0
app/Filament/Company/Resources/Purchases/VendorResource/Pages/CreateVendor.php 파일 보기

4
 
4
 
5
 use App\Concerns\HandlePageRedirect;
5
 use App\Concerns\HandlePageRedirect;
6
 use App\Filament\Company\Resources\Purchases\VendorResource;
6
 use App\Filament\Company\Resources\Purchases\VendorResource;
7
+use App\Models\Common\Vendor;
7
 use Filament\Resources\Pages\CreateRecord;
8
 use Filament\Resources\Pages\CreateRecord;
8
 use Filament\Support\Enums\MaxWidth;
9
 use Filament\Support\Enums\MaxWidth;
10
+use Illuminate\Database\Eloquent\Model;
9
 
11
 
10
 class CreateVendor extends CreateRecord
12
 class CreateVendor extends CreateRecord
11
 {
13
 {
13
 
15
 
14
     protected static string $resource = VendorResource::class;
16
     protected static string $resource = VendorResource::class;
15
 
17
 
18
+    protected function handleRecordCreation(array $data): Model
19
+    {
20
+        /** @var Vendor $vendor */
21
+        $vendor = parent::handleRecordCreation($data);
22
+
23
+        if (isset($data['contact'], $data['contact']['first_name'])) {
24
+            $vendor->contact()->create([
25
+                'is_primary' => true,
26
+                'first_name' => $data['contact']['first_name'],
27
+                'last_name' => $data['contact']['last_name'],
28
+                'email' => $data['contact']['email'],
29
+                'phones' => $data['contact']['phones'] ?? [],
30
+            ]);
31
+        }
32
+
33
+        if (isset($data['address'], $data['address']['type'], $data['address']['address_line_1'])) {
34
+            $vendor->address()->create([
35
+                'type' => $data['address']['type'],
36
+                'address_line_1' => $data['address']['address_line_1'],
37
+                'address_line_2' => $data['address']['address_line_2'] ?? null,
38
+                'country_code' => $data['address']['country_code'] ?? null,
39
+                'state_id' => $data['address']['state_id'] ?? null,
40
+                'city' => $data['address']['city'] ?? null,
41
+                'postal_code' => $data['address']['postal_code'] ?? null,
42
+            ]);
43
+        }
44
+
45
+        return $vendor;
46
+    }
47
+
16
     public function getMaxContentWidth(): MaxWidth | string | null
48
     public function getMaxContentWidth(): MaxWidth | string | null
17
     {
49
     {
18
         return MaxWidth::FiveExtraLarge;
50
         return MaxWidth::FiveExtraLarge;

+ 36
- 0
app/Filament/Company/Resources/Purchases/VendorResource/Pages/EditVendor.php 파일 보기

4
 
4
 
5
 use App\Concerns\HandlePageRedirect;
5
 use App\Concerns\HandlePageRedirect;
6
 use App\Filament\Company\Resources\Purchases\VendorResource;
6
 use App\Filament\Company\Resources\Purchases\VendorResource;
7
+use App\Models\Common\Vendor;
7
 use Filament\Actions;
8
 use Filament\Actions;
8
 use Filament\Resources\Pages\EditRecord;
9
 use Filament\Resources\Pages\EditRecord;
9
 use Filament\Support\Enums\MaxWidth;
10
 use Filament\Support\Enums\MaxWidth;
11
+use Illuminate\Database\Eloquent\Model;
10
 
12
 
11
 class EditVendor extends EditRecord
13
 class EditVendor extends EditRecord
12
 {
14
 {
14
 
16
 
15
     protected static string $resource = VendorResource::class;
17
     protected static string $resource = VendorResource::class;
16
 
18
 
19
+    protected function handleRecordUpdate(Model $record, array $data): Model
20
+    {
21
+        /** @var Vendor $vendor */
22
+        $vendor = parent::handleRecordUpdate($record, $data);
23
+
24
+        if (isset($data['contact'], $data['contact']['first_name'])) {
25
+            $vendor->contact()->updateOrCreate(
26
+                ['is_primary' => true],
27
+                [
28
+                    'first_name' => $data['contact']['first_name'],
29
+                    'last_name' => $data['contact']['last_name'],
30
+                    'email' => $data['contact']['email'],
31
+                    'phones' => $data['contact']['phones'] ?? [],
32
+                ]
33
+            );
34
+        }
35
+
36
+        if (isset($data['address'], $data['address']['type'], $data['address']['address_line_1'])) {
37
+            $vendor->address()->updateOrCreate(
38
+                ['type' => $data['address']['type']],
39
+                [
40
+                    'address_line_1' => $data['address']['address_line_1'],
41
+                    'address_line_2' => $data['address']['address_line_2'] ?? null,
42
+                    'country_code' => $data['address']['country_code'] ?? null,
43
+                    'state_id' => $data['address']['state_id'] ?? null,
44
+                    'city' => $data['address']['city'] ?? null,
45
+                    'postal_code' => $data['address']['postal_code'] ?? null,
46
+                ]
47
+            );
48
+        }
49
+
50
+        return $vendor;
51
+    }
52
+
17
     protected function getHeaderActions(): array
53
     protected function getHeaderActions(): array
18
     {
54
     {
19
         return [
55
         return [

+ 11
- 13
app/Filament/Company/Resources/Sales/ClientResource.php 파일 보기

47
                             ]),
47
                             ]),
48
                         CustomSection::make('Primary Contact')
48
                         CustomSection::make('Primary Contact')
49
                             ->relationship('primaryContact')
49
                             ->relationship('primaryContact')
50
+                            ->saveRelationshipsUsing(null)
51
+                            ->saveRelationshipsBeforeChildrenUsing(null)
52
+                            ->dehydrated(true)
50
                             ->contained(false)
53
                             ->contained(false)
51
                             ->schema([
54
                             ->schema([
52
                                 Forms\Components\Hidden::make('is_primary')
55
                                 Forms\Components\Hidden::make('is_primary')
53
                                     ->default(true),
56
                                     ->default(true),
54
                                 Forms\Components\TextInput::make('first_name')
57
                                 Forms\Components\TextInput::make('first_name')
55
                                     ->label('First name')
58
                                     ->label('First name')
56
-                                    ->required()
57
                                     ->maxLength(255),
59
                                     ->maxLength(255),
58
                                 Forms\Components\TextInput::make('last_name')
60
                                 Forms\Components\TextInput::make('last_name')
59
                                     ->label('Last name')
61
                                     ->label('Last name')
60
-                                    ->required()
61
                                     ->maxLength(255),
62
                                     ->maxLength(255),
62
                                 Forms\Components\TextInput::make('email')
63
                                 Forms\Components\TextInput::make('email')
63
                                     ->label('Email')
64
                                     ->label('Email')
64
-                                    ->required()
65
                                     ->email()
65
                                     ->email()
66
                                     ->columnSpanFull()
66
                                     ->columnSpanFull()
67
                                     ->maxLength(255),
67
                                     ->maxLength(255),
77
                                             ->schema([
77
                                             ->schema([
78
                                                 Forms\Components\TextInput::make('number')
78
                                                 Forms\Components\TextInput::make('number')
79
                                                     ->label('Phone')
79
                                                     ->label('Phone')
80
-                                                    ->required()
81
                                                     ->maxLength(15),
80
                                                     ->maxLength(15),
82
                                             ])->maxItems(1),
81
                                             ])->maxItems(1),
83
                                         Forms\Components\Builder\Block::make('mobile')
82
                                         Forms\Components\Builder\Block::make('mobile')
84
                                             ->schema([
83
                                             ->schema([
85
                                                 Forms\Components\TextInput::make('number')
84
                                                 Forms\Components\TextInput::make('number')
86
                                                     ->label('Mobile')
85
                                                     ->label('Mobile')
87
-                                                    ->required()
88
                                                     ->maxLength(15),
86
                                                     ->maxLength(15),
89
                                             ])->maxItems(1),
87
                                             ])->maxItems(1),
90
                                         Forms\Components\Builder\Block::make('toll_free')
88
                                         Forms\Components\Builder\Block::make('toll_free')
91
                                             ->schema([
89
                                             ->schema([
92
                                                 Forms\Components\TextInput::make('number')
90
                                                 Forms\Components\TextInput::make('number')
93
                                                     ->label('Toll free')
91
                                                     ->label('Toll free')
94
-                                                    ->required()
95
                                                     ->maxLength(15),
92
                                                     ->maxLength(15),
96
                                             ])->maxItems(1),
93
                                             ])->maxItems(1),
97
                                         Forms\Components\Builder\Block::make('fax')
94
                                         Forms\Components\Builder\Block::make('fax')
109
                             ])->columns(),
106
                             ])->columns(),
110
                         Forms\Components\Repeater::make('secondaryContacts')
107
                         Forms\Components\Repeater::make('secondaryContacts')
111
                             ->relationship()
108
                             ->relationship()
109
+                            ->saveRelationshipsUsing(null)
110
+                            ->saveRelationshipsBeforeChildrenUsing(null)
111
+                            ->dehydrated(true)
112
                             ->hiddenLabel()
112
                             ->hiddenLabel()
113
                             ->extraAttributes([
113
                             ->extraAttributes([
114
                                 'class' => 'uncontained',
114
                                 'class' => 'uncontained',
138
                             ->schema([
138
                             ->schema([
139
                                 Forms\Components\TextInput::make('first_name')
139
                                 Forms\Components\TextInput::make('first_name')
140
                                     ->label('First name')
140
                                     ->label('First name')
141
-                                    ->required()
142
                                     ->live(onBlur: true)
141
                                     ->live(onBlur: true)
143
                                     ->maxLength(255),
142
                                     ->maxLength(255),
144
                                 Forms\Components\TextInput::make('last_name')
143
                                 Forms\Components\TextInput::make('last_name')
145
                                     ->label('Last name')
144
                                     ->label('Last name')
146
-                                    ->required()
147
                                     ->live(onBlur: true)
145
                                     ->live(onBlur: true)
148
                                     ->maxLength(255),
146
                                     ->maxLength(255),
149
                                 Forms\Components\TextInput::make('email')
147
                                 Forms\Components\TextInput::make('email')
150
                                     ->label('Email')
148
                                     ->label('Email')
151
-                                    ->required()
152
                                     ->email()
149
                                     ->email()
153
                                     ->maxLength(255),
150
                                     ->maxLength(255),
154
                                 PhoneBuilder::make('phones')
151
                                 PhoneBuilder::make('phones')
162
                                             ->schema([
159
                                             ->schema([
163
                                                 Forms\Components\TextInput::make('number')
160
                                                 Forms\Components\TextInput::make('number')
164
                                                     ->label('Phone')
161
                                                     ->label('Phone')
165
-                                                    ->required()
166
                                                     ->maxLength(255),
162
                                                     ->maxLength(255),
167
                                             ])->maxItems(1),
163
                                             ])->maxItems(1),
168
                                     ])
164
                                     ])
174
                     ])->columns(1),
170
                     ])->columns(1),
175
                 Forms\Components\Section::make('Billing')
171
                 Forms\Components\Section::make('Billing')
176
                     ->schema([
172
                     ->schema([
177
-                        CreateCurrencySelect::make('currency_code'),
173
+                        CreateCurrencySelect::make('currency_code')
174
+                            ->required(false)
175
+                            ->selectablePlaceholder(false),
178
                         CustomSection::make('Billing Address')
176
                         CustomSection::make('Billing Address')
179
                             ->relationship('billingAddress')
177
                             ->relationship('billingAddress')
180
                             ->saveRelationshipsUsing(null)
178
                             ->saveRelationshipsUsing(null)
179
+                            ->saveRelationshipsBeforeChildrenUsing(null)
181
                             ->dehydrated(true)
180
                             ->dehydrated(true)
182
                             ->contained(false)
181
                             ->contained(false)
183
                             ->schema([
182
                             ->schema([
190
                 Forms\Components\Section::make('Shipping')
189
                 Forms\Components\Section::make('Shipping')
191
                     ->relationship('shippingAddress')
190
                     ->relationship('shippingAddress')
192
                     ->saveRelationshipsUsing(null)
191
                     ->saveRelationshipsUsing(null)
192
+                    ->saveRelationshipsBeforeChildrenUsing(null)
193
                     ->dehydrated(true)
193
                     ->dehydrated(true)
194
                     ->schema([
194
                     ->schema([
195
                         Forms\Components\Hidden::make('type')
195
                         Forms\Components\Hidden::make('type')
196
                             ->default('shipping'),
196
                             ->default('shipping'),
197
                         Forms\Components\TextInput::make('recipient')
197
                         Forms\Components\TextInput::make('recipient')
198
                             ->label('Recipient')
198
                             ->label('Recipient')
199
-                            ->required()
200
                             ->maxLength(255),
199
                             ->maxLength(255),
201
                         Forms\Components\TextInput::make('phone')
200
                         Forms\Components\TextInput::make('phone')
202
                             ->label('Phone')
201
                             ->label('Phone')
203
-                            ->required()
204
                             ->maxLength(255),
202
                             ->maxLength(255),
205
                         CustomSection::make('Shipping Address')
203
                         CustomSection::make('Shipping Address')
206
                             ->contained(false)
204
                             ->contained(false)

+ 67
- 36
app/Filament/Company/Resources/Sales/ClientResource/Pages/CreateClient.php 파일 보기

5
 use App\Concerns\HandlePageRedirect;
5
 use App\Concerns\HandlePageRedirect;
6
 use App\Enums\Common\AddressType;
6
 use App\Enums\Common\AddressType;
7
 use App\Filament\Company\Resources\Sales\ClientResource;
7
 use App\Filament\Company\Resources\Sales\ClientResource;
8
-use App\Models\Common\Address;
9
 use App\Models\Common\Client;
8
 use App\Models\Common\Client;
10
 use Filament\Resources\Pages\CreateRecord;
9
 use Filament\Resources\Pages\CreateRecord;
11
 use Filament\Support\Enums\MaxWidth;
10
 use Filament\Support\Enums\MaxWidth;
27
         /** @var Client $record */
26
         /** @var Client $record */
28
         $record = parent::handleRecordCreation($data);
27
         $record = parent::handleRecordCreation($data);
29
 
28
 
30
-        // Create billing address first
31
-        /** @var Address $billingAddress */
32
-        $billingAddress = $record->addresses()->create([
33
-            ...$data['billingAddress'],
34
-            'type' => AddressType::Billing,
35
-        ]);
29
+        if (isset($data['primaryContact'], $data['primaryContact']['first_name'])) {
30
+            $record->primaryContact()->create([
31
+                'is_primary' => true,
32
+                'first_name' => $data['primaryContact']['first_name'],
33
+                'last_name' => $data['primaryContact']['last_name'],
34
+                'email' => $data['primaryContact']['email'],
35
+                'phones' => $data['primaryContact']['phones'] ?? [],
36
+            ]);
37
+        }
36
 
38
 
37
-        // Create shipping address with reference to billing if needed
38
-        $shippingData = $data['shippingAddress'];
39
+        if (isset($data['secondaryContacts'])) {
40
+            foreach ($data['secondaryContacts'] as $contactData) {
41
+                if (isset($contactData['first_name'])) {
42
+                    $record->secondaryContacts()->create([
43
+                        'is_primary' => false,
44
+                        'first_name' => $contactData['first_name'],
45
+                        'last_name' => $contactData['last_name'],
46
+                        'email' => $contactData['email'],
47
+                        'phones' => $contactData['phones'] ?? [],
48
+                    ]);
49
+                }
50
+            }
51
+        }
39
 
52
 
40
-        $shippingAddress = [
41
-            'type' => AddressType::Shipping,
42
-            'recipient' => $shippingData['recipient'],
43
-            'phone' => $shippingData['phone'],
44
-            'notes' => $shippingData['notes'],
45
-        ];
53
+        if (isset($data['billingAddress'], $data['billingAddress']['address_line_1'])) {
54
+            $record->billingAddress()->create([
55
+                'type' => AddressType::Billing,
56
+                'address_line_1' => $data['billingAddress']['address_line_1'],
57
+                'address_line_2' => $data['billingAddress']['address_line_2'] ?? null,
58
+                'country_code' => $data['billingAddress']['country_code'] ?? null,
59
+                'state_id' => $data['billingAddress']['state_id'] ?? null,
60
+                'city' => $data['billingAddress']['city'] ?? null,
61
+                'postal_code' => $data['billingAddress']['postal_code'] ?? null,
62
+            ]);
63
+        }
46
 
64
 
47
-        if ($shippingData['same_as_billing']) {
65
+        if (isset($data['shippingAddress'])) {
66
+            $shippingData = $data['shippingAddress'];
48
             $shippingAddress = [
67
             $shippingAddress = [
49
-                ...$shippingAddress,
50
-                'parent_address_id' => $billingAddress->id,
51
-                'address_line_1' => $billingAddress->address_line_1,
52
-                'address_line_2' => $billingAddress->address_line_2,
53
-                'country_code' => $billingAddress->country_code,
54
-                'state_id' => $billingAddress->state_id,
55
-                'city' => $billingAddress->city,
56
-                'postal_code' => $billingAddress->postal_code,
68
+                'type' => AddressType::Shipping,
69
+                'recipient' => $shippingData['recipient'] ?? null,
70
+                'phone' => $shippingData['phone'] ?? null,
71
+                'notes' => $shippingData['notes'] ?? null,
57
             ];
72
             ];
58
-        } else {
59
-            $shippingAddress = [
60
-                ...$shippingAddress,
61
-                'address_line_1' => $shippingData['address_line_1'],
62
-                'address_line_2' => $shippingData['address_line_2'],
63
-                'country_code' => $shippingData['country_code'],
64
-                'state_id' => $shippingData['state_id'],
65
-                'city' => $shippingData['city'],
66
-                'postal_code' => $shippingData['postal_code'],
67
-            ];
68
-        }
69
 
73
 
70
-        $record->addresses()->create($shippingAddress);
74
+            if ($shippingData['same_as_billing'] ?? false) {
75
+                $billingAddress = $record->billingAddress;
76
+                if ($billingAddress) {
77
+                    $shippingAddress = [
78
+                        ...$shippingAddress,
79
+                        'parent_address_id' => $billingAddress->id,
80
+                        'address_line_1' => $billingAddress->address_line_1,
81
+                        'address_line_2' => $billingAddress->address_line_2,
82
+                        'country_code' => $billingAddress->country_code,
83
+                        'state_id' => $billingAddress->state_id,
84
+                        'city' => $billingAddress->city,
85
+                        'postal_code' => $billingAddress->postal_code,
86
+                    ];
87
+                    $record->shippingAddress()->create($shippingAddress);
88
+                }
89
+            } elseif (isset($shippingData['address_line_1'])) {
90
+                $shippingAddress = [
91
+                    ...$shippingAddress,
92
+                    'address_line_1' => $shippingData['address_line_1'],
93
+                    'address_line_2' => $shippingData['address_line_2'] ?? null,
94
+                    'country_code' => $shippingData['country_code'] ?? null,
95
+                    'state_id' => $shippingData['state_id'] ?? null,
96
+                    'city' => $shippingData['city'] ?? null,
97
+                    'postal_code' => $shippingData['postal_code'] ?? null,
98
+                ];
99
+                $record->shippingAddress()->create($shippingAddress);
100
+            }
101
+        }
71
 
102
 
72
         return $record;
103
         return $record;
73
     }
104
     }

+ 85
- 34
app/Filament/Company/Resources/Sales/ClientResource/Pages/EditClient.php 파일 보기

3
 namespace App\Filament\Company\Resources\Sales\ClientResource\Pages;
3
 namespace App\Filament\Company\Resources\Sales\ClientResource\Pages;
4
 
4
 
5
 use App\Concerns\HandlePageRedirect;
5
 use App\Concerns\HandlePageRedirect;
6
+use App\Enums\Common\AddressType;
6
 use App\Filament\Company\Resources\Sales\ClientResource;
7
 use App\Filament\Company\Resources\Sales\ClientResource;
7
 use App\Models\Common\Client;
8
 use App\Models\Common\Client;
8
 use Filament\Actions;
9
 use Filament\Actions;
33
         /** @var Client $record */
34
         /** @var Client $record */
34
         $record = parent::handleRecordUpdate($record, $data);
35
         $record = parent::handleRecordUpdate($record, $data);
35
 
36
 
36
-        // Update billing address
37
-        $billingAddress = $record->billingAddress;
38
-        $billingAddress->update($data['billingAddress']);
37
+        if (isset($data['primaryContact'], $data['primaryContact']['first_name'])) {
38
+            $record->primaryContact()->updateOrCreate(
39
+                ['is_primary' => true],
40
+                [
41
+                    'first_name' => $data['primaryContact']['first_name'],
42
+                    'last_name' => $data['primaryContact']['last_name'],
43
+                    'email' => $data['primaryContact']['email'],
44
+                    'phones' => $data['primaryContact']['phones'] ?? [],
45
+                ]
46
+            );
47
+        }
39
 
48
 
40
-        // Update shipping address
41
-        $shippingAddress = $record->shippingAddress;
42
-        $shippingData = $data['shippingAddress'];
49
+        if (isset($data['secondaryContacts'])) {
50
+            // Delete removed contacts
51
+            $existingIds = collect($data['secondaryContacts'])->pluck('id')->filter()->all();
52
+            $record->secondaryContacts()->whereNotIn('id', $existingIds)->delete();
43
 
53
 
44
-        $shippingUpdateData = [
45
-            'recipient' => $shippingData['recipient'],
46
-            'phone' => $shippingData['phone'],
47
-            'notes' => $shippingData['notes'],
48
-        ];
54
+            // Update or create contacts
55
+            foreach ($data['secondaryContacts'] as $contactData) {
56
+                if (isset($contactData['first_name'])) {
57
+                    $record->secondaryContacts()->updateOrCreate(
58
+                        ['id' => $contactData['id'] ?? null],
59
+                        [
60
+                            'is_primary' => false,
61
+                            'first_name' => $contactData['first_name'],
62
+                            'last_name' => $contactData['last_name'],
63
+                            'email' => $contactData['email'],
64
+                            'phones' => $contactData['phones'] ?? [],
65
+                        ]
66
+                    );
67
+                }
68
+            }
69
+        }
49
 
70
 
50
-        if ($shippingData['same_as_billing']) {
51
-            $shippingUpdateData = [
52
-                ...$shippingUpdateData,
53
-                'parent_address_id' => $billingAddress->id,
54
-                'address_line_1' => $billingAddress->address_line_1,
55
-                'address_line_2' => $billingAddress->address_line_2,
56
-                'country_code' => $billingAddress->country_code,
57
-                'state_id' => $billingAddress->state_id,
58
-                'city' => $billingAddress->city,
59
-                'postal_code' => $billingAddress->postal_code,
60
-            ];
61
-        } else {
62
-            $shippingUpdateData = [
63
-                ...$shippingUpdateData,
64
-                'parent_address_id' => null,
65
-                'address_line_1' => $shippingData['address_line_1'],
66
-                'address_line_2' => $shippingData['address_line_2'],
67
-                'country_code' => $shippingData['country_code'],
68
-                'state_id' => $shippingData['state_id'],
69
-                'city' => $shippingData['city'],
70
-                'postal_code' => $shippingData['postal_code'],
71
-            ];
71
+        if (isset($data['billingAddress'], $data['billingAddress']['address_line_1'])) {
72
+            $record->billingAddress()->updateOrCreate(
73
+                ['type' => AddressType::Billing],
74
+                [
75
+                    'address_line_1' => $data['billingAddress']['address_line_1'],
76
+                    'address_line_2' => $data['billingAddress']['address_line_2'] ?? null,
77
+                    'country_code' => $data['billingAddress']['country_code'] ?? null,
78
+                    'state_id' => $data['billingAddress']['state_id'] ?? null,
79
+                    'city' => $data['billingAddress']['city'] ?? null,
80
+                    'postal_code' => $data['billingAddress']['postal_code'] ?? null,
81
+                ]
82
+            );
72
         }
83
         }
73
 
84
 
74
-        $shippingAddress->update($shippingUpdateData);
85
+        if (isset($data['shippingAddress'])) {
86
+            $shippingData = $data['shippingAddress'];
87
+            $shippingAddress = [
88
+                'type' => AddressType::Shipping,
89
+                'recipient' => $shippingData['recipient'] ?? null,
90
+                'phone' => $shippingData['phone'] ?? null,
91
+                'notes' => $shippingData['notes'] ?? null,
92
+            ];
93
+
94
+            if ($shippingData['same_as_billing'] ?? false) {
95
+                $billingAddress = $record->billingAddress;
96
+                if ($billingAddress) {
97
+                    $shippingAddress = [
98
+                        ...$shippingAddress,
99
+                        'parent_address_id' => $billingAddress->id,
100
+                        'address_line_1' => $billingAddress->address_line_1,
101
+                        'address_line_2' => $billingAddress->address_line_2,
102
+                        'country_code' => $billingAddress->country_code,
103
+                        'state_id' => $billingAddress->state_id,
104
+                        'city' => $billingAddress->city,
105
+                        'postal_code' => $billingAddress->postal_code,
106
+                    ];
107
+                }
108
+            } elseif (isset($shippingData['address_line_1'])) {
109
+                $shippingAddress = [
110
+                    ...$shippingAddress,
111
+                    'parent_address_id' => null,
112
+                    'address_line_1' => $shippingData['address_line_1'],
113
+                    'address_line_2' => $shippingData['address_line_2'] ?? null,
114
+                    'country_code' => $shippingData['country_code'] ?? null,
115
+                    'state_id' => $shippingData['state_id'] ?? null,
116
+                    'city' => $shippingData['city'] ?? null,
117
+                    'postal_code' => $shippingData['postal_code'] ?? null,
118
+                ];
119
+            }
120
+
121
+            $record->shippingAddress()->updateOrCreate(
122
+                ['type' => AddressType::Shipping],
123
+                $shippingAddress
124
+            );
125
+        }
75
 
126
 
76
         return $record;
127
         return $record;
77
     }
128
     }

+ 3
- 4
app/Filament/Company/Resources/Sales/InvoiceResource.php 파일 보기

15
 use App\Filament\Company\Resources\Sales\InvoiceResource\Pages;
15
 use App\Filament\Company\Resources\Sales\InvoiceResource\Pages;
16
 use App\Filament\Company\Resources\Sales\InvoiceResource\Widgets;
16
 use App\Filament\Company\Resources\Sales\InvoiceResource\Widgets;
17
 use App\Filament\Forms\Components\CreateAdjustmentSelect;
17
 use App\Filament\Forms\Components\CreateAdjustmentSelect;
18
+use App\Filament\Forms\Components\CreateClientSelect;
18
 use App\Filament\Forms\Components\CreateCurrencySelect;
19
 use App\Filament\Forms\Components\CreateCurrencySelect;
19
 use App\Filament\Forms\Components\DocumentFooterSection;
20
 use App\Filament\Forms\Components\DocumentFooterSection;
20
 use App\Filament\Forms\Components\DocumentHeaderSection;
21
 use App\Filament\Forms\Components\DocumentHeaderSection;
67
                     ->schema([
68
                     ->schema([
68
                         Forms\Components\Split::make([
69
                         Forms\Components\Split::make([
69
                             Forms\Components\Group::make([
70
                             Forms\Components\Group::make([
70
-                                Forms\Components\Select::make('client_id')
71
-                                    ->relationship('client', 'name')
72
-                                    ->preload()
73
-                                    ->searchable()
71
+                                CreateClientSelect::make('client_id')
72
+                                    ->label('Client')
74
                                     ->required()
73
                                     ->required()
75
                                     ->live()
74
                                     ->live()
76
                                     ->afterStateUpdated(function (Forms\Set $set, Forms\Get $get, $state) {
75
                                     ->afterStateUpdated(function (Forms\Set $set, Forms\Get $get, $state) {

+ 17
- 3
app/Filament/Forms/Components/AddressFields.php 파일 보기

13
 
13
 
14
     protected bool | Closure $isCountryDisabled = false;
14
     protected bool | Closure $isCountryDisabled = false;
15
 
15
 
16
+    protected bool | Closure $isRequired = false;
17
+
16
     protected function setUp(): void
18
     protected function setUp(): void
17
     {
19
     {
18
         parent::setUp();
20
         parent::setUp();
20
         $this->schema([
22
         $this->schema([
21
             TextInput::make('address_line_1')
23
             TextInput::make('address_line_1')
22
                 ->label('Address line 1')
24
                 ->label('Address line 1')
23
-                ->required()
25
+                ->required(fn () => $this->isRequired())
24
                 ->maxLength(255),
26
                 ->maxLength(255),
25
             TextInput::make('address_line_2')
27
             TextInput::make('address_line_2')
26
                 ->label('Address line 2')
28
                 ->label('Address line 2')
28
             CountrySelect::make('country_code')
30
             CountrySelect::make('country_code')
29
                 ->disabled(fn () => $this->isCountryDisabled())
31
                 ->disabled(fn () => $this->isCountryDisabled())
30
                 ->clearStateField()
32
                 ->clearStateField()
31
-                ->required(),
33
+                ->required(fn () => $this->isRequired()),
32
             StateSelect::make('state_id'),
34
             StateSelect::make('state_id'),
33
             TextInput::make('city')
35
             TextInput::make('city')
34
                 ->label('City')
36
                 ->label('City')
35
-                ->required()
37
+                ->required(fn () => $this->isRequired())
36
                 ->maxLength(255),
38
                 ->maxLength(255),
37
             TextInput::make('postal_code')
39
             TextInput::make('postal_code')
38
                 ->label('Postal code')
40
                 ->label('Postal code')
60
         }
62
         }
61
     }
63
     }
62
 
64
 
65
+    public function required(bool | Closure $condition = true): static
66
+    {
67
+        $this->isRequired = $condition;
68
+
69
+        return $this;
70
+    }
71
+
72
+    public function isRequired(): bool
73
+    {
74
+        return (bool) $this->evaluate($this->isRequired);
75
+    }
76
+
63
     public function disabledCountry(bool | Closure $condition = true): static
77
     public function disabledCountry(bool | Closure $condition = true): static
64
     {
78
     {
65
         $this->isCountryDisabled = $condition;
79
         $this->isCountryDisabled = $condition;

+ 82
- 0
app/Filament/Forms/Components/CreateClientSelect.php 파일 보기

1
+<?php
2
+
3
+namespace App\Filament\Forms\Components;
4
+
5
+use App\Filament\Company\Resources\Sales\ClientResource;
6
+use App\Models\Common\Address;
7
+use App\Models\Common\Client;
8
+use App\Models\Common\Contact;
9
+use Filament\Forms\Components\Actions\Action;
10
+use Filament\Forms\Components\Select;
11
+use Filament\Forms\Form;
12
+use Filament\Support\Enums\MaxWidth;
13
+use Illuminate\Support\Facades\DB;
14
+
15
+class CreateClientSelect extends Select
16
+{
17
+    protected function setUp(): void
18
+    {
19
+        parent::setUp();
20
+
21
+        $this
22
+            ->searchable()
23
+            ->preload()
24
+            ->createOptionForm(fn (Form $form) => $this->createClientForm($form))
25
+            ->createOptionAction(fn (Action $action) => $this->createClientAction($action));
26
+
27
+        $this->relationship('client', 'name');
28
+
29
+        $this->createOptionUsing(static function (array $data) {
30
+            return DB::transaction(static function () use ($data) {
31
+                $client = Client::create([
32
+                    'name' => $data['name'],
33
+                    'website' => $data['website'] ?? null,
34
+                    'notes' => $data['notes'] ?? null,
35
+                ]);
36
+
37
+                // Create primary contact
38
+                $primaryContact = $client->contacts()->create([
39
+                    'first_name' => $data['primary_contact']['first_name'],
40
+                    'last_name' => $data['primary_contact']['last_name'],
41
+                    'email' => $data['primary_contact']['email'],
42
+                    'is_primary' => true,
43
+                ]);
44
+
45
+                // Add phone number
46
+                $primaryContact->phones()->create([
47
+                    'type' => 'primary',
48
+                    'number' => $data['primary_contact']['phones'][0]['number'],
49
+                ]);
50
+
51
+                // Create billing address
52
+                $client->addresses()->create([
53
+                    'type' => 'billing',
54
+                    ...$data['billing_address'],
55
+                ]);
56
+
57
+                // Create shipping address
58
+                $client->addresses()->create([
59
+                    'type' => 'shipping',
60
+                    'recipient' => $data['shipping_address']['recipient'],
61
+                    'phone' => $data['shipping_address']['phone'],
62
+                    ...$data['shipping_address'],
63
+                ]);
64
+
65
+                return $client->getKey();
66
+            });
67
+        });
68
+    }
69
+
70
+    protected function createClientForm(Form $form): Form
71
+    {
72
+        return ClientResource::form($form);
73
+    }
74
+
75
+    protected function createClientAction(Action $action): Action
76
+    {
77
+        return $action
78
+            ->label('Add client')
79
+            ->slideOver()
80
+            ->modalWidth(MaxWidth::ThreeExtraLarge);
81
+    }
82
+}

Loading…
취소
저장