|
@@ -46,7 +46,6 @@ class BudgetResource extends Resource
|
46
|
46
|
->live()
|
47
|
47
|
->disabled(static fn (Forms\Get $get) => blank($get('start_date')))
|
48
|
48
|
->minDate(fn (Forms\Get $get) => match (BudgetIntervalType::parse($get('interval_type'))) {
|
49
|
|
- BudgetIntervalType::Week => Carbon::parse($get('start_date'))->addWeek(),
|
50
|
49
|
BudgetIntervalType::Month => Carbon::parse($get('start_date'))->addMonth(),
|
51
|
50
|
BudgetIntervalType::Quarter => Carbon::parse($get('start_date'))->addQuarter(),
|
52
|
51
|
BudgetIntervalType::Year => Carbon::parse($get('start_date'))->addYear(),
|
|
@@ -57,144 +56,144 @@ class BudgetResource extends Resource
|
57
|
56
|
->columnSpanFull(),
|
58
|
57
|
]),
|
59
|
58
|
|
60
|
|
- Forms\Components\Section::make('Budget Items')
|
61
|
|
- ->headerActions([
|
62
|
|
- Forms\Components\Actions\Action::make('addAccounts')
|
63
|
|
- ->label('Add Accounts')
|
64
|
|
- ->icon('heroicon-m-plus')
|
65
|
|
- ->outlined()
|
66
|
|
- ->color('primary')
|
67
|
|
- ->form(fn (Forms\Get $get) => [
|
68
|
|
- Forms\Components\Select::make('selected_accounts')
|
69
|
|
- ->label('Choose Accounts to Add')
|
70
|
|
- ->options(function () use ($get) {
|
71
|
|
- $existingAccounts = collect($get('budgetItems'))->pluck('account_id')->toArray();
|
72
|
|
-
|
73
|
|
- return Account::query()
|
74
|
|
- ->budgetable()
|
75
|
|
- ->whereNotIn('id', $existingAccounts) // Prevent duplicate selections
|
76
|
|
- ->pluck('name', 'id');
|
77
|
|
- })
|
78
|
|
- ->searchable()
|
79
|
|
- ->multiple()
|
80
|
|
- ->hint('Select the accounts you want to add to this budget'),
|
81
|
|
- ])
|
82
|
|
- ->action(static fn (Forms\Set $set, Forms\Get $get, array $data) => self::addSelectedAccounts($set, $get, $data)),
|
83
|
|
-
|
84
|
|
- Forms\Components\Actions\Action::make('addAllAccounts')
|
85
|
|
- ->label('Add All Accounts')
|
86
|
|
- ->icon('heroicon-m-folder-plus')
|
87
|
|
- ->outlined()
|
88
|
|
- ->color('primary')
|
89
|
|
- ->action(static fn (Forms\Set $set, Forms\Get $get) => self::addAllAccounts($set, $get))
|
90
|
|
- ->hidden(static fn (Forms\Get $get) => filled($get('budgetItems'))),
|
91
|
|
-
|
92
|
|
- Forms\Components\Actions\Action::make('increaseAllocations')
|
93
|
|
- ->label('Increase Allocations')
|
94
|
|
- ->icon('heroicon-m-arrow-up')
|
95
|
|
- ->outlined()
|
96
|
|
- ->color('success')
|
97
|
|
- ->form(fn (Forms\Get $get) => [
|
98
|
|
- Forms\Components\Select::make('increase_type')
|
99
|
|
- ->label('Increase Type')
|
100
|
|
- ->options([
|
101
|
|
- 'percentage' => 'Percentage (%)',
|
102
|
|
- 'fixed' => 'Fixed Amount',
|
103
|
|
- ])
|
104
|
|
- ->default('percentage')
|
105
|
|
- ->live()
|
106
|
|
- ->required(),
|
107
|
|
-
|
108
|
|
- Forms\Components\TextInput::make('percentage')
|
109
|
|
- ->label('Increase by %')
|
110
|
|
- ->numeric()
|
111
|
|
- ->suffix('%')
|
112
|
|
- ->required()
|
113
|
|
- ->hidden(fn (Forms\Get $get) => $get('increase_type') !== 'percentage'),
|
114
|
|
-
|
115
|
|
- Forms\Components\TextInput::make('fixed_amount')
|
116
|
|
- ->label('Increase by Fixed Amount')
|
117
|
|
- ->numeric()
|
118
|
|
- ->suffix('USD')
|
119
|
|
- ->required()
|
120
|
|
- ->hidden(fn (Forms\Get $get) => $get('increase_type') !== 'fixed'),
|
121
|
|
-
|
122
|
|
- Forms\Components\Select::make('apply_to_accounts')
|
123
|
|
- ->label('Apply to Accounts')
|
124
|
|
- ->options(function () use ($get) {
|
125
|
|
- $budgetItems = $get('budgetItems') ?? [];
|
126
|
|
- $accountIds = collect($budgetItems)
|
127
|
|
- ->pluck('account_id')
|
128
|
|
- ->filter()
|
129
|
|
- ->unique()
|
130
|
|
- ->toArray();
|
131
|
|
-
|
132
|
|
- return Account::query()
|
133
|
|
- ->whereIn('id', $accountIds)
|
134
|
|
- ->pluck('name', 'id')
|
135
|
|
- ->toArray();
|
136
|
|
- })
|
137
|
|
- ->searchable()
|
138
|
|
- ->multiple()
|
139
|
|
- ->hint('Leave blank to apply to all accounts'),
|
140
|
|
-
|
141
|
|
- Forms\Components\Select::make('apply_to_periods')
|
142
|
|
- ->label('Apply to Periods')
|
143
|
|
- ->options(static function () use ($get) {
|
144
|
|
- $startDate = $get('start_date');
|
145
|
|
- $endDate = $get('end_date');
|
146
|
|
- $intervalType = $get('interval_type');
|
147
|
|
-
|
148
|
|
- if (blank($startDate) || blank($endDate) || blank($intervalType)) {
|
149
|
|
- return [];
|
150
|
|
- }
|
151
|
|
-
|
152
|
|
- $labels = self::generateFormattedLabels($startDate, $endDate, $intervalType);
|
153
|
|
-
|
154
|
|
- return array_combine($labels, $labels);
|
155
|
|
- })
|
156
|
|
- ->searchable()
|
157
|
|
- ->multiple()
|
158
|
|
- ->hint('Leave blank to apply to all periods'),
|
159
|
|
- ])
|
160
|
|
- ->action(static fn (Forms\Set $set, Forms\Get $get, array $data) => self::increaseAllocations($set, $get, $data))
|
161
|
|
- ->visible(static fn (Forms\Get $get) => filled($get('budgetItems'))),
|
162
|
|
- ])
|
163
|
|
- ->schema([
|
164
|
|
- Forms\Components\Repeater::make('budgetItems')
|
165
|
|
- ->columns(4)
|
166
|
|
- ->hiddenLabel()
|
167
|
|
- ->schema([
|
168
|
|
- Forms\Components\Select::make('account_id')
|
169
|
|
- ->label('Account')
|
170
|
|
- ->options(Account::query()
|
171
|
|
- ->budgetable()
|
172
|
|
- ->pluck('name', 'id'))
|
173
|
|
- ->searchable()
|
174
|
|
- ->disableOptionsWhenSelectedInSiblingRepeaterItems()
|
175
|
|
- ->columnSpan(1)
|
176
|
|
- ->required(),
|
177
|
|
-
|
178
|
|
- Forms\Components\TextInput::make('total_amount')
|
179
|
|
- ->label('Total Amount')
|
180
|
|
- ->numeric()
|
181
|
|
- ->columnSpan(1)
|
182
|
|
- ->suffixAction(
|
183
|
|
- Forms\Components\Actions\Action::make('disperse')
|
184
|
|
- ->label('Disperse')
|
185
|
|
- ->icon('heroicon-m-bars-arrow-down')
|
186
|
|
- ->color('primary')
|
187
|
|
- ->action(static fn (Forms\Set $set, Forms\Get $get, $state) => self::disperseTotalAmount($set, $get, $state))
|
188
|
|
- ),
|
189
|
|
-
|
190
|
|
- CustomSection::make('Budget Allocations')
|
191
|
|
- ->contained(false)
|
192
|
|
- ->columns(4)
|
193
|
|
- ->schema(static fn (Forms\Get $get) => self::getAllocationFields($get('../../start_date'), $get('../../end_date'), $get('../../interval_type'))),
|
194
|
|
- ])
|
195
|
|
- ->defaultItems(0)
|
196
|
|
- ->addActionLabel('Add Budget Item'),
|
197
|
|
- ]),
|
|
59
|
+ // Forms\Components\Section::make('Budget Items')
|
|
60
|
+ // ->headerActions([
|
|
61
|
+ // Forms\Components\Actions\Action::make('addAccounts')
|
|
62
|
+ // ->label('Add Accounts')
|
|
63
|
+ // ->icon('heroicon-m-plus')
|
|
64
|
+ // ->outlined()
|
|
65
|
+ // ->color('primary')
|
|
66
|
+ // ->form(fn (Forms\Get $get) => [
|
|
67
|
+ // Forms\Components\Select::make('selected_accounts')
|
|
68
|
+ // ->label('Choose Accounts to Add')
|
|
69
|
+ // ->options(function () use ($get) {
|
|
70
|
+ // $existingAccounts = collect($get('budgetItems'))->pluck('account_id')->toArray();
|
|
71
|
+ //
|
|
72
|
+ // return Account::query()
|
|
73
|
+ // ->budgetable()
|
|
74
|
+ // ->whereNotIn('id', $existingAccounts) // Prevent duplicate selections
|
|
75
|
+ // ->pluck('name', 'id');
|
|
76
|
+ // })
|
|
77
|
+ // ->searchable()
|
|
78
|
+ // ->multiple()
|
|
79
|
+ // ->hint('Select the accounts you want to add to this budget'),
|
|
80
|
+ // ])
|
|
81
|
+ // ->action(static fn (Forms\Set $set, Forms\Get $get, array $data) => self::addSelectedAccounts($set, $get, $data)),
|
|
82
|
+ //
|
|
83
|
+ // Forms\Components\Actions\Action::make('addAllAccounts')
|
|
84
|
+ // ->label('Add All Accounts')
|
|
85
|
+ // ->icon('heroicon-m-folder-plus')
|
|
86
|
+ // ->outlined()
|
|
87
|
+ // ->color('primary')
|
|
88
|
+ // ->action(static fn (Forms\Set $set, Forms\Get $get) => self::addAllAccounts($set, $get))
|
|
89
|
+ // ->hidden(static fn (Forms\Get $get) => filled($get('budgetItems'))),
|
|
90
|
+ //
|
|
91
|
+ // Forms\Components\Actions\Action::make('increaseAllocations')
|
|
92
|
+ // ->label('Increase Allocations')
|
|
93
|
+ // ->icon('heroicon-m-arrow-up')
|
|
94
|
+ // ->outlined()
|
|
95
|
+ // ->color('success')
|
|
96
|
+ // ->form(fn (Forms\Get $get) => [
|
|
97
|
+ // Forms\Components\Select::make('increase_type')
|
|
98
|
+ // ->label('Increase Type')
|
|
99
|
+ // ->options([
|
|
100
|
+ // 'percentage' => 'Percentage (%)',
|
|
101
|
+ // 'fixed' => 'Fixed Amount',
|
|
102
|
+ // ])
|
|
103
|
+ // ->default('percentage')
|
|
104
|
+ // ->live()
|
|
105
|
+ // ->required(),
|
|
106
|
+ //
|
|
107
|
+ // Forms\Components\TextInput::make('percentage')
|
|
108
|
+ // ->label('Increase by %')
|
|
109
|
+ // ->numeric()
|
|
110
|
+ // ->suffix('%')
|
|
111
|
+ // ->required()
|
|
112
|
+ // ->hidden(fn (Forms\Get $get) => $get('increase_type') !== 'percentage'),
|
|
113
|
+ //
|
|
114
|
+ // Forms\Components\TextInput::make('fixed_amount')
|
|
115
|
+ // ->label('Increase by Fixed Amount')
|
|
116
|
+ // ->numeric()
|
|
117
|
+ // ->suffix('USD')
|
|
118
|
+ // ->required()
|
|
119
|
+ // ->hidden(fn (Forms\Get $get) => $get('increase_type') !== 'fixed'),
|
|
120
|
+ //
|
|
121
|
+ // Forms\Components\Select::make('apply_to_accounts')
|
|
122
|
+ // ->label('Apply to Accounts')
|
|
123
|
+ // ->options(function () use ($get) {
|
|
124
|
+ // $budgetItems = $get('budgetItems') ?? [];
|
|
125
|
+ // $accountIds = collect($budgetItems)
|
|
126
|
+ // ->pluck('account_id')
|
|
127
|
+ // ->filter()
|
|
128
|
+ // ->unique()
|
|
129
|
+ // ->toArray();
|
|
130
|
+ //
|
|
131
|
+ // return Account::query()
|
|
132
|
+ // ->whereIn('id', $accountIds)
|
|
133
|
+ // ->pluck('name', 'id')
|
|
134
|
+ // ->toArray();
|
|
135
|
+ // })
|
|
136
|
+ // ->searchable()
|
|
137
|
+ // ->multiple()
|
|
138
|
+ // ->hint('Leave blank to apply to all accounts'),
|
|
139
|
+ //
|
|
140
|
+ // Forms\Components\Select::make('apply_to_periods')
|
|
141
|
+ // ->label('Apply to Periods')
|
|
142
|
+ // ->options(static function () use ($get) {
|
|
143
|
+ // $startDate = $get('start_date');
|
|
144
|
+ // $endDate = $get('end_date');
|
|
145
|
+ // $intervalType = $get('interval_type');
|
|
146
|
+ //
|
|
147
|
+ // if (blank($startDate) || blank($endDate) || blank($intervalType)) {
|
|
148
|
+ // return [];
|
|
149
|
+ // }
|
|
150
|
+ //
|
|
151
|
+ // $labels = self::generateFormattedLabels($startDate, $endDate, $intervalType);
|
|
152
|
+ //
|
|
153
|
+ // return array_combine($labels, $labels);
|
|
154
|
+ // })
|
|
155
|
+ // ->searchable()
|
|
156
|
+ // ->multiple()
|
|
157
|
+ // ->hint('Leave blank to apply to all periods'),
|
|
158
|
+ // ])
|
|
159
|
+ // ->action(static fn (Forms\Set $set, Forms\Get $get, array $data) => self::increaseAllocations($set, $get, $data))
|
|
160
|
+ // ->visible(static fn (Forms\Get $get) => filled($get('budgetItems'))),
|
|
161
|
+ // ])
|
|
162
|
+ // ->schema([
|
|
163
|
+ // Forms\Components\Repeater::make('budgetItems')
|
|
164
|
+ // ->columns(4)
|
|
165
|
+ // ->hiddenLabel()
|
|
166
|
+ // ->schema([
|
|
167
|
+ // Forms\Components\Select::make('account_id')
|
|
168
|
+ // ->label('Account')
|
|
169
|
+ // ->options(Account::query()
|
|
170
|
+ // ->budgetable()
|
|
171
|
+ // ->pluck('name', 'id'))
|
|
172
|
+ // ->searchable()
|
|
173
|
+ // ->disableOptionsWhenSelectedInSiblingRepeaterItems()
|
|
174
|
+ // ->columnSpan(1)
|
|
175
|
+ // ->required(),
|
|
176
|
+ //
|
|
177
|
+ // Forms\Components\TextInput::make('total_amount')
|
|
178
|
+ // ->label('Total Amount')
|
|
179
|
+ // ->numeric()
|
|
180
|
+ // ->columnSpan(1)
|
|
181
|
+ // ->suffixAction(
|
|
182
|
+ // Forms\Components\Actions\Action::make('disperse')
|
|
183
|
+ // ->label('Disperse')
|
|
184
|
+ // ->icon('heroicon-m-bars-arrow-down')
|
|
185
|
+ // ->color('primary')
|
|
186
|
+ // ->action(static fn (Forms\Set $set, Forms\Get $get, $state) => self::disperseTotalAmount($set, $get, $state))
|
|
187
|
+ // ),
|
|
188
|
+ //
|
|
189
|
+ // CustomSection::make('Budget Allocations')
|
|
190
|
+ // ->contained(false)
|
|
191
|
+ // ->columns(4)
|
|
192
|
+ // ->schema(static fn (Forms\Get $get) => self::getAllocationFields($get('../../start_date'), $get('../../end_date'), $get('../../interval_type'))),
|
|
193
|
+ // ])
|
|
194
|
+ // ->defaultItems(0)
|
|
195
|
+ // ->addActionLabel('Add Budget Item'),
|
|
196
|
+ // ]),
|
198
|
197
|
]);
|
199
|
198
|
}
|
200
|
199
|
|
|
@@ -206,6 +205,11 @@ class BudgetResource extends Resource
|
206
|
205
|
->sortable()
|
207
|
206
|
->searchable(),
|
208
|
207
|
|
|
208
|
+ Tables\Columns\TextColumn::make('status')
|
|
209
|
+ ->label('Status')
|
|
210
|
+ ->sortable()
|
|
211
|
+ ->badge(),
|
|
212
|
+
|
209
|
213
|
Tables\Columns\TextColumn::make('interval_type')
|
210
|
214
|
->label('Interval')
|
211
|
215
|
->sortable()
|
|
@@ -373,7 +377,6 @@ class BudgetResource extends Resource
|
373
|
377
|
|
374
|
378
|
while ($start->lte($end)) {
|
375
|
379
|
$labels[] = match ($intervalTypeEnum) {
|
376
|
|
- BudgetIntervalType::Week => 'W' . $start->weekOfYear . ' ' . $start->year, // Example: W10 2024
|
377
|
380
|
BudgetIntervalType::Month => $start->format('M'), // Example: Jan, Feb, Mar
|
378
|
381
|
BudgetIntervalType::Quarter => 'Q' . $start->quarter, // Example: Q1, Q2, Q3
|
379
|
382
|
BudgetIntervalType::Year => (string) $start->year, // Example: 2024, 2025
|
|
@@ -381,7 +384,6 @@ class BudgetResource extends Resource
|
381
|
384
|
};
|
382
|
385
|
|
383
|
386
|
match ($intervalTypeEnum) {
|
384
|
|
- BudgetIntervalType::Week => $start->addWeek(),
|
385
|
387
|
BudgetIntervalType::Month => $start->addMonth(),
|
386
|
388
|
BudgetIntervalType::Quarter => $start->addQuarter(),
|
387
|
389
|
BudgetIntervalType::Year => $start->addYear(),
|
|
@@ -398,32 +400,15 @@ class BudgetResource extends Resource
|
398
|
400
|
return [];
|
399
|
401
|
}
|
400
|
402
|
|
401
|
|
- $start = Carbon::parse($startDate);
|
402
|
|
- $end = Carbon::parse($endDate);
|
403
|
|
- $intervalTypeEnum = BudgetIntervalType::parse($intervalType);
|
404
|
403
|
$fields = [];
|
405
|
404
|
|
406
|
|
- while ($start->lte($end)) {
|
407
|
|
- $label = match ($intervalTypeEnum) {
|
408
|
|
- BudgetIntervalType::Week => 'W' . $start->weekOfYear . ' ' . $start->year, // Example: W10 2024
|
409
|
|
- BudgetIntervalType::Month => $start->format('M'), // Example: Jan, Feb, Mar
|
410
|
|
- BudgetIntervalType::Quarter => 'Q' . $start->quarter, // Example: Q1, Q2, Q3
|
411
|
|
- BudgetIntervalType::Year => (string) $start->year, // Example: 2024, 2025
|
412
|
|
- default => '',
|
413
|
|
- };
|
|
405
|
+ $labels = self::generateFormattedLabels($startDate, $endDate, $intervalType);
|
414
|
406
|
|
|
407
|
+ foreach ($labels as $label) {
|
415
|
408
|
$fields[] = Forms\Components\TextInput::make("amounts.{$label}")
|
416
|
409
|
->label($label)
|
417
|
410
|
->numeric()
|
418
|
411
|
->required();
|
419
|
|
-
|
420
|
|
- match ($intervalTypeEnum) {
|
421
|
|
- BudgetIntervalType::Week => $start->addWeek(),
|
422
|
|
- BudgetIntervalType::Month => $start->addMonth(),
|
423
|
|
- BudgetIntervalType::Quarter => $start->addQuarter(),
|
424
|
|
- BudgetIntervalType::Year => $start->addYear(),
|
425
|
|
- default => null,
|
426
|
|
- };
|
427
|
412
|
}
|
428
|
413
|
|
429
|
414
|
return $fields;
|