浏览代码

Merge pull request #95 from andrewdwallo/development-3.x

Fix Issue with DatePicker causing recursive updates
3.x
Andrew Wallo 9 个月前
父节点
当前提交
1733778052
没有帐户链接到提交者的电子邮件

+ 2
- 2
app/Filament/Company/Resources/Sales/RecurringInvoiceResource/Pages/ViewRecurringInvoice.php 查看文件

58
                     ->info()
58
                     ->info()
59
                     ->title('Schedule Not Set')
59
                     ->title('Schedule Not Set')
60
                     ->description('The schedule for this recurring invoice has not been set. You must set a schedule before you can approve this draft and start creating invoices.')
60
                     ->description('The schedule for this recurring invoice has not been set. You must set a schedule before you can approve this draft and start creating invoices.')
61
-                    ->visible(fn (RecurringInvoice $record) => ! $record->hasSchedule())
61
+                    ->visible(fn (RecurringInvoice $record) => ! $record->hasValidStartDate())
62
                     ->columnSpanFull()
62
                     ->columnSpanFull()
63
                     ->actions([
63
                     ->actions([
64
                         RecurringInvoice::getUpdateScheduleAction(Action::class)
64
                         RecurringInvoice::getUpdateScheduleAction(Action::class)
68
                     ->info()
68
                     ->info()
69
                     ->title('Ready to Approve')
69
                     ->title('Ready to Approve')
70
                     ->description('This recurring invoice is ready for approval. Review the details, and approve it when you’re ready to start generating invoices.')
70
                     ->description('This recurring invoice is ready for approval. Review the details, and approve it when you’re ready to start generating invoices.')
71
-                    ->visible(fn (RecurringInvoice $record) => $record->isDraft() && $record->hasSchedule())
71
+                    ->visible(fn (RecurringInvoice $record) => $record->canBeApproved())
72
                     ->columnSpanFull()
72
                     ->columnSpanFull()
73
                     ->actions([
73
                     ->actions([
74
                         RecurringInvoice::getApproveDraftAction(Action::class)
74
                         RecurringInvoice::getApproveDraftAction(Action::class)

+ 9
- 7
app/Models/Accounting/RecurringInvoice.php 查看文件

177
 
177
 
178
     public function canBeApproved(): bool
178
     public function canBeApproved(): bool
179
     {
179
     {
180
-        return $this->isDraft() && $this->hasSchedule() && ! $this->wasApproved();
180
+        return $this->isDraft() && $this->hasSchedule() && ! $this->wasApproved() && $this->hasValidStartDate();
181
     }
181
     }
182
 
182
 
183
     public function canBeEnded(): bool
183
     public function canBeEnded(): bool
187
 
187
 
188
     public function hasSchedule(): bool
188
     public function hasSchedule(): bool
189
     {
189
     {
190
-        if (! $this->start_date) {
191
-            return false;
192
-        }
190
+        return $this->start_date !== null;
191
+    }
193
 
192
 
194
-        if (! $this->wasApproved() && $this->start_date->lt(today())) {
195
-            return false;
193
+    public function hasValidStartDate(): bool
194
+    {
195
+        if ($this->wasApproved()) {
196
+            return true;
196
         }
197
         }
197
 
198
 
198
-        return true;
199
+        // For unapproved/draft invoices, start date must be today or in the future
200
+        return $this->start_date?->gte(today()) ?? false;
199
     }
201
     }
200
 
202
 
201
     public function getScheduleDescription(): string
203
     public function getScheduleDescription(): string

+ 1
- 1
app/Observers/RecurringInvoiceObserver.php 查看文件

13
     {
13
     {
14
         if (
14
         if (
15
             $recurringInvoice->wasApproved() &&
15
             $recurringInvoice->wasApproved() &&
16
-            (($recurringInvoice->isDirty('start_date') && ! $recurringInvoice->last_date) || $this->otherScheduleDetailsChanged($recurringInvoice))
16
+            (($recurringInvoice->isDirty('start_date') && ! $recurringInvoice->last_date))
17
         ) {
17
         ) {
18
             $recurringInvoice->next_date = $recurringInvoice->calculateNextDate();
18
             $recurringInvoice->next_date = $recurringInvoice->calculateNextDate();
19
         }
19
         }

+ 12
- 12
app/Support/ScheduleHandler.php 查看文件

77
             'interval_value' => null,
77
             'interval_value' => null,
78
             'interval_type' => null,
78
             'interval_type' => null,
79
             'day_of_month' => null,
79
             'day_of_month' => null,
80
-            'start_date' => $this->today,
80
+            'start_date' => $this->today->toDateString(),
81
         ]);
81
         ]);
82
     }
82
     }
83
 
83
 
87
 
87
 
88
         $this->setMany($this->set, [
88
         $this->setMany($this->set, [
89
             'day_of_week' => $currentDayOfWeek,
89
             'day_of_week' => $currentDayOfWeek,
90
-            'start_date' => $this->today,
90
+            'start_date' => $this->today->toDateString(),
91
             'interval_value' => null,
91
             'interval_value' => null,
92
             'interval_type' => null,
92
             'interval_type' => null,
93
             'day_of_month' => null,
93
             'day_of_month' => null,
106
         $this->setMany($this->set, [
106
         $this->setMany($this->set, [
107
             'month' => null,
107
             'month' => null,
108
             'day_of_month' => $dayOfMonth,
108
             'day_of_month' => $dayOfMonth,
109
-            'start_date' => $adjustedStartDate,
109
+            'start_date' => $adjustedStartDate->toDateString(),
110
             'interval_value' => null,
110
             'interval_value' => null,
111
             'interval_type' => null,
111
             'interval_type' => null,
112
         ]);
112
         ]);
120
         $this->setMany($this->set, [
120
         $this->setMany($this->set, [
121
             'month' => $currentMonth,
121
             'month' => $currentMonth,
122
             'day_of_month' => $currentDayOfMonth,
122
             'day_of_month' => $currentDayOfMonth,
123
-            'start_date' => $this->today,
123
+            'start_date' => $this->today->toDateString(),
124
             'interval_value' => null,
124
             'interval_value' => null,
125
             'interval_type' => null,
125
             'interval_type' => null,
126
         ]);
126
         ]);
140
             'interval_type' => IntervalType::Month,
140
             'interval_type' => IntervalType::Month,
141
             'month' => null,
141
             'month' => null,
142
             'day_of_month' => $dayOfMonth,
142
             'day_of_month' => $dayOfMonth,
143
-            'start_date' => $adjustedStartDate,
143
+            'start_date' => $adjustedStartDate->toDateString(),
144
         ]);
144
         ]);
145
     }
145
     }
146
 
146
 
150
 
150
 
151
         $this->setMany($this->set, [
151
         $this->setMany($this->set, [
152
             'day_of_week' => $currentDayOfWeek,
152
             'day_of_week' => $currentDayOfWeek,
153
-            'start_date' => $this->today,
153
+            'start_date' => $this->today->toDateString(),
154
         ]);
154
         ]);
155
     }
155
     }
156
 
156
 
166
         $this->setMany($this->set, [
166
         $this->setMany($this->set, [
167
             'month' => null,
167
             'month' => null,
168
             'day_of_month' => $dayOfMonth,
168
             'day_of_month' => $dayOfMonth,
169
-            'start_date' => $adjustedStartDate,
169
+            'start_date' => $adjustedStartDate->toDateString(),
170
         ]);
170
         ]);
171
     }
171
     }
172
 
172
 
178
         $this->setMany($this->set, [
178
         $this->setMany($this->set, [
179
             'month' => $currentMonth,
179
             'month' => $currentMonth,
180
             'day_of_month' => $currentDayOfMonth,
180
             'day_of_month' => $currentDayOfMonth,
181
-            'start_date' => $this->today,
181
+            'start_date' => $this->today->toDateString(),
182
         ]);
182
         ]);
183
     }
183
     }
184
 
184
 
223
 
223
 
224
             $this->setMany($this->set, [
224
             $this->setMany($this->set, [
225
                 'day_of_month' => $adjustedDay,
225
                 'day_of_month' => $adjustedDay,
226
-                'start_date' => $adjustedStartDate,
226
+                'start_date' => $adjustedStartDate->toDateString(),
227
             ]);
227
             ]);
228
         }
228
         }
229
     }
229
     }
246
                 ? $dayOfMonth->resolveDate($date->addMonth())
246
                 ? $dayOfMonth->resolveDate($date->addMonth())
247
                 : $dayOfMonth->resolveDate($date);
247
                 : $dayOfMonth->resolveDate($date);
248
 
248
 
249
-            ($this->set)('start_date', $adjustedStartDate);
249
+            ($this->set)('start_date', $adjustedStartDate->toDateString());
250
         }
250
         }
251
 
251
 
252
         if (($frequency->isYearly() || $intervalType?->isYear()) && $month && $dayOfMonth) {
252
         if (($frequency->isYearly() || $intervalType?->isYear()) && $month && $dayOfMonth) {
256
                 ? $dayOfMonth->resolveDate($date->addYear()->month($month->value))
256
                 ? $dayOfMonth->resolveDate($date->addYear()->month($month->value))
257
                 : $dayOfMonth->resolveDate($date->month($month->value));
257
                 : $dayOfMonth->resolveDate($date->month($month->value));
258
 
258
 
259
-            ($this->set)('start_date', $adjustedStartDate);
259
+            ($this->set)('start_date', $adjustedStartDate->toDateString());
260
         }
260
         }
261
     }
261
     }
262
 
262
 
268
             ? $this->today
268
             ? $this->today
269
             : $this->today->next($dayOfWeek->name);
269
             : $this->today->next($dayOfWeek->name);
270
 
270
 
271
-        ($this->set)('start_date', $adjustedStartDate);
271
+        ($this->set)('start_date', $adjustedStartDate->toDateString());
272
     }
272
     }
273
 }
273
 }

+ 1
- 1
composer.json 查看文件

18
         "awcodes/filament-table-repeater": "^3.0",
18
         "awcodes/filament-table-repeater": "^3.0",
19
         "barryvdh/laravel-snappy": "^1.0",
19
         "barryvdh/laravel-snappy": "^1.0",
20
         "codewithdennis/filament-simple-alert": "^3.0",
20
         "codewithdennis/filament-simple-alert": "^3.0",
21
-        "filament/filament": "^3.2",
21
+        "filament/filament": "v3.2.132",
22
         "guava/filament-clusters": "^1.1",
22
         "guava/filament-clusters": "^1.1",
23
         "guzzlehttp/guzzle": "^7.8",
23
         "guzzlehttp/guzzle": "^7.8",
24
         "jaocero/radio-deck": "^1.2",
24
         "jaocero/radio-deck": "^1.2",

+ 42
- 42
composer.lock 查看文件

4
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
4
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5
         "This file is @generated automatically"
5
         "This file is @generated automatically"
6
     ],
6
     ],
7
-    "content-hash": "decc627f2a7bd0c6546114ebb1f500f9",
7
+    "content-hash": "861a1aea38f7af0893ee251608dc7cfa",
8
     "packages": [
8
     "packages": [
9
         {
9
         {
10
             "name": "akaunting/laravel-money",
10
             "name": "akaunting/laravel-money",
1735
         },
1735
         },
1736
         {
1736
         {
1737
             "name": "filament/actions",
1737
             "name": "filament/actions",
1738
-            "version": "v3.2.133",
1738
+            "version": "v3.2.132",
1739
             "source": {
1739
             "source": {
1740
                 "type": "git",
1740
                 "type": "git",
1741
                 "url": "https://github.com/filamentphp/actions.git",
1741
                 "url": "https://github.com/filamentphp/actions.git",
1742
-                "reference": "33464f1583217b5eb12364b617b27abe5315eb88"
1742
+                "reference": "887b9e5552658a37098e7a279196a4d188d94f50"
1743
             },
1743
             },
1744
             "dist": {
1744
             "dist": {
1745
                 "type": "zip",
1745
                 "type": "zip",
1746
-                "url": "https://api.github.com/repos/filamentphp/actions/zipball/33464f1583217b5eb12364b617b27abe5315eb88",
1747
-                "reference": "33464f1583217b5eb12364b617b27abe5315eb88",
1746
+                "url": "https://api.github.com/repos/filamentphp/actions/zipball/887b9e5552658a37098e7a279196a4d188d94f50",
1747
+                "reference": "887b9e5552658a37098e7a279196a4d188d94f50",
1748
                 "shasum": ""
1748
                 "shasum": ""
1749
             },
1749
             },
1750
             "require": {
1750
             "require": {
1756
                 "illuminate/contracts": "^10.45|^11.0",
1756
                 "illuminate/contracts": "^10.45|^11.0",
1757
                 "illuminate/database": "^10.45|^11.0",
1757
                 "illuminate/database": "^10.45|^11.0",
1758
                 "illuminate/support": "^10.45|^11.0",
1758
                 "illuminate/support": "^10.45|^11.0",
1759
-                "league/csv": "^9.16",
1759
+                "league/csv": "^9.14",
1760
                 "openspout/openspout": "^4.23",
1760
                 "openspout/openspout": "^4.23",
1761
                 "php": "^8.1",
1761
                 "php": "^8.1",
1762
                 "spatie/laravel-package-tools": "^1.9"
1762
                 "spatie/laravel-package-tools": "^1.9"
1784
                 "issues": "https://github.com/filamentphp/filament/issues",
1784
                 "issues": "https://github.com/filamentphp/filament/issues",
1785
                 "source": "https://github.com/filamentphp/filament"
1785
                 "source": "https://github.com/filamentphp/filament"
1786
             },
1786
             },
1787
-            "time": "2025-01-10T12:47:49+00:00"
1787
+            "time": "2024-12-31T13:16:04+00:00"
1788
         },
1788
         },
1789
         {
1789
         {
1790
             "name": "filament/filament",
1790
             "name": "filament/filament",
1791
-            "version": "v3.2.133",
1791
+            "version": "v3.2.132",
1792
             "source": {
1792
             "source": {
1793
                 "type": "git",
1793
                 "type": "git",
1794
                 "url": "https://github.com/filamentphp/panels.git",
1794
                 "url": "https://github.com/filamentphp/panels.git",
1795
-                "reference": "74550888c1c79761218aece3c339ca0e0cc260e8"
1795
+                "reference": "54fcc0b883cc6622d1d9322d28c823ba6172f9ef"
1796
             },
1796
             },
1797
             "dist": {
1797
             "dist": {
1798
                 "type": "zip",
1798
                 "type": "zip",
1799
-                "url": "https://api.github.com/repos/filamentphp/panels/zipball/74550888c1c79761218aece3c339ca0e0cc260e8",
1800
-                "reference": "74550888c1c79761218aece3c339ca0e0cc260e8",
1799
+                "url": "https://api.github.com/repos/filamentphp/panels/zipball/54fcc0b883cc6622d1d9322d28c823ba6172f9ef",
1800
+                "reference": "54fcc0b883cc6622d1d9322d28c823ba6172f9ef",
1801
                 "shasum": ""
1801
                 "shasum": ""
1802
             },
1802
             },
1803
             "require": {
1803
             "require": {
1849
                 "issues": "https://github.com/filamentphp/filament/issues",
1849
                 "issues": "https://github.com/filamentphp/filament/issues",
1850
                 "source": "https://github.com/filamentphp/filament"
1850
                 "source": "https://github.com/filamentphp/filament"
1851
             },
1851
             },
1852
-            "time": "2025-01-10T12:48:32+00:00"
1852
+            "time": "2024-12-31T13:16:24+00:00"
1853
         },
1853
         },
1854
         {
1854
         {
1855
             "name": "filament/forms",
1855
             "name": "filament/forms",
1856
-            "version": "v3.2.133",
1856
+            "version": "v3.2.132",
1857
             "source": {
1857
             "source": {
1858
                 "type": "git",
1858
                 "type": "git",
1859
                 "url": "https://github.com/filamentphp/forms.git",
1859
                 "url": "https://github.com/filamentphp/forms.git",
1860
-                "reference": "20473c9eec7afa3ee618d2f86c7c449b3723d9fb"
1860
+                "reference": "4abbf867f060483699f3cb8e1c1c8f4469b7980f"
1861
             },
1861
             },
1862
             "dist": {
1862
             "dist": {
1863
                 "type": "zip",
1863
                 "type": "zip",
1864
-                "url": "https://api.github.com/repos/filamentphp/forms/zipball/20473c9eec7afa3ee618d2f86c7c449b3723d9fb",
1865
-                "reference": "20473c9eec7afa3ee618d2f86c7c449b3723d9fb",
1864
+                "url": "https://api.github.com/repos/filamentphp/forms/zipball/4abbf867f060483699f3cb8e1c1c8f4469b7980f",
1865
+                "reference": "4abbf867f060483699f3cb8e1c1c8f4469b7980f",
1866
                 "shasum": ""
1866
                 "shasum": ""
1867
             },
1867
             },
1868
             "require": {
1868
             "require": {
1905
                 "issues": "https://github.com/filamentphp/filament/issues",
1905
                 "issues": "https://github.com/filamentphp/filament/issues",
1906
                 "source": "https://github.com/filamentphp/filament"
1906
                 "source": "https://github.com/filamentphp/filament"
1907
             },
1907
             },
1908
-            "time": "2025-01-10T12:47:50+00:00"
1908
+            "time": "2024-12-31T13:16:06+00:00"
1909
         },
1909
         },
1910
         {
1910
         {
1911
             "name": "filament/infolists",
1911
             "name": "filament/infolists",
1912
-            "version": "v3.2.133",
1912
+            "version": "v3.2.132",
1913
             "source": {
1913
             "source": {
1914
                 "type": "git",
1914
                 "type": "git",
1915
                 "url": "https://github.com/filamentphp/infolists.git",
1915
                 "url": "https://github.com/filamentphp/infolists.git",
1916
-                "reference": "d3ee1eb508561f2b101c69cdb45c309539948d86"
1916
+                "reference": "8c0344fc603085da8f385ed6a022aacbe3aa49fb"
1917
             },
1917
             },
1918
             "dist": {
1918
             "dist": {
1919
                 "type": "zip",
1919
                 "type": "zip",
1920
-                "url": "https://api.github.com/repos/filamentphp/infolists/zipball/d3ee1eb508561f2b101c69cdb45c309539948d86",
1921
-                "reference": "d3ee1eb508561f2b101c69cdb45c309539948d86",
1920
+                "url": "https://api.github.com/repos/filamentphp/infolists/zipball/8c0344fc603085da8f385ed6a022aacbe3aa49fb",
1921
+                "reference": "8c0344fc603085da8f385ed6a022aacbe3aa49fb",
1922
                 "shasum": ""
1922
                 "shasum": ""
1923
             },
1923
             },
1924
             "require": {
1924
             "require": {
1956
                 "issues": "https://github.com/filamentphp/filament/issues",
1956
                 "issues": "https://github.com/filamentphp/filament/issues",
1957
                 "source": "https://github.com/filamentphp/filament"
1957
                 "source": "https://github.com/filamentphp/filament"
1958
             },
1958
             },
1959
-            "time": "2025-01-10T12:48:11+00:00"
1959
+            "time": "2024-12-31T13:16:16+00:00"
1960
         },
1960
         },
1961
         {
1961
         {
1962
             "name": "filament/notifications",
1962
             "name": "filament/notifications",
1963
-            "version": "v3.2.133",
1963
+            "version": "v3.2.132",
1964
             "source": {
1964
             "source": {
1965
                 "type": "git",
1965
                 "type": "git",
1966
                 "url": "https://github.com/filamentphp/notifications.git",
1966
                 "url": "https://github.com/filamentphp/notifications.git",
1967
-                "reference": "16cf5dbcbaf88cd9fff8d06aad866cb314b8bb64"
1967
+                "reference": "c19df07c801c5550de0d30957c5a316f53019533"
1968
             },
1968
             },
1969
             "dist": {
1969
             "dist": {
1970
                 "type": "zip",
1970
                 "type": "zip",
1971
-                "url": "https://api.github.com/repos/filamentphp/notifications/zipball/16cf5dbcbaf88cd9fff8d06aad866cb314b8bb64",
1972
-                "reference": "16cf5dbcbaf88cd9fff8d06aad866cb314b8bb64",
1971
+                "url": "https://api.github.com/repos/filamentphp/notifications/zipball/c19df07c801c5550de0d30957c5a316f53019533",
1972
+                "reference": "c19df07c801c5550de0d30957c5a316f53019533",
1973
                 "shasum": ""
1973
                 "shasum": ""
1974
             },
1974
             },
1975
             "require": {
1975
             "require": {
2008
                 "issues": "https://github.com/filamentphp/filament/issues",
2008
                 "issues": "https://github.com/filamentphp/filament/issues",
2009
                 "source": "https://github.com/filamentphp/filament"
2009
                 "source": "https://github.com/filamentphp/filament"
2010
             },
2010
             },
2011
-            "time": "2025-01-10T12:48:23+00:00"
2011
+            "time": "2024-10-23T07:36:14+00:00"
2012
         },
2012
         },
2013
         {
2013
         {
2014
             "name": "filament/support",
2014
             "name": "filament/support",
2015
-            "version": "v3.2.133",
2015
+            "version": "v3.2.132",
2016
             "source": {
2016
             "source": {
2017
                 "type": "git",
2017
                 "type": "git",
2018
                 "url": "https://github.com/filamentphp/support.git",
2018
                 "url": "https://github.com/filamentphp/support.git",
2019
-                "reference": "38fd76ae4f96b53e6f98cbb7bad3f05ad5032cee"
2019
+                "reference": "0bd91d5b937b0ae50394a976ba5fed9506581943"
2020
             },
2020
             },
2021
             "dist": {
2021
             "dist": {
2022
                 "type": "zip",
2022
                 "type": "zip",
2023
-                "url": "https://api.github.com/repos/filamentphp/support/zipball/38fd76ae4f96b53e6f98cbb7bad3f05ad5032cee",
2024
-                "reference": "38fd76ae4f96b53e6f98cbb7bad3f05ad5032cee",
2023
+                "url": "https://api.github.com/repos/filamentphp/support/zipball/0bd91d5b937b0ae50394a976ba5fed9506581943",
2024
+                "reference": "0bd91d5b937b0ae50394a976ba5fed9506581943",
2025
                 "shasum": ""
2025
                 "shasum": ""
2026
             },
2026
             },
2027
             "require": {
2027
             "require": {
2067
                 "issues": "https://github.com/filamentphp/filament/issues",
2067
                 "issues": "https://github.com/filamentphp/filament/issues",
2068
                 "source": "https://github.com/filamentphp/filament"
2068
                 "source": "https://github.com/filamentphp/filament"
2069
             },
2069
             },
2070
-            "time": "2025-01-10T12:48:52+00:00"
2070
+            "time": "2024-12-31T13:16:28+00:00"
2071
         },
2071
         },
2072
         {
2072
         {
2073
             "name": "filament/tables",
2073
             "name": "filament/tables",
2074
-            "version": "v3.2.133",
2074
+            "version": "v3.2.132",
2075
             "source": {
2075
             "source": {
2076
                 "type": "git",
2076
                 "type": "git",
2077
                 "url": "https://github.com/filamentphp/tables.git",
2077
                 "url": "https://github.com/filamentphp/tables.git",
2078
-                "reference": "6cbbea0bfd966ca2f26988c0fac4e02caebddf4a"
2078
+                "reference": "e34f63f89ef672f8e810c2e181665d718e84ff37"
2079
             },
2079
             },
2080
             "dist": {
2080
             "dist": {
2081
                 "type": "zip",
2081
                 "type": "zip",
2082
-                "url": "https://api.github.com/repos/filamentphp/tables/zipball/6cbbea0bfd966ca2f26988c0fac4e02caebddf4a",
2083
-                "reference": "6cbbea0bfd966ca2f26988c0fac4e02caebddf4a",
2082
+                "url": "https://api.github.com/repos/filamentphp/tables/zipball/e34f63f89ef672f8e810c2e181665d718e84ff37",
2083
+                "reference": "e34f63f89ef672f8e810c2e181665d718e84ff37",
2084
                 "shasum": ""
2084
                 "shasum": ""
2085
             },
2085
             },
2086
             "require": {
2086
             "require": {
2119
                 "issues": "https://github.com/filamentphp/filament/issues",
2119
                 "issues": "https://github.com/filamentphp/filament/issues",
2120
                 "source": "https://github.com/filamentphp/filament"
2120
                 "source": "https://github.com/filamentphp/filament"
2121
             },
2121
             },
2122
-            "time": "2025-01-10T12:48:48+00:00"
2122
+            "time": "2024-12-31T13:16:31+00:00"
2123
         },
2123
         },
2124
         {
2124
         {
2125
             "name": "filament/widgets",
2125
             "name": "filament/widgets",
2126
-            "version": "v3.2.133",
2126
+            "version": "v3.2.132",
2127
             "source": {
2127
             "source": {
2128
                 "type": "git",
2128
                 "type": "git",
2129
                 "url": "https://github.com/filamentphp/widgets.git",
2129
                 "url": "https://github.com/filamentphp/widgets.git",
2130
-                "reference": "9f6674daceced7d5045494d0bf7e1d2908ea439d"
2130
+                "reference": "869a419fe42e2cf1b9461f2d1e702e2fcad030ae"
2131
             },
2131
             },
2132
             "dist": {
2132
             "dist": {
2133
                 "type": "zip",
2133
                 "type": "zip",
2134
-                "url": "https://api.github.com/repos/filamentphp/widgets/zipball/9f6674daceced7d5045494d0bf7e1d2908ea439d",
2135
-                "reference": "9f6674daceced7d5045494d0bf7e1d2908ea439d",
2134
+                "url": "https://api.github.com/repos/filamentphp/widgets/zipball/869a419fe42e2cf1b9461f2d1e702e2fcad030ae",
2135
+                "reference": "869a419fe42e2cf1b9461f2d1e702e2fcad030ae",
2136
                 "shasum": ""
2136
                 "shasum": ""
2137
             },
2137
             },
2138
             "require": {
2138
             "require": {
2163
                 "issues": "https://github.com/filamentphp/filament/issues",
2163
                 "issues": "https://github.com/filamentphp/filament/issues",
2164
                 "source": "https://github.com/filamentphp/filament"
2164
                 "source": "https://github.com/filamentphp/filament"
2165
             },
2165
             },
2166
-            "time": "2025-01-10T12:48:52+00:00"
2166
+            "time": "2024-12-17T13:03:07+00:00"
2167
         },
2167
         },
2168
         {
2168
         {
2169
             "name": "firebase/php-jwt",
2169
             "name": "firebase/php-jwt",

+ 104
- 86
database/factories/Accounting/RecurringInvoiceFactory.php 查看文件

66
         ?Carbon $startDate = null,
66
         ?Carbon $startDate = null,
67
         ?EndType $endType = null
67
         ?EndType $endType = null
68
     ): static {
68
     ): static {
69
-        $frequency ??= $this->faker->randomElement(Frequency::class);
70
-        $endType ??= EndType::Never;
71
-
72
-        // Adjust the start date range based on frequency
73
-        $startDate = match ($frequency) {
74
-            Frequency::Daily => Carbon::parse($this->faker->dateTimeBetween('-30 days')), // At most 30 days back
75
-            default => $startDate ?? Carbon::parse($this->faker->dateTimeBetween('-1 year')),
76
-        };
77
-
78
-        return match ($frequency) {
79
-            Frequency::Daily => $this->withDailySchedule($startDate, $endType),
80
-            Frequency::Weekly => $this->withWeeklySchedule($startDate, $endType),
81
-            Frequency::Monthly => $this->withMonthlySchedule($startDate, $endType),
82
-            Frequency::Yearly => $this->withYearlySchedule($startDate, $endType),
83
-            Frequency::Custom => $this->withCustomSchedule($startDate, $endType),
84
-        };
69
+        return $this->afterCreating(function (RecurringInvoice $recurringInvoice) use ($frequency, $endType, $startDate) {
70
+            $this->ensureLineItems($recurringInvoice);
71
+
72
+            $frequency ??= $this->faker->randomElement(Frequency::class);
73
+            $endType ??= EndType::Never;
74
+
75
+            // Adjust the start date range based on frequency
76
+            $startDate = match ($frequency) {
77
+                Frequency::Daily => Carbon::parse($this->faker->dateTimeBetween('-30 days')), // At most 30 days back
78
+                default => $startDate ?? Carbon::parse($this->faker->dateTimeBetween('-1 year')),
79
+            };
80
+
81
+            $state = match ($frequency) {
82
+                Frequency::Daily => $this->withDailySchedule($startDate, $endType),
83
+                Frequency::Weekly => $this->withWeeklySchedule($startDate, $endType),
84
+                Frequency::Monthly => $this->withMonthlySchedule($startDate, $endType),
85
+                Frequency::Yearly => $this->withYearlySchedule($startDate, $endType),
86
+                Frequency::Custom => $this->withCustomSchedule($startDate, $endType),
87
+            };
88
+
89
+            $state->callAfterCreating(collect([$recurringInvoice]));
90
+        });
85
     }
91
     }
86
 
92
 
87
     protected function withDailySchedule(Carbon $startDate, EndType $endType): static
93
     protected function withDailySchedule(Carbon $startDate, EndType $endType): static
88
     {
94
     {
89
-        return $this->state([
90
-            'frequency' => Frequency::Daily,
91
-            'start_date' => $startDate,
92
-            'end_type' => $endType,
93
-        ]);
95
+        return $this->afterCreating(function (RecurringInvoice $recurringInvoice) use ($startDate, $endType) {
96
+            $this->ensureLineItems($recurringInvoice);
97
+
98
+            $recurringInvoice->updateQuietly([
99
+                'frequency' => Frequency::Daily,
100
+                'start_date' => $startDate,
101
+                'end_type' => $endType,
102
+            ]);
103
+        });
94
     }
104
     }
95
 
105
 
96
     protected function withWeeklySchedule(Carbon $startDate, EndType $endType): static
106
     protected function withWeeklySchedule(Carbon $startDate, EndType $endType): static
97
     {
107
     {
98
-        return $this->state([
99
-            'frequency' => Frequency::Weekly,
100
-            'day_of_week' => DayOfWeek::from($startDate->dayOfWeek),
101
-            'start_date' => $startDate,
102
-            'end_type' => $endType,
103
-        ]);
108
+        return $this->afterCreating(function (RecurringInvoice $recurringInvoice) use ($startDate, $endType) {
109
+            $this->ensureLineItems($recurringInvoice);
110
+
111
+            $recurringInvoice->updateQuietly([
112
+                'frequency' => Frequency::Weekly,
113
+                'day_of_week' => DayOfWeek::from($startDate->dayOfWeek),
114
+                'start_date' => $startDate,
115
+                'end_type' => $endType,
116
+            ]);
117
+        });
104
     }
118
     }
105
 
119
 
106
     protected function withMonthlySchedule(Carbon $startDate, EndType $endType): static
120
     protected function withMonthlySchedule(Carbon $startDate, EndType $endType): static
107
     {
121
     {
108
-        return $this->state([
109
-            'frequency' => Frequency::Monthly,
110
-            'day_of_month' => DayOfMonth::from($startDate->day),
111
-            'start_date' => $startDate,
112
-            'end_type' => $endType,
113
-        ]);
122
+        return $this->afterCreating(function (RecurringInvoice $recurringInvoice) use ($startDate, $endType) {
123
+            $this->ensureLineItems($recurringInvoice);
124
+
125
+            $recurringInvoice->updateQuietly([
126
+                'frequency' => Frequency::Monthly,
127
+                'day_of_month' => DayOfMonth::from($startDate->day),
128
+                'start_date' => $startDate,
129
+                'end_type' => $endType,
130
+            ]);
131
+        });
114
     }
132
     }
115
 
133
 
116
     protected function withYearlySchedule(Carbon $startDate, EndType $endType): static
134
     protected function withYearlySchedule(Carbon $startDate, EndType $endType): static
117
     {
135
     {
118
-        return $this->state([
119
-            'frequency' => Frequency::Yearly,
120
-            'month' => Month::from($startDate->month),
121
-            'day_of_month' => DayOfMonth::from($startDate->day),
122
-            'start_date' => $startDate,
123
-            'end_type' => $endType,
124
-        ]);
136
+        return $this->afterCreating(function (RecurringInvoice $recurringInvoice) use ($startDate, $endType) {
137
+            $this->ensureLineItems($recurringInvoice);
138
+
139
+            $recurringInvoice->updateQuietly([
140
+                'frequency' => Frequency::Yearly,
141
+                'month' => Month::from($startDate->month),
142
+                'day_of_month' => DayOfMonth::from($startDate->day),
143
+                'start_date' => $startDate,
144
+                'end_type' => $endType,
145
+            ]);
146
+        });
125
     }
147
     }
126
 
148
 
127
     protected function withCustomSchedule(
149
     protected function withCustomSchedule(
130
         ?IntervalType $intervalType = null,
152
         ?IntervalType $intervalType = null,
131
         ?int $intervalValue = null
153
         ?int $intervalValue = null
132
     ): static {
154
     ): static {
133
-        $intervalType ??= $this->faker->randomElement(IntervalType::class);
134
-        $intervalValue ??= match ($intervalType) {
135
-            IntervalType::Day => $this->faker->numberBetween(1, 7),
136
-            IntervalType::Week => $this->faker->numberBetween(1, 4),
137
-            IntervalType::Month => $this->faker->numberBetween(1, 3),
138
-            IntervalType::Year => 1,
139
-        };
140
-
141
-        $state = [
142
-            'frequency' => Frequency::Custom,
143
-            'interval_type' => $intervalType,
144
-            'interval_value' => $intervalValue,
145
-            'start_date' => $startDate,
146
-            'end_type' => $endType,
147
-        ];
155
+        return $this->afterCreating(function (RecurringInvoice $recurringInvoice) use ($intervalType, $intervalValue, $startDate, $endType) {
156
+            $this->ensureLineItems($recurringInvoice);
148
 
157
 
149
-        // Add interval-specific attributes
150
-        switch ($intervalType) {
151
-            case IntervalType::Day:
152
-                // No additional attributes needed
153
-                break;
158
+            $intervalType ??= $this->faker->randomElement(IntervalType::class);
159
+            $intervalValue ??= match ($intervalType) {
160
+                IntervalType::Day => $this->faker->numberBetween(1, 7),
161
+                IntervalType::Week => $this->faker->numberBetween(1, 4),
162
+                IntervalType::Month => $this->faker->numberBetween(1, 3),
163
+                IntervalType::Year => 1,
164
+            };
154
 
165
 
155
-            case IntervalType::Week:
156
-                $state['day_of_week'] = DayOfWeek::from($startDate->dayOfWeek);
166
+            $state = [
167
+                'frequency' => Frequency::Custom,
168
+                'interval_type' => $intervalType,
169
+                'interval_value' => $intervalValue,
170
+                'start_date' => $startDate,
171
+                'end_type' => $endType,
172
+            ];
157
 
173
 
158
-                break;
174
+            // Add interval-specific attributes
175
+            switch ($intervalType) {
176
+                case IntervalType::Day:
177
+                    // No additional attributes needed
178
+                    break;
159
 
179
 
160
-            case IntervalType::Month:
161
-                $state['day_of_month'] = DayOfMonth::from($startDate->day);
180
+                case IntervalType::Week:
181
+                    $state['day_of_week'] = DayOfWeek::from($startDate->dayOfWeek);
162
 
182
 
163
-                break;
183
+                    break;
164
 
184
 
165
-            case IntervalType::Year:
166
-                $state['month'] = Month::from($startDate->month);
167
-                $state['day_of_month'] = DayOfMonth::from($startDate->day);
185
+                case IntervalType::Month:
186
+                    $state['day_of_month'] = DayOfMonth::from($startDate->day);
168
 
187
 
169
-                break;
170
-        }
188
+                    break;
189
+
190
+                case IntervalType::Year:
191
+                    $state['month'] = Month::from($startDate->month);
192
+                    $state['day_of_month'] = DayOfMonth::from($startDate->day);
171
 
193
 
172
-        return $this->state($state);
194
+                    break;
195
+            }
196
+
197
+            return $recurringInvoice->updateQuietly($state);
198
+        });
173
     }
199
     }
174
 
200
 
175
     public function endAfter(int $occurrences = 12): static
201
     public function endAfter(int $occurrences = 12): static
208
                 $recurringInvoice->refresh();
234
                 $recurringInvoice->refresh();
209
             }
235
             }
210
 
236
 
211
-            if (! $recurringInvoice->canBeApproved()) {
212
-                return;
213
-            }
214
-
215
             $approvedAt = $recurringInvoice->start_date
237
             $approvedAt = $recurringInvoice->start_date
216
                 ? $recurringInvoice->start_date->copy()->subDays($this->faker->numberBetween(1, 7))
238
                 ? $recurringInvoice->start_date->copy()->subDays($this->faker->numberBetween(1, 7))
217
                 : now()->subDays($this->faker->numberBetween(1, 30));
239
                 : now()->subDays($this->faker->numberBetween(1, 30));
230
     public function ended(): static
252
     public function ended(): static
231
     {
253
     {
232
         return $this->afterCreating(function (RecurringInvoice $recurringInvoice) {
254
         return $this->afterCreating(function (RecurringInvoice $recurringInvoice) {
255
+            $this->ensureLineItems($recurringInvoice);
256
+
233
             if (! $recurringInvoice->canBeEnded()) {
257
             if (! $recurringInvoice->canBeEnded()) {
234
                 $this->active()->callAfterCreating(collect([$recurringInvoice]));
258
                 $this->active()->callAfterCreating(collect([$recurringInvoice]));
235
             }
259
             }
236
 
260
 
237
-            $endedAt = now()->subDays($this->faker->numberBetween(1, 30));
261
+            $endedAt = $recurringInvoice->last_date
262
+                ? $recurringInvoice->last_date->copy()->addDays($this->faker->numberBetween(1, 7))
263
+                : now()->subDays($this->faker->numberBetween(1, 30));
238
 
264
 
239
-            $recurringInvoice->update([
265
+            $recurringInvoice->updateQuietly([
240
                 'ended_at' => $endedAt,
266
                 'ended_at' => $endedAt,
241
                 'status' => RecurringInvoiceStatus::Ended,
267
                 'status' => RecurringInvoiceStatus::Ended,
242
             ]);
268
             ]);
247
     {
273
     {
248
         return $this->afterCreating(function (RecurringInvoice $recurringInvoice) {
274
         return $this->afterCreating(function (RecurringInvoice $recurringInvoice) {
249
             $this->ensureLineItems($recurringInvoice);
275
             $this->ensureLineItems($recurringInvoice);
250
-
251
-            $nextDate = $recurringInvoice->calculateNextDate();
252
-
253
-            if ($nextDate) {
254
-                $recurringInvoice->updateQuietly([
255
-                    'next_date' => $nextDate,
256
-                ]);
257
-            }
258
         });
276
         });
259
     }
277
     }
260
 
278
 

+ 9
- 28
database/factories/CompanyFactory.php 查看文件

2
 
2
 
3
 namespace Database\Factories;
3
 namespace Database\Factories;
4
 
4
 
5
-use App\Enums\Accounting\Frequency;
6
 use App\Models\Accounting\Bill;
5
 use App\Models\Accounting\Bill;
7
 use App\Models\Accounting\Estimate;
6
 use App\Models\Accounting\Estimate;
8
 use App\Models\Accounting\Invoice;
7
 use App\Models\Accounting\Invoice;
178
             // Draft recurring invoices (no schedule)
177
             // Draft recurring invoices (no schedule)
179
             RecurringInvoice::factory()
178
             RecurringInvoice::factory()
180
                 ->count($draftCount)
179
                 ->count($draftCount)
181
-                ->withLineItems()
182
                 ->create([
180
                 ->create([
183
                     'company_id' => $company->id,
181
                     'company_id' => $company->id,
184
                     'created_by' => $company->user_id,
182
                     'created_by' => $company->user_id,
188
             // Draft recurring invoices with schedule
186
             // Draft recurring invoices with schedule
189
             RecurringInvoice::factory()
187
             RecurringInvoice::factory()
190
                 ->count($scheduledCount)
188
                 ->count($scheduledCount)
191
-                ->withLineItems()
192
                 ->withSchedule()
189
                 ->withSchedule()
193
                 ->create([
190
                 ->create([
194
                     'company_id' => $company->id,
191
                     'company_id' => $company->id,
197
                 ]);
194
                 ]);
198
 
195
 
199
             // Active recurring invoices with various schedules and historical invoices
196
             // Active recurring invoices with various schedules and historical invoices
200
-            $frequencies = [
201
-                Frequency::Daily,
202
-                Frequency::Weekly,
203
-                Frequency::Monthly,
204
-                Frequency::Yearly,
205
-                Frequency::Custom,
206
-            ];
207
-
208
-            foreach (array_chunk(range(1, $activeCount), (int) ceil($activeCount / count($frequencies))) as $chunk) {
209
-                RecurringInvoice::factory()
210
-                    ->count(count($chunk))
211
-                    ->withLineItems()
212
-                    ->withSchedule(fake()->randomElement($frequencies)) // Randomize frequency
213
-                    ->active()
214
-                    ->create([
215
-                        'company_id' => $company->id,
216
-                        'created_by' => $company->user_id,
217
-                        'updated_by' => $company->user_id,
218
-                    ]);
219
-            }
197
+            RecurringInvoice::factory()
198
+                ->count($activeCount)
199
+                ->active()
200
+                ->create([
201
+                    'company_id' => $company->id,
202
+                    'created_by' => $company->user_id,
203
+                    'updated_by' => $company->user_id,
204
+                ]);
220
 
205
 
221
             // Manually ended recurring invoices
206
             // Manually ended recurring invoices
222
             RecurringInvoice::factory()
207
             RecurringInvoice::factory()
223
                 ->count($endedCount)
208
                 ->count($endedCount)
224
-                ->withLineItems()
225
-                ->withSchedule()
226
                 ->ended()
209
                 ->ended()
227
                 ->create([
210
                 ->create([
228
                     'company_id' => $company->id,
211
                     'company_id' => $company->id,
233
             // Completed recurring invoices (reached end conditions)
216
             // Completed recurring invoices (reached end conditions)
234
             RecurringInvoice::factory()
217
             RecurringInvoice::factory()
235
                 ->count($completedCount)
218
                 ->count($completedCount)
236
-                ->withLineItems()
237
-                ->withSchedule()
238
-                ->endAfter($this->faker->numberBetween(5, 12))
239
                 ->active()
219
                 ->active()
220
+                ->endAfter($this->faker->numberBetween(5, 12))
240
                 ->create([
221
                 ->create([
241
                     'company_id' => $company->id,
222
                     'company_id' => $company->id,
242
                     'created_by' => $company->user_id,
223
                     'created_by' => $company->user_id,

正在加载...
取消
保存