|
@@ -67,6 +67,19 @@ class BudgetResource extends Resource
|
67
|
67
|
->columnSpan(1)
|
68
|
68
|
->required(),
|
69
|
69
|
|
|
70
|
+ Forms\Components\TextInput::make('total_amount')
|
|
71
|
+ ->label('Total Amount')
|
|
72
|
+ ->numeric()
|
|
73
|
+ ->required()
|
|
74
|
+ ->columnSpan(1)
|
|
75
|
+ ->suffixAction(
|
|
76
|
+ Forms\Components\Actions\Action::make('disperse')
|
|
77
|
+ ->label('Disperse')
|
|
78
|
+ ->icon('heroicon-m-bars-arrow-down')
|
|
79
|
+ ->color('primary')
|
|
80
|
+ ->action(fn (Forms\Set $set, Forms\Get $get, $state) => self::disperseTotalAmount($set, $get, $state))
|
|
81
|
+ ),
|
|
82
|
+
|
70
|
83
|
CustomSection::make('Budget Allocations')
|
71
|
84
|
->contained(false)
|
72
|
85
|
->columns(4)
|
|
@@ -98,6 +111,66 @@ class BudgetResource extends Resource
|
98
|
111
|
]);
|
99
|
112
|
}
|
100
|
113
|
|
|
114
|
+ /**
|
|
115
|
+ * Disperses the total amount across the budget items based on the selected interval.
|
|
116
|
+ */
|
|
117
|
+ private static function disperseTotalAmount(Forms\Set $set, Forms\Get $get, float $totalAmount): void
|
|
118
|
+ {
|
|
119
|
+ $startDate = $get('../../start_date');
|
|
120
|
+ $endDate = $get('../../end_date');
|
|
121
|
+ $intervalType = $get('../../interval_type');
|
|
122
|
+
|
|
123
|
+ if (! $startDate || ! $endDate || ! $intervalType || $totalAmount <= 0) {
|
|
124
|
+ return;
|
|
125
|
+ }
|
|
126
|
+
|
|
127
|
+ // Generate labels based on interval type (must match `getAllocationFields()`)
|
|
128
|
+ $labels = self::generateFormattedLabels($startDate, $endDate, $intervalType);
|
|
129
|
+ $numPeriods = count($labels);
|
|
130
|
+
|
|
131
|
+ if ($numPeriods === 0) {
|
|
132
|
+ return;
|
|
133
|
+ }
|
|
134
|
+
|
|
135
|
+ // Calculate base allocation and handle rounding
|
|
136
|
+ $baseAmount = floor($totalAmount / $numPeriods);
|
|
137
|
+ $remainder = $totalAmount - ($baseAmount * $numPeriods);
|
|
138
|
+
|
|
139
|
+ // Assign amounts to the correct fields using labels
|
|
140
|
+ foreach ($labels as $index => $label) {
|
|
141
|
+ $amount = $baseAmount + ($index === 0 ? $remainder : 0);
|
|
142
|
+ $set("amounts.{$label}", $amount); // Now correctly assigns to the right field
|
|
143
|
+ }
|
|
144
|
+ }
|
|
145
|
+
|
|
146
|
+ /**
|
|
147
|
+ * Generates formatted labels for the budget allocation fields based on the selected interval type.
|
|
148
|
+ */
|
|
149
|
+ private static function generateFormattedLabels(string $startDate, string $endDate, string $intervalType): array
|
|
150
|
+ {
|
|
151
|
+ $start = Carbon::parse($startDate);
|
|
152
|
+ $end = Carbon::parse($endDate);
|
|
153
|
+ $labels = [];
|
|
154
|
+
|
|
155
|
+ while ($start->lte($end)) {
|
|
156
|
+ $labels[] = match ($intervalType) {
|
|
157
|
+ 'month' => $start->format('M'), // Example: Jan, Feb, Mar
|
|
158
|
+ 'quarter' => 'Q' . $start->quarter, // Example: Q1, Q2, Q3
|
|
159
|
+ 'year' => (string) $start->year, // Example: 2024, 2025
|
|
160
|
+ default => '',
|
|
161
|
+ };
|
|
162
|
+
|
|
163
|
+ match ($intervalType) {
|
|
164
|
+ 'month' => $start->addMonth(),
|
|
165
|
+ 'quarter' => $start->addQuarter(),
|
|
166
|
+ 'year' => $start->addYear(),
|
|
167
|
+ default => null,
|
|
168
|
+ };
|
|
169
|
+ }
|
|
170
|
+
|
|
171
|
+ return $labels;
|
|
172
|
+ }
|
|
173
|
+
|
101
|
174
|
private static function getAllocationFields(?string $startDate, ?string $endDate, ?string $intervalType): array
|
102
|
175
|
{
|
103
|
176
|
if (! $startDate || ! $endDate || ! $intervalType) {
|