Andrew Wallo 6 月之前
父節點
當前提交
45f6eeafbb

+ 75
- 80
app/Filament/Company/Resources/Accounting/BudgetResource/RelationManagers/BudgetItemsRelationManager.php 查看文件

19
 use Filament\Tables\Table;
19
 use Filament\Tables\Table;
20
 use Illuminate\Database\Eloquent\Builder;
20
 use Illuminate\Database\Eloquent\Builder;
21
 use Illuminate\Database\Eloquent\Collection;
21
 use Illuminate\Database\Eloquent\Collection;
22
-use Illuminate\Support\Str;
22
+use Illuminate\Support\Carbon;
23
+use Illuminate\Support\Facades\DB;
24
+use stdClass;
23
 
25
 
24
 class BudgetItemsRelationManager extends RelationManager
26
 class BudgetItemsRelationManager extends RelationManager
25
 {
27
 {
27
 
29
 
28
     protected static bool $isLazy = false;
30
     protected static bool $isLazy = false;
29
 
31
 
30
-    protected const AMOUNT_PREFIX = 'amount_';
31
-
32
     protected const TOTAL_COLUMN = 'total';
32
     protected const TOTAL_COLUMN = 'total';
33
 
33
 
34
     public array $batchChanges = [];
34
     public array $batchChanges = [];
36
     /**
36
     /**
37
      * Generate a consistent key for the budget item and period
37
      * Generate a consistent key for the budget item and period
38
      */
38
      */
39
-    protected static function generatePeriodKey(int $recordId, string $period): string
39
+    protected static function generatePeriodKey(int $recordId, string | Carbon $startDate): string
40
     {
40
     {
41
-        return "{$recordId}." . self::AMOUNT_PREFIX . Str::snake($period);
41
+        $formattedDate = $startDate instanceof Carbon
42
+            ? $startDate->format('Y_m_d')
43
+            : Carbon::parse($startDate)->format('Y_m_d');
44
+
45
+        return "{$recordId}.{$formattedDate}";
42
     }
46
     }
43
 
47
 
44
     /**
48
     /**
49
         return "{$recordId}." . self::TOTAL_COLUMN;
53
         return "{$recordId}." . self::TOTAL_COLUMN;
50
     }
54
     }
51
 
55
 
52
-    /**
53
-     * Extract the period from a column name
54
-     */
55
-    protected static function extractPeriodFromColumn(string $columnName): ?string
56
-    {
57
-        if (preg_match('/' . self::AMOUNT_PREFIX . '(.+)/', $columnName, $matches)) {
58
-            return str_replace('_', ' ', $matches[1] ?? '');
59
-        }
60
-
61
-        return null;
62
-    }
63
-
64
     public function handleBatchColumnChanged($data): void
56
     public function handleBatchColumnChanged($data): void
65
     {
57
     {
66
         $key = "{$data['recordKey']}.{$data['name']}";
58
         $key = "{$data['recordKey']}.{$data['name']}";
72
         foreach ($this->batchChanges as $key => $value) {
64
         foreach ($this->batchChanges as $key => $value) {
73
             [$recordKey, $column] = explode('.', $key, 2);
65
             [$recordKey, $column] = explode('.', $key, 2);
74
 
66
 
75
-            $period = self::extractPeriodFromColumn($column);
76
-            if (! $period) {
67
+            try {
68
+                $startDate = Carbon::createFromFormat('Y_m_d', $column);
69
+            } catch (\Exception) {
77
                 continue;
70
                 continue;
78
             }
71
             }
79
 
72
 
82
                 continue;
75
                 continue;
83
             }
76
             }
84
 
77
 
85
-            $allocation = $record->allocations->firstWhere('period', $period);
86
-            if ($allocation) {
87
-                $allocation->update(['amount' => $value]);
88
-            } else {
89
-                $record->allocations()->create([
90
-                    'period' => $period,
91
-                    'amount' => $value,
92
-                ]);
93
-            }
78
+            $allocation = $record->allocations()
79
+                ->whereDate('start_date', $startDate)
80
+                ->first();
81
+
82
+            $allocation?->update(['amount' => $value]);
94
         }
83
         }
95
 
84
 
96
         $this->batchChanges = [];
85
         $this->batchChanges = [];
101
             ->send();
90
             ->send();
102
     }
91
     }
103
 
92
 
104
-    protected function calculateTotalSum(array $budgetItemIds): int
93
+    protected function calculatePeriodSum(array $budgetItemIds, string | Carbon $startDate): int
105
     {
94
     {
106
-        $periods = BudgetAllocation::whereIn('budget_item_id', $budgetItemIds)
107
-            ->pluck('period')
108
-            ->unique()
109
-            ->values()
110
-            ->toArray();
111
-
112
-        $total = 0;
113
-        foreach ($periods as $period) {
114
-            $total += $this->calculatePeriodSum($budgetItemIds, $period);
115
-        }
95
+        $allocations = DB::table('budget_allocations')
96
+            ->whereIn('budget_item_id', $budgetItemIds)
97
+            ->whereDate('start_date', $startDate)
98
+            ->pluck('amount', 'budget_item_id');
116
 
99
 
117
-        return $total;
118
-    }
119
-
120
-    protected function calculatePeriodSum(array $budgetItemIds, string $period): int
121
-    {
122
-        $dbTotal = BudgetAllocation::whereIn('budget_item_id', $budgetItemIds)
123
-            ->where('period', $period)
124
-            ->sum('amount');
100
+        $dbTotal = $allocations->sum();
125
 
101
 
126
         $batchTotal = 0;
102
         $batchTotal = 0;
103
+
127
         foreach ($budgetItemIds as $itemId) {
104
         foreach ($budgetItemIds as $itemId) {
128
-            $key = self::generatePeriodKey($itemId, $period);
105
+            $key = self::generatePeriodKey($itemId, $startDate);
106
+
129
             if (isset($this->batchChanges[$key])) {
107
             if (isset($this->batchChanges[$key])) {
130
                 $batchValue = CurrencyConverter::convertToCents($this->batchChanges[$key]);
108
                 $batchValue = CurrencyConverter::convertToCents($this->batchChanges[$key]);
131
-                $existingAmount = BudgetAllocation::where('budget_item_id', $itemId)
132
-                    ->where('period', $period)
133
-                    ->first()
134
-                    ?->getRawOriginal('amount') ?? 0;
109
+                $existingAmount = $allocations[$itemId] ?? 0;
135
 
110
 
136
                 $batchTotal += ($batchValue - $existingAmount);
111
                 $batchTotal += ($batchValue - $existingAmount);
137
             }
112
             }
144
     {
119
     {
145
         /** @var Budget $budget */
120
         /** @var Budget $budget */
146
         $budget = $this->getOwnerRecord();
121
         $budget = $this->getOwnerRecord();
147
-        $periods = $budget->getPeriods();
122
+        $allocationPeriods = $budget->getPeriods();
148
 
123
 
149
         return $table
124
         return $table
150
             ->recordTitleAttribute('account_id')
125
             ->recordTitleAttribute('account_id')
151
             ->paginated(false)
126
             ->paginated(false)
152
             ->heading(null)
127
             ->heading(null)
153
-            ->modifyQueryUsing(function (Builder $query) use ($periods) {
128
+            ->modifyQueryUsing(function (Builder $query) use ($allocationPeriods) {
154
                 $query->select('budget_items.*')
129
                 $query->select('budget_items.*')
155
                     ->leftJoin('budget_allocations', 'budget_allocations.budget_item_id', '=', 'budget_items.id');
130
                     ->leftJoin('budget_allocations', 'budget_allocations.budget_item_id', '=', 'budget_items.id');
156
 
131
 
157
-                foreach ($periods as $period) {
158
-                    $alias = self::AMOUNT_PREFIX . Str::snake($period);
132
+                foreach ($allocationPeriods as $period) {
133
+                    $alias = $period->start_date->format('Y_m_d');
159
                     $query->selectRaw(
134
                     $query->selectRaw(
160
-                        "SUM(CASE WHEN budget_allocations.period = ? THEN budget_allocations.amount ELSE 0 END) as {$alias}",
161
-                        [$period]
135
+                        "SUM(CASE WHEN budget_allocations.start_date = ? THEN budget_allocations.amount ELSE 0 END) as {$alias}",
136
+                        [$period->start_date->toDateString()]
162
                     );
137
                     );
163
                 }
138
                 }
164
 
139
 
202
                     ->summarize(
177
                     ->summarize(
203
                         Summarizer::make()
178
                         Summarizer::make()
204
                             ->using(function (\Illuminate\Database\Query\Builder $query) {
179
                             ->using(function (\Illuminate\Database\Query\Builder $query) {
205
-                                $budgetItemIds = $query->pluck('id')->toArray();
206
-                                $total = $this->calculateTotalSum($budgetItemIds);
180
+                                $allocations = $query
181
+                                    ->leftJoin('budget_allocations', 'budget_allocations.budget_item_id', '=', 'budget_items.id')
182
+                                    ->select('budget_allocations.budget_item_id', 'budget_allocations.start_date', 'budget_allocations.amount')
183
+                                    ->get();
184
+
185
+                                $allocationsByDate = $allocations->groupBy('start_date');
186
+
187
+                                $total = 0;
188
+
189
+                                /** @var \Illuminate\Support\Collection<string, \Illuminate\Support\Collection<int, stdClass>> $allocationsByDate */
190
+                                foreach ($allocationsByDate as $startDate => $group) {
191
+                                    $dbTotal = $group->sum('amount');
192
+                                    $amounts = $group->pluck('amount', 'budget_item_id');
193
+                                    $batchTotal = 0;
194
+
195
+                                    foreach ($amounts as $itemId => $existingAmount) {
196
+                                        $key = self::generatePeriodKey($itemId, $startDate);
197
+
198
+                                        if (isset($this->batchChanges[$key])) {
199
+                                            $batchValue = CurrencyConverter::convertToCents($this->batchChanges[$key]);
200
+                                            $batchTotal += ($batchValue - $existingAmount);
201
+                                        }
202
+                                    }
203
+
204
+                                    $total += $dbTotal + $batchTotal;
205
+                                }
207
 
206
 
208
                                 return CurrencyConverter::convertCentsToFormatSimple($total);
207
                                 return CurrencyConverter::convertCentsToFormatSimple($total);
209
                             })
208
                             })
217
                     ->action(
216
                     ->action(
218
                         Action::make('disperse')
217
                         Action::make('disperse')
219
                             ->label('Disperse')
218
                             ->label('Disperse')
220
-                            ->action(function (BudgetItem $record) use ($periods) {
221
-                                if (empty($periods)) {
219
+                            ->action(function (BudgetItem $record) use ($allocationPeriods) {
220
+                                if (empty($allocationPeriods)) {
222
                                     return;
221
                                     return;
223
                                 }
222
                                 }
224
 
223
 
233
                                     });
232
                                     });
234
                                 }
233
                                 }
235
 
234
 
236
-                                $numPeriods = count($periods);
237
-
238
-                                if ($numPeriods === 0) {
239
-                                    return;
240
-                                }
241
-
242
                                 if ($totalCents <= 0) {
235
                                 if ($totalCents <= 0) {
243
-                                    foreach ($periods as $period) {
244
-                                        $periodKey = self::generatePeriodKey($record->getKey(), $period);
236
+                                    foreach ($allocationPeriods as $period) {
237
+                                        $periodKey = self::generatePeriodKey($record->getKey(), $period->start_date);
245
                                         $this->batchChanges[$periodKey] = CurrencyConverter::convertCentsToFormatSimple(0);
238
                                         $this->batchChanges[$periodKey] = CurrencyConverter::convertCentsToFormatSimple(0);
246
                                     }
239
                                     }
247
 
240
 
248
                                     return;
241
                                     return;
249
                                 }
242
                                 }
250
 
243
 
244
+                                $numPeriods = count($allocationPeriods);
245
+
251
                                 $baseAmount = floor($totalCents / $numPeriods);
246
                                 $baseAmount = floor($totalCents / $numPeriods);
252
                                 $remainder = $totalCents - ($baseAmount * $numPeriods);
247
                                 $remainder = $totalCents - ($baseAmount * $numPeriods);
253
 
248
 
254
-                                foreach ($periods as $index => $period) {
249
+                                foreach ($allocationPeriods as $index => $period) {
255
                                     $amount = $baseAmount + ($index === 0 ? $remainder : 0);
250
                                     $amount = $baseAmount + ($index === 0 ? $remainder : 0);
256
                                     $formattedAmount = CurrencyConverter::convertCentsToFormatSimple($amount);
251
                                     $formattedAmount = CurrencyConverter::convertCentsToFormatSimple($amount);
257
 
252
 
258
-                                    $periodKey = self::generatePeriodKey($record->getKey(), $period);
253
+                                    $periodKey = self::generatePeriodKey($record->getKey(), $period->start_date);
259
                                     $this->batchChanges[$periodKey] = $formattedAmount;
254
                                     $this->batchChanges[$periodKey] = $formattedAmount;
260
                                 }
255
                                 }
261
                             }),
256
                             }),
262
                     ),
257
                     ),
263
-                ...array_map(function (string $period) {
264
-                    $alias = self::AMOUNT_PREFIX . Str::snake($period);
258
+                ...$allocationPeriods->map(function (BudgetAllocation $period) {
259
+                    $alias = $period->start_date->format('Y_m_d');
265
 
260
 
266
                     return DeferredTextInputColumn::make($alias)
261
                     return DeferredTextInputColumn::make($alias)
267
-                        ->label($period)
262
+                        ->label($period->period)
268
                         ->alignRight()
263
                         ->alignRight()
269
                         ->batchMode()
264
                         ->batchMode()
270
                         ->mask(RawJs::make('$money($input)'))
265
                         ->mask(RawJs::make('$money($input)'))
277
                             Summarizer::make()
272
                             Summarizer::make()
278
                                 ->using(function (\Illuminate\Database\Query\Builder $query) use ($period) {
273
                                 ->using(function (\Illuminate\Database\Query\Builder $query) use ($period) {
279
                                     $budgetItemIds = $query->pluck('id')->toArray();
274
                                     $budgetItemIds = $query->pluck('id')->toArray();
280
-                                    $total = $this->calculatePeriodSum($budgetItemIds, $period);
275
+                                    $total = $this->calculatePeriodSum($budgetItemIds, $period->start_date);
281
 
276
 
282
                                     return CurrencyConverter::convertCentsToFormatSimple($total);
277
                                     return CurrencyConverter::convertCentsToFormatSimple($total);
283
                                 })
278
                                 })
284
                         );
279
                         );
285
-                }, $periods),
280
+                })->toArray(),
286
             ])
281
             ])
287
             ->bulkActions([
282
             ->bulkActions([
288
                 BulkAction::make('clearAllocations')
283
                 BulkAction::make('clearAllocations')
291
                     ->color('danger')
286
                     ->color('danger')
292
                     ->requiresConfirmation()
287
                     ->requiresConfirmation()
293
                     ->deselectRecordsAfterCompletion()
288
                     ->deselectRecordsAfterCompletion()
294
-                    ->action(function (Collection $records) use ($periods) {
289
+                    ->action(function (Collection $records) use ($allocationPeriods) {
295
                         foreach ($records as $record) {
290
                         foreach ($records as $record) {
296
-                            foreach ($periods as $period) {
297
-                                $periodKey = self::generatePeriodKey($record->getKey(), $period);
291
+                            foreach ($allocationPeriods as $period) {
292
+                                $periodKey = self::generatePeriodKey($record->getKey(), $period->start_date);
298
                                 $this->batchChanges[$periodKey] = CurrencyConverter::convertCentsToFormatSimple(0);
293
                                 $this->batchChanges[$periodKey] = CurrencyConverter::convertCentsToFormatSimple(0);
299
                             }
294
                             }
300
                         }
295
                         }

+ 3
- 3
app/Models/Accounting/Budget.php 查看文件

20
 use Illuminate\Database\Eloquent\Relations\HasMany;
20
 use Illuminate\Database\Eloquent\Relations\HasMany;
21
 use Illuminate\Database\Eloquent\Relations\HasManyThrough;
21
 use Illuminate\Database\Eloquent\Relations\HasManyThrough;
22
 use Illuminate\Support\Carbon;
22
 use Illuminate\Support\Carbon;
23
+use Illuminate\Support\Collection;
23
 
24
 
24
 class Budget extends Model
25
 class Budget extends Model
25
 {
26
 {
81
         return $this->hasManyThrough(BudgetAllocation::class, BudgetItem::class);
82
         return $this->hasManyThrough(BudgetAllocation::class, BudgetItem::class);
82
     }
83
     }
83
 
84
 
84
-    public function getPeriods(): array
85
+    public function getPeriods(): Collection
85
     {
86
     {
86
         return $this->allocations()
87
         return $this->allocations()
87
             ->select(['period', 'start_date'])
88
             ->select(['period', 'start_date'])
88
             ->distinct()
89
             ->distinct()
89
             ->orderBy('start_date')
90
             ->orderBy('start_date')
90
-            ->pluck('period')
91
-            ->toArray();
91
+            ->get();
92
     }
92
     }
93
 
93
 
94
     public function isDraft(): bool
94
     public function isDraft(): bool

+ 41
- 41
composer.lock 查看文件

9306
     "packages-dev": [
9306
     "packages-dev": [
9307
         {
9307
         {
9308
             "name": "brianium/paratest",
9308
             "name": "brianium/paratest",
9309
-            "version": "v7.7.0",
9309
+            "version": "v7.8.3",
9310
             "source": {
9310
             "source": {
9311
                 "type": "git",
9311
                 "type": "git",
9312
                 "url": "https://github.com/paratestphp/paratest.git",
9312
                 "url": "https://github.com/paratestphp/paratest.git",
9313
-                "reference": "4fb3f73bc5a4c3146bac2850af7dc72435a32daf"
9313
+                "reference": "a585c346ddf1bec22e51e20b5387607905604a71"
9314
             },
9314
             },
9315
             "dist": {
9315
             "dist": {
9316
                 "type": "zip",
9316
                 "type": "zip",
9317
-                "url": "https://api.github.com/repos/paratestphp/paratest/zipball/4fb3f73bc5a4c3146bac2850af7dc72435a32daf",
9318
-                "reference": "4fb3f73bc5a4c3146bac2850af7dc72435a32daf",
9317
+                "url": "https://api.github.com/repos/paratestphp/paratest/zipball/a585c346ddf1bec22e51e20b5387607905604a71",
9318
+                "reference": "a585c346ddf1bec22e51e20b5387607905604a71",
9319
                 "shasum": ""
9319
                 "shasum": ""
9320
             },
9320
             },
9321
             "require": {
9321
             "require": {
9326
                 "fidry/cpu-core-counter": "^1.2.0",
9326
                 "fidry/cpu-core-counter": "^1.2.0",
9327
                 "jean85/pretty-package-versions": "^2.1.0",
9327
                 "jean85/pretty-package-versions": "^2.1.0",
9328
                 "php": "~8.2.0 || ~8.3.0 || ~8.4.0",
9328
                 "php": "~8.2.0 || ~8.3.0 || ~8.4.0",
9329
-                "phpunit/php-code-coverage": "^11.0.8",
9330
-                "phpunit/php-file-iterator": "^5.1.0",
9331
-                "phpunit/php-timer": "^7.0.1",
9332
-                "phpunit/phpunit": "^11.5.1",
9333
-                "sebastian/environment": "^7.2.0",
9334
-                "symfony/console": "^6.4.14 || ^7.2.1",
9335
-                "symfony/process": "^6.4.14 || ^7.2.0"
9329
+                "phpunit/php-code-coverage": "^11.0.9 || ^12.0.4",
9330
+                "phpunit/php-file-iterator": "^5.1.0 || ^6",
9331
+                "phpunit/php-timer": "^7.0.1 || ^8",
9332
+                "phpunit/phpunit": "^11.5.11 || ^12.0.6",
9333
+                "sebastian/environment": "^7.2.0 || ^8",
9334
+                "symfony/console": "^6.4.17 || ^7.2.1",
9335
+                "symfony/process": "^6.4.19 || ^7.2.4"
9336
             },
9336
             },
9337
             "require-dev": {
9337
             "require-dev": {
9338
                 "doctrine/coding-standard": "^12.0.0",
9338
                 "doctrine/coding-standard": "^12.0.0",
9339
                 "ext-pcov": "*",
9339
                 "ext-pcov": "*",
9340
                 "ext-posix": "*",
9340
                 "ext-posix": "*",
9341
-                "phpstan/phpstan": "^2.0.3",
9341
+                "phpstan/phpstan": "^2.1.6",
9342
                 "phpstan/phpstan-deprecation-rules": "^2.0.1",
9342
                 "phpstan/phpstan-deprecation-rules": "^2.0.1",
9343
-                "phpstan/phpstan-phpunit": "^2.0.1",
9344
-                "phpstan/phpstan-strict-rules": "^2",
9345
-                "squizlabs/php_codesniffer": "^3.11.1",
9343
+                "phpstan/phpstan-phpunit": "^2.0.4",
9344
+                "phpstan/phpstan-strict-rules": "^2.0.3",
9345
+                "squizlabs/php_codesniffer": "^3.11.3",
9346
                 "symfony/filesystem": "^6.4.13 || ^7.2.0"
9346
                 "symfony/filesystem": "^6.4.13 || ^7.2.0"
9347
             },
9347
             },
9348
             "bin": [
9348
             "bin": [
9383
             ],
9383
             ],
9384
             "support": {
9384
             "support": {
9385
                 "issues": "https://github.com/paratestphp/paratest/issues",
9385
                 "issues": "https://github.com/paratestphp/paratest/issues",
9386
-                "source": "https://github.com/paratestphp/paratest/tree/v7.7.0"
9386
+                "source": "https://github.com/paratestphp/paratest/tree/v7.8.3"
9387
             },
9387
             },
9388
             "funding": [
9388
             "funding": [
9389
                 {
9389
                 {
9395
                     "type": "paypal"
9395
                     "type": "paypal"
9396
                 }
9396
                 }
9397
             ],
9397
             ],
9398
-            "time": "2024-12-11T14:50:44+00:00"
9398
+            "time": "2025-03-05T08:29:11+00:00"
9399
         },
9399
         },
9400
         {
9400
         {
9401
             "name": "fakerphp/faker",
9401
             "name": "fakerphp/faker",
10075
         },
10075
         },
10076
         {
10076
         {
10077
             "name": "pestphp/pest",
10077
             "name": "pestphp/pest",
10078
-            "version": "v3.7.4",
10078
+            "version": "v3.7.5",
10079
             "source": {
10079
             "source": {
10080
                 "type": "git",
10080
                 "type": "git",
10081
                 "url": "https://github.com/pestphp/pest.git",
10081
                 "url": "https://github.com/pestphp/pest.git",
10082
-                "reference": "4a987d3d5c4e3ba36c76fecbf56113baac2d1b2b"
10082
+                "reference": "4969526ef2841118aa9d8b13ae2dad40f3d91492"
10083
             },
10083
             },
10084
             "dist": {
10084
             "dist": {
10085
                 "type": "zip",
10085
                 "type": "zip",
10086
-                "url": "https://api.github.com/repos/pestphp/pest/zipball/4a987d3d5c4e3ba36c76fecbf56113baac2d1b2b",
10087
-                "reference": "4a987d3d5c4e3ba36c76fecbf56113baac2d1b2b",
10086
+                "url": "https://api.github.com/repos/pestphp/pest/zipball/4969526ef2841118aa9d8b13ae2dad40f3d91492",
10087
+                "reference": "4969526ef2841118aa9d8b13ae2dad40f3d91492",
10088
                 "shasum": ""
10088
                 "shasum": ""
10089
             },
10089
             },
10090
             "require": {
10090
             "require": {
10091
-                "brianium/paratest": "^7.7.0",
10092
-                "nunomaduro/collision": "^8.6.1",
10091
+                "brianium/paratest": "^7.8.3",
10092
+                "nunomaduro/collision": "^8.7.0",
10093
                 "nunomaduro/termwind": "^2.3.0",
10093
                 "nunomaduro/termwind": "^2.3.0",
10094
                 "pestphp/pest-plugin": "^3.0.0",
10094
                 "pestphp/pest-plugin": "^3.0.0",
10095
                 "pestphp/pest-plugin-arch": "^3.0.0",
10095
                 "pestphp/pest-plugin-arch": "^3.0.0",
10096
                 "pestphp/pest-plugin-mutate": "^3.0.5",
10096
                 "pestphp/pest-plugin-mutate": "^3.0.5",
10097
                 "php": "^8.2.0",
10097
                 "php": "^8.2.0",
10098
-                "phpunit/phpunit": "^11.5.3"
10098
+                "phpunit/phpunit": "^11.5.15"
10099
             },
10099
             },
10100
             "conflict": {
10100
             "conflict": {
10101
                 "filp/whoops": "<2.16.0",
10101
                 "filp/whoops": "<2.16.0",
10102
-                "phpunit/phpunit": ">11.5.3",
10102
+                "phpunit/phpunit": ">11.5.15",
10103
                 "sebastian/exporter": "<6.0.0",
10103
                 "sebastian/exporter": "<6.0.0",
10104
                 "webmozart/assert": "<1.11.0"
10104
                 "webmozart/assert": "<1.11.0"
10105
             },
10105
             },
10106
             "require-dev": {
10106
             "require-dev": {
10107
-                "pestphp/pest-dev-tools": "^3.3.0",
10108
-                "pestphp/pest-plugin-type-coverage": "^3.2.3",
10109
-                "symfony/process": "^7.2.0"
10107
+                "pestphp/pest-dev-tools": "^3.4.0",
10108
+                "pestphp/pest-plugin-type-coverage": "^3.5.0",
10109
+                "symfony/process": "^7.2.5"
10110
             },
10110
             },
10111
             "bin": [
10111
             "bin": [
10112
                 "bin/pest"
10112
                 "bin/pest"
10171
             ],
10171
             ],
10172
             "support": {
10172
             "support": {
10173
                 "issues": "https://github.com/pestphp/pest/issues",
10173
                 "issues": "https://github.com/pestphp/pest/issues",
10174
-                "source": "https://github.com/pestphp/pest/tree/v3.7.4"
10174
+                "source": "https://github.com/pestphp/pest/tree/v3.7.5"
10175
             },
10175
             },
10176
             "funding": [
10176
             "funding": [
10177
                 {
10177
                 {
10183
                     "type": "github"
10183
                     "type": "github"
10184
                 }
10184
                 }
10185
             ],
10185
             ],
10186
-            "time": "2025-01-23T14:03:29+00:00"
10186
+            "time": "2025-03-29T17:57:53+00:00"
10187
         },
10187
         },
10188
         {
10188
         {
10189
             "name": "pestphp/pest-plugin",
10189
             "name": "pestphp/pest-plugin",
11256
         },
11256
         },
11257
         {
11257
         {
11258
             "name": "phpunit/phpunit",
11258
             "name": "phpunit/phpunit",
11259
-            "version": "11.5.3",
11259
+            "version": "11.5.15",
11260
             "source": {
11260
             "source": {
11261
                 "type": "git",
11261
                 "type": "git",
11262
                 "url": "https://github.com/sebastianbergmann/phpunit.git",
11262
                 "url": "https://github.com/sebastianbergmann/phpunit.git",
11263
-                "reference": "30e319e578a7b5da3543073e30002bf82042f701"
11263
+                "reference": "4b6a4ee654e5e0c5e1f17e2f83c0f4c91dee1f9c"
11264
             },
11264
             },
11265
             "dist": {
11265
             "dist": {
11266
                 "type": "zip",
11266
                 "type": "zip",
11267
-                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/30e319e578a7b5da3543073e30002bf82042f701",
11268
-                "reference": "30e319e578a7b5da3543073e30002bf82042f701",
11267
+                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/4b6a4ee654e5e0c5e1f17e2f83c0f4c91dee1f9c",
11268
+                "reference": "4b6a4ee654e5e0c5e1f17e2f83c0f4c91dee1f9c",
11269
                 "shasum": ""
11269
                 "shasum": ""
11270
             },
11270
             },
11271
             "require": {
11271
             "require": {
11275
                 "ext-mbstring": "*",
11275
                 "ext-mbstring": "*",
11276
                 "ext-xml": "*",
11276
                 "ext-xml": "*",
11277
                 "ext-xmlwriter": "*",
11277
                 "ext-xmlwriter": "*",
11278
-                "myclabs/deep-copy": "^1.12.1",
11278
+                "myclabs/deep-copy": "^1.13.0",
11279
                 "phar-io/manifest": "^2.0.4",
11279
                 "phar-io/manifest": "^2.0.4",
11280
                 "phar-io/version": "^3.2.1",
11280
                 "phar-io/version": "^3.2.1",
11281
                 "php": ">=8.2",
11281
                 "php": ">=8.2",
11282
-                "phpunit/php-code-coverage": "^11.0.8",
11282
+                "phpunit/php-code-coverage": "^11.0.9",
11283
                 "phpunit/php-file-iterator": "^5.1.0",
11283
                 "phpunit/php-file-iterator": "^5.1.0",
11284
                 "phpunit/php-invoker": "^5.0.1",
11284
                 "phpunit/php-invoker": "^5.0.1",
11285
                 "phpunit/php-text-template": "^4.0.1",
11285
                 "phpunit/php-text-template": "^4.0.1",
11286
                 "phpunit/php-timer": "^7.0.1",
11286
                 "phpunit/php-timer": "^7.0.1",
11287
                 "sebastian/cli-parser": "^3.0.2",
11287
                 "sebastian/cli-parser": "^3.0.2",
11288
-                "sebastian/code-unit": "^3.0.2",
11289
-                "sebastian/comparator": "^6.3.0",
11288
+                "sebastian/code-unit": "^3.0.3",
11289
+                "sebastian/comparator": "^6.3.1",
11290
                 "sebastian/diff": "^6.0.2",
11290
                 "sebastian/diff": "^6.0.2",
11291
                 "sebastian/environment": "^7.2.0",
11291
                 "sebastian/environment": "^7.2.0",
11292
                 "sebastian/exporter": "^6.3.0",
11292
                 "sebastian/exporter": "^6.3.0",
11293
                 "sebastian/global-state": "^7.0.2",
11293
                 "sebastian/global-state": "^7.0.2",
11294
                 "sebastian/object-enumerator": "^6.0.1",
11294
                 "sebastian/object-enumerator": "^6.0.1",
11295
-                "sebastian/type": "^5.1.0",
11295
+                "sebastian/type": "^5.1.2",
11296
                 "sebastian/version": "^5.0.2",
11296
                 "sebastian/version": "^5.0.2",
11297
                 "staabm/side-effects-detector": "^1.0.5"
11297
                 "staabm/side-effects-detector": "^1.0.5"
11298
             },
11298
             },
11337
             "support": {
11337
             "support": {
11338
                 "issues": "https://github.com/sebastianbergmann/phpunit/issues",
11338
                 "issues": "https://github.com/sebastianbergmann/phpunit/issues",
11339
                 "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
11339
                 "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
11340
-                "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.3"
11340
+                "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.15"
11341
             },
11341
             },
11342
             "funding": [
11342
             "funding": [
11343
                 {
11343
                 {
11353
                     "type": "tidelift"
11353
                     "type": "tidelift"
11354
                 }
11354
                 }
11355
             ],
11355
             ],
11356
-            "time": "2025-01-13T09:36:00+00:00"
11356
+            "time": "2025-03-23T16:02:11+00:00"
11357
         },
11357
         },
11358
         {
11358
         {
11359
             "name": "sebastian/cli-parser",
11359
             "name": "sebastian/cli-parser",

Loading…
取消
儲存