Skip to content

Commit 946ec1a

Browse files
Merge pull request #70 from khalidmaquilang/dev
v2.2.0 - Hotfix | disable admin slug + Hotfix | cant create purchase order + Feature | remove unused permission + Feature | added menu item + Hotfix | fix create user through invitation + Hotfix | kick function missing + Feature | test cases + Feature | subscription + Hotfix | fix design + Hotfix | able to join existing users
2 parents c167df8 + 953294c commit 946ec1a

File tree

82 files changed

+2958
-85
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+2958
-85
lines changed

app/Enums/BillingCycleEnum.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
namespace App\Enums;
4+
5+
use Filament\Support\Contracts\HasLabel;
6+
7+
enum BillingCycleEnum: string implements HasLabel
8+
{
9+
case MONTHLY = 'monthly';
10+
case YEARLY = 'yearly';
11+
12+
/**
13+
* @return string
14+
*/
15+
public function getLabel(): string
16+
{
17+
return match ($this) {
18+
self::MONTHLY => 'Monthly',
19+
self::YEARLY => 'Yearly',
20+
};
21+
}
22+
}

app/Enums/PaymentStatusEnum.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace App\Enums;
4+
5+
use Filament\Support\Contracts\HasColor;
6+
use Filament\Support\Contracts\HasLabel;
7+
8+
enum PaymentStatusEnum: string implements HasColor, HasLabel
9+
{
10+
case SUCCESS = 'success';
11+
case FAILED = 'failed';
12+
case PENDING = 'pending';
13+
14+
/**
15+
* @return string
16+
*/
17+
public function getLabel(): string
18+
{
19+
return match ($this) {
20+
self::SUCCESS => 'Success',
21+
self::FAILED => 'Failed',
22+
self::PENDING => 'Pending',
23+
};
24+
}
25+
26+
/**
27+
* @return string
28+
*/
29+
public function getColor(): string
30+
{
31+
return match ($this) {
32+
self::SUCCESS => 'success',
33+
self::FAILED => 'danger',
34+
self::PENDING => 'warning',
35+
};
36+
}
37+
}

app/Enums/PlanTypeEnum.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
namespace App\Enums;
4+
5+
use Filament\Support\Contracts\HasLabel;
6+
7+
enum PlanTypeEnum: string implements HasLabel
8+
{
9+
case STANDARD = 'standard';
10+
case CUSTOM = 'custom';
11+
12+
/**
13+
* @return string
14+
*/
15+
public function getLabel(): string
16+
{
17+
return match ($this) {
18+
self::STANDARD => 'Standard',
19+
self::CUSTOM => 'Custom',
20+
};
21+
}
22+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
namespace App\Enums;
4+
5+
use Filament\Support\Contracts\HasColor;
6+
use Filament\Support\Contracts\HasLabel;
7+
8+
enum SubscriptionStatusEnum: string implements HasColor, HasLabel
9+
{
10+
case ACTIVE = 'active';
11+
case TRIAL = 'trialing';
12+
case CANCELED = 'canceled';
13+
case PAST_DUE = 'past_due';
14+
case UNPAID = 'unpaid';
15+
16+
/**
17+
* @return string
18+
*/
19+
public function getLabel(): string
20+
{
21+
return match ($this) {
22+
self::ACTIVE => 'Active',
23+
self::TRIAL => 'Trialing',
24+
self::CANCELED => 'Canceled',
25+
self::PAST_DUE => 'Past Due',
26+
self::UNPAID => 'Unpaid',
27+
};
28+
}
29+
30+
/**
31+
* @return string
32+
*/
33+
public function getColor(): string
34+
{
35+
return match ($this) {
36+
self::ACTIVE => 'success',
37+
self::TRIAL => 'info',
38+
self::CANCELED => 'danger',
39+
self::PAST_DUE => 'warning',
40+
self::UNPAID => 'danger',
41+
};
42+
}
43+
}

app/Filament/Admin/Resources/CompanyResource.php

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ public static function table(Table $table): Table
6666
->searchable(),
6767
Tables\Columns\TextColumn::make('currency')
6868
->searchable(),
69+
Tables\Columns\TextColumn::make('plan')
70+
->getStateUsing(fn ($record) => $record->getActiveSubscription()->plan->name),
6971
Tables\Columns\TextColumn::make('created_at')
7072
->dateTime()
7173
->sortable()
@@ -75,10 +77,8 @@ public static function table(Table $table): Table
7577
->sortable()
7678
->toggleable(isToggledHiddenByDefault: true),
7779
])
78-
->filters([
79-
//
80-
])
8180
->actions([
81+
Tables\Actions\ViewAction::make(),
8282
Tables\Actions\EditAction::make(),
8383
])
8484
->bulkActions([
@@ -88,19 +88,13 @@ public static function table(Table $table): Table
8888
]);
8989
}
9090

91-
public static function getRelations(): array
92-
{
93-
return [
94-
//
95-
];
96-
}
97-
9891
public static function getPages(): array
9992
{
10093
return [
10194
'index' => Pages\ListCompanies::route('/'),
10295
'create' => Pages\CreateCompany::route('/create'),
10396
'edit' => Pages\EditCompany::route('/{record}/edit'),
97+
'view' => Pages\ViewCompany::route('/{record}'),
10498
];
10599
}
106100
}

app/Filament/Admin/Resources/CompanyResource/Pages/EditCompany.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,9 @@ protected function getHeaderActions(): array
1616
Actions\DeleteAction::make(),
1717
];
1818
}
19+
20+
public function getRelationManagers(): array
21+
{
22+
return [];
23+
}
1924
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
namespace App\Filament\Admin\Resources\CompanyResource\Pages;
4+
5+
use App\Filament\Admin\Resources\CompanyResource;
6+
use Filament\Actions;
7+
use Filament\Infolists\Components\Section;
8+
use Filament\Infolists\Components\TextEntry;
9+
use Filament\Infolists\Infolist;
10+
use Filament\Resources\Pages\ViewRecord;
11+
12+
class ViewCompany extends ViewRecord
13+
{
14+
protected static string $resource = CompanyResource::class;
15+
16+
protected function getHeaderActions(): array
17+
{
18+
return [
19+
Actions\EditAction::make(),
20+
];
21+
}
22+
23+
public function infolist(Infolist $infolist): Infolist
24+
{
25+
return $infolist
26+
->schema([
27+
Section::make()
28+
->columns(2)
29+
->schema([
30+
TextEntry::make('name'),
31+
TextEntry::make('slug'),
32+
TextEntry::make('owner.name'),
33+
TextEntry::make('phone'),
34+
TextEntry::make('email'),
35+
TextEntry::make('currency'),
36+
]),
37+
]);
38+
}
39+
40+
/**
41+
* @return \class-string[]
42+
*/
43+
public function getRelationManagers(): array
44+
{
45+
return [
46+
CompanyResource\RelationManagers\SubscriptionsRelationManager::class,
47+
];
48+
}
49+
}
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
<?php
2+
3+
namespace App\Filament\Admin\Resources\CompanyResource\RelationManagers;
4+
5+
use App\Enums\BillingCycleEnum;
6+
use App\Enums\PaymentStatusEnum;
7+
use App\Enums\SubscriptionStatusEnum;
8+
use App\Models\Plan;
9+
use Carbon\Carbon;
10+
use Filament\Forms;
11+
use Filament\Forms\Components\Select;
12+
use Filament\Forms\Components\TextInput;
13+
use Filament\Forms\Form;
14+
use Filament\Resources\RelationManagers\RelationManager;
15+
use Filament\Tables;
16+
use Filament\Tables\Table;
17+
18+
class SubscriptionsRelationManager extends RelationManager
19+
{
20+
protected static string $relationship = 'subscriptions';
21+
22+
public function form(Form $form): Form
23+
{
24+
return $form
25+
->schema([
26+
Forms\Components\Hidden::make('total_amount')
27+
->default(1),
28+
Forms\Components\Select::make('plan_id')
29+
->relationship('plan', 'name')
30+
->required(),
31+
Forms\Components\DatePicker::make('start_date')
32+
->required(),
33+
Forms\Components\TextInput::make('extra_users')
34+
->default(0),
35+
]);
36+
}
37+
38+
public function table(Table $table): Table
39+
{
40+
return $table
41+
->recordTitleAttribute('id')
42+
->columns([
43+
Tables\Columns\TextColumn::make('plan.name'),
44+
Tables\Columns\TextColumn::make('start_date')
45+
->date(),
46+
Tables\Columns\TextColumn::make('end_date')
47+
->date(),
48+
Tables\Columns\TextColumn::make('status')
49+
->badge(),
50+
Tables\Columns\TextColumn::make('extra_users')
51+
->badge(),
52+
Tables\Columns\TextColumn::make('total_amount')
53+
->money('PHP'),
54+
])
55+
->filters([
56+
//
57+
])
58+
->headerActions([
59+
Tables\Actions\CreateAction::make()
60+
->mutateFormDataUsing(function (array $data) {
61+
return $this->beforeCreate($data);
62+
})
63+
->after(fn ($record) => $this->afterCreate($record))
64+
->createAnother(false),
65+
])
66+
->actions([
67+
Tables\Actions\Action::make('view')
68+
->icon('heroicon-m-eye')
69+
->color('gray')
70+
->label('View')
71+
->action(fn ($record) => redirect(route('filament.admin.resources.subscriptions.view', [$record]))),
72+
Tables\Actions\EditAction::make(),
73+
Tables\Actions\Action::make('renew')
74+
->icon('heroicon-m-banknotes')
75+
->color('success')
76+
->fillForm(fn ($record): array => [
77+
'amount' => $record->total_amount,
78+
])
79+
->form($this->renewForm())
80+
->action(function (array $data, $record): void {
81+
$record->updateEndDate();
82+
$record->payments()->create($data);
83+
})
84+
->successNotificationTitle('Payment Updated')
85+
->visible(fn ($record) => $record->isActive()),
86+
])
87+
->bulkActions([
88+
89+
])
90+
->defaultSort('created_at', 'desc');
91+
}
92+
93+
/**
94+
* @return array
95+
*/
96+
protected function renewForm(): array
97+
{
98+
return [
99+
Forms\Components\DatePicker::make('payment_date')
100+
->required(),
101+
TextInput::make('amount')
102+
->numeric()
103+
->required(),
104+
TextInput::make('payment_method')
105+
->required(),
106+
Select::make('status')
107+
->options(PaymentStatusEnum::class)
108+
->required(),
109+
];
110+
}
111+
112+
/**
113+
* @param array $data
114+
* @return array
115+
*/
116+
protected function beforeCreate(array $data): array
117+
{
118+
$plan = Plan::find($data['plan_id']);
119+
if (empty($plan)) {
120+
return [];
121+
}
122+
123+
$data['status'] = SubscriptionStatusEnum::ACTIVE;
124+
$data['end_date'] = $plan->billing_cycle === BillingCycleEnum::MONTHLY ? (new Carbon(
125+
$data['start_date']
126+
))->addMonth() : (new Carbon($data['start_date']))->addYear();
127+
$data['total_amount'] = $plan->price + ($data['extra_users'] * 100); //100php per user
128+
129+
$subscription = $this->ownerRecord->getActiveSubscription();
130+
if (! empty($subscription)) {
131+
$subscription->cancel(); // cancel latest subscription
132+
}
133+
134+
return $data;
135+
}
136+
137+
/**
138+
* @param $record
139+
* @return void
140+
*/
141+
protected function afterCreate($record): void
142+
{
143+
$record->payments()->create([
144+
'payment_date' => now(),
145+
'amount' => $record->total_amount,
146+
'payment_method' => 'system',
147+
'status' => PaymentStatusEnum::SUCCESS,
148+
]);
149+
}
150+
151+
/**
152+
* @return bool
153+
*/
154+
public function isReadOnly(): bool
155+
{
156+
return false;
157+
}
158+
}

0 commit comments

Comments
 (0)