Andrew Wallo hace 9 meses
padre
commit
ac0dc36cd4

+ 2
- 2
app/Filament/Company/Resources/Sales/RecurringInvoiceResource/Pages/ViewRecurringInvoice.php Ver fichero

@@ -58,7 +58,7 @@ class ViewRecurringInvoice extends ViewRecord
58 58
                     ->info()
59 59
                     ->title('Schedule Not Set')
60 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 62
                     ->columnSpanFull()
63 63
                     ->actions([
64 64
                         RecurringInvoice::getUpdateScheduleAction(Action::class)
@@ -68,7 +68,7 @@ class ViewRecurringInvoice extends ViewRecord
68 68
                     ->info()
69 69
                     ->title('Ready to Approve')
70 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 72
                     ->columnSpanFull()
73 73
                     ->actions([
74 74
                         RecurringInvoice::getApproveDraftAction(Action::class)

+ 9
- 7
app/Models/Accounting/RecurringInvoice.php Ver fichero

@@ -177,7 +177,7 @@ class RecurringInvoice extends Document
177 177
 
178 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 183
     public function canBeEnded(): bool
@@ -187,15 +187,17 @@ class RecurringInvoice extends Document
187 187
 
188 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 203
     public function getScheduleDescription(): string

+ 1
- 1
app/Observers/RecurringInvoiceObserver.php Ver fichero

@@ -13,7 +13,7 @@ class RecurringInvoiceObserver
13 13
     {
14 14
         if (
15 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 18
             $recurringInvoice->next_date = $recurringInvoice->calculateNextDate();
19 19
         }

+ 12
- 12
app/Support/ScheduleHandler.php Ver fichero

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

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

+ 42
- 42
composer.lock Ver fichero

@@ -4,7 +4,7 @@
4 4
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5 5
         "This file is @generated automatically"
6 6
     ],
7
-    "content-hash": "decc627f2a7bd0c6546114ebb1f500f9",
7
+    "content-hash": "861a1aea38f7af0893ee251608dc7cfa",
8 8
     "packages": [
9 9
         {
10 10
             "name": "akaunting/laravel-money",
@@ -1735,16 +1735,16 @@
1735 1735
         },
1736 1736
         {
1737 1737
             "name": "filament/actions",
1738
-            "version": "v3.2.133",
1738
+            "version": "v3.2.132",
1739 1739
             "source": {
1740 1740
                 "type": "git",
1741 1741
                 "url": "https://github.com/filamentphp/actions.git",
1742
-                "reference": "33464f1583217b5eb12364b617b27abe5315eb88"
1742
+                "reference": "887b9e5552658a37098e7a279196a4d188d94f50"
1743 1743
             },
1744 1744
             "dist": {
1745 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 1748
                 "shasum": ""
1749 1749
             },
1750 1750
             "require": {
@@ -1756,7 +1756,7 @@
1756 1756
                 "illuminate/contracts": "^10.45|^11.0",
1757 1757
                 "illuminate/database": "^10.45|^11.0",
1758 1758
                 "illuminate/support": "^10.45|^11.0",
1759
-                "league/csv": "^9.16",
1759
+                "league/csv": "^9.14",
1760 1760
                 "openspout/openspout": "^4.23",
1761 1761
                 "php": "^8.1",
1762 1762
                 "spatie/laravel-package-tools": "^1.9"
@@ -1784,20 +1784,20 @@
1784 1784
                 "issues": "https://github.com/filamentphp/filament/issues",
1785 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 1790
             "name": "filament/filament",
1791
-            "version": "v3.2.133",
1791
+            "version": "v3.2.132",
1792 1792
             "source": {
1793 1793
                 "type": "git",
1794 1794
                 "url": "https://github.com/filamentphp/panels.git",
1795
-                "reference": "74550888c1c79761218aece3c339ca0e0cc260e8"
1795
+                "reference": "54fcc0b883cc6622d1d9322d28c823ba6172f9ef"
1796 1796
             },
1797 1797
             "dist": {
1798 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 1801
                 "shasum": ""
1802 1802
             },
1803 1803
             "require": {
@@ -1849,20 +1849,20 @@
1849 1849
                 "issues": "https://github.com/filamentphp/filament/issues",
1850 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 1855
             "name": "filament/forms",
1856
-            "version": "v3.2.133",
1856
+            "version": "v3.2.132",
1857 1857
             "source": {
1858 1858
                 "type": "git",
1859 1859
                 "url": "https://github.com/filamentphp/forms.git",
1860
-                "reference": "20473c9eec7afa3ee618d2f86c7c449b3723d9fb"
1860
+                "reference": "4abbf867f060483699f3cb8e1c1c8f4469b7980f"
1861 1861
             },
1862 1862
             "dist": {
1863 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 1866
                 "shasum": ""
1867 1867
             },
1868 1868
             "require": {
@@ -1905,20 +1905,20 @@
1905 1905
                 "issues": "https://github.com/filamentphp/filament/issues",
1906 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 1911
             "name": "filament/infolists",
1912
-            "version": "v3.2.133",
1912
+            "version": "v3.2.132",
1913 1913
             "source": {
1914 1914
                 "type": "git",
1915 1915
                 "url": "https://github.com/filamentphp/infolists.git",
1916
-                "reference": "d3ee1eb508561f2b101c69cdb45c309539948d86"
1916
+                "reference": "8c0344fc603085da8f385ed6a022aacbe3aa49fb"
1917 1917
             },
1918 1918
             "dist": {
1919 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 1922
                 "shasum": ""
1923 1923
             },
1924 1924
             "require": {
@@ -1956,20 +1956,20 @@
1956 1956
                 "issues": "https://github.com/filamentphp/filament/issues",
1957 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 1962
             "name": "filament/notifications",
1963
-            "version": "v3.2.133",
1963
+            "version": "v3.2.132",
1964 1964
             "source": {
1965 1965
                 "type": "git",
1966 1966
                 "url": "https://github.com/filamentphp/notifications.git",
1967
-                "reference": "16cf5dbcbaf88cd9fff8d06aad866cb314b8bb64"
1967
+                "reference": "c19df07c801c5550de0d30957c5a316f53019533"
1968 1968
             },
1969 1969
             "dist": {
1970 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 1973
                 "shasum": ""
1974 1974
             },
1975 1975
             "require": {
@@ -2008,20 +2008,20 @@
2008 2008
                 "issues": "https://github.com/filamentphp/filament/issues",
2009 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 2014
             "name": "filament/support",
2015
-            "version": "v3.2.133",
2015
+            "version": "v3.2.132",
2016 2016
             "source": {
2017 2017
                 "type": "git",
2018 2018
                 "url": "https://github.com/filamentphp/support.git",
2019
-                "reference": "38fd76ae4f96b53e6f98cbb7bad3f05ad5032cee"
2019
+                "reference": "0bd91d5b937b0ae50394a976ba5fed9506581943"
2020 2020
             },
2021 2021
             "dist": {
2022 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 2025
                 "shasum": ""
2026 2026
             },
2027 2027
             "require": {
@@ -2067,20 +2067,20 @@
2067 2067
                 "issues": "https://github.com/filamentphp/filament/issues",
2068 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 2073
             "name": "filament/tables",
2074
-            "version": "v3.2.133",
2074
+            "version": "v3.2.132",
2075 2075
             "source": {
2076 2076
                 "type": "git",
2077 2077
                 "url": "https://github.com/filamentphp/tables.git",
2078
-                "reference": "6cbbea0bfd966ca2f26988c0fac4e02caebddf4a"
2078
+                "reference": "e34f63f89ef672f8e810c2e181665d718e84ff37"
2079 2079
             },
2080 2080
             "dist": {
2081 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 2084
                 "shasum": ""
2085 2085
             },
2086 2086
             "require": {
@@ -2119,20 +2119,20 @@
2119 2119
                 "issues": "https://github.com/filamentphp/filament/issues",
2120 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 2125
             "name": "filament/widgets",
2126
-            "version": "v3.2.133",
2126
+            "version": "v3.2.132",
2127 2127
             "source": {
2128 2128
                 "type": "git",
2129 2129
                 "url": "https://github.com/filamentphp/widgets.git",
2130
-                "reference": "9f6674daceced7d5045494d0bf7e1d2908ea439d"
2130
+                "reference": "869a419fe42e2cf1b9461f2d1e702e2fcad030ae"
2131 2131
             },
2132 2132
             "dist": {
2133 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 2136
                 "shasum": ""
2137 2137
             },
2138 2138
             "require": {
@@ -2163,7 +2163,7 @@
2163 2163
                 "issues": "https://github.com/filamentphp/filament/issues",
2164 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 2169
             "name": "firebase/php-jwt",

+ 104
- 86
database/factories/Accounting/RecurringInvoiceFactory.php Ver fichero

@@ -66,62 +66,84 @@ class RecurringInvoiceFactory extends Factory
66 66
         ?Carbon $startDate = null,
67 67
         ?EndType $endType = null
68 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 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 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 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 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 149
     protected function withCustomSchedule(
@@ -130,46 +152,50 @@ class RecurringInvoiceFactory extends Factory
130 152
         ?IntervalType $intervalType = null,
131 153
         ?int $intervalValue = null
132 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 201
     public function endAfter(int $occurrences = 12): static
@@ -208,10 +234,6 @@ class RecurringInvoiceFactory extends Factory
208 234
                 $recurringInvoice->refresh();
209 235
             }
210 236
 
211
-            if (! $recurringInvoice->canBeApproved()) {
212
-                return;
213
-            }
214
-
215 237
             $approvedAt = $recurringInvoice->start_date
216 238
                 ? $recurringInvoice->start_date->copy()->subDays($this->faker->numberBetween(1, 7))
217 239
                 : now()->subDays($this->faker->numberBetween(1, 30));
@@ -230,13 +252,17 @@ class RecurringInvoiceFactory extends Factory
230 252
     public function ended(): static
231 253
     {
232 254
         return $this->afterCreating(function (RecurringInvoice $recurringInvoice) {
255
+            $this->ensureLineItems($recurringInvoice);
256
+
233 257
             if (! $recurringInvoice->canBeEnded()) {
234 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 266
                 'ended_at' => $endedAt,
241 267
                 'status' => RecurringInvoiceStatus::Ended,
242 268
             ]);
@@ -247,14 +273,6 @@ class RecurringInvoiceFactory extends Factory
247 273
     {
248 274
         return $this->afterCreating(function (RecurringInvoice $recurringInvoice) {
249 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 Ver fichero

@@ -2,7 +2,6 @@
2 2
 
3 3
 namespace Database\Factories;
4 4
 
5
-use App\Enums\Accounting\Frequency;
6 5
 use App\Models\Accounting\Bill;
7 6
 use App\Models\Accounting\Estimate;
8 7
 use App\Models\Accounting\Invoice;
@@ -178,7 +177,6 @@ class CompanyFactory extends Factory
178 177
             // Draft recurring invoices (no schedule)
179 178
             RecurringInvoice::factory()
180 179
                 ->count($draftCount)
181
-                ->withLineItems()
182 180
                 ->create([
183 181
                     'company_id' => $company->id,
184 182
                     'created_by' => $company->user_id,
@@ -188,7 +186,6 @@ class CompanyFactory extends Factory
188 186
             // Draft recurring invoices with schedule
189 187
             RecurringInvoice::factory()
190 188
                 ->count($scheduledCount)
191
-                ->withLineItems()
192 189
                 ->withSchedule()
193 190
                 ->create([
194 191
                     'company_id' => $company->id,
@@ -197,32 +194,18 @@ class CompanyFactory extends Factory
197 194
                 ]);
198 195
 
199 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 206
             // Manually ended recurring invoices
222 207
             RecurringInvoice::factory()
223 208
                 ->count($endedCount)
224
-                ->withLineItems()
225
-                ->withSchedule()
226 209
                 ->ended()
227 210
                 ->create([
228 211
                     'company_id' => $company->id,
@@ -233,10 +216,8 @@ class CompanyFactory extends Factory
233 216
             // Completed recurring invoices (reached end conditions)
234 217
             RecurringInvoice::factory()
235 218
                 ->count($completedCount)
236
-                ->withLineItems()
237
-                ->withSchedule()
238
-                ->endAfter($this->faker->numberBetween(5, 12))
239 219
                 ->active()
220
+                ->endAfter($this->faker->numberBetween(5, 12))
240 221
                 ->create([
241 222
                     'company_id' => $company->id,
242 223
                     'created_by' => $company->user_id,

Loading…
Cancelar
Guardar