WIP: SoftDelete Contract/Payment/Customer, collected_by, Notifications, ProjectReport, ExportDebtReport
This commit is contained in:
84
app/Filament/Pages/ProjectReport.php
Normal file
84
app/Filament/Pages/ProjectReport.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Pages;
|
||||
|
||||
use App\Models\Project;
|
||||
use Filament\Pages\Page;
|
||||
use Filament\Tables\Table;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Concerns\InteractsWithTable;
|
||||
use Filament\Tables\Contracts\HasTable;
|
||||
|
||||
class ProjectReport extends Page implements HasTable
|
||||
{
|
||||
use InteractsWithTable;
|
||||
|
||||
protected static string | \BackedEnum | null $navigationIcon = 'heroicon-o-chart-bar';
|
||||
protected static ?string $navigationLabel = 'Báo cáo theo Dự án';
|
||||
protected static ?string $title = 'Báo cáo Thống kê theo Dự án';
|
||||
protected static string | \UnitEnum | null $navigationGroup = 'Quản lý Dòng tiền';
|
||||
protected static ?int $navigationSort = 50;
|
||||
protected string $view = 'filament.pages.project-report';
|
||||
|
||||
public function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->query(
|
||||
Project::query()
|
||||
->select('projects.id', 'projects.name', 'projects.code')
|
||||
->selectRaw('COUNT(DISTINCT products.id) as product_count')
|
||||
->selectRaw('COUNT(DISTINCT CASE WHEN contracts.id IS NOT NULL THEN products.id END) as sold_product_count')
|
||||
->selectRaw('COUNT(DISTINCT contracts.id) as contract_count')
|
||||
->selectRaw('COALESCE(SUM(contracts.total_value), 0) as total_revenue')
|
||||
->selectRaw('COALESCE(SUM(contracts.paid_amount), 0) as total_paid')
|
||||
->selectRaw('COALESCE(SUM(contracts.remaining_amount), 0) as total_remaining')
|
||||
->leftJoin('products', 'products.project_id', '=', 'projects.id')
|
||||
->leftJoin('contracts', 'contracts.product_id', '=', 'products.id')
|
||||
->groupBy('projects.id', 'projects.name', 'projects.code')
|
||||
)
|
||||
->columns([
|
||||
TextColumn::make('name')
|
||||
->label('Dự án')
|
||||
->searchable()
|
||||
->sortable(),
|
||||
|
||||
TextColumn::make('product_count')
|
||||
->label('Tổng SP')
|
||||
->alignCenter()
|
||||
->sortable(),
|
||||
|
||||
TextColumn::make('sold_product_count')
|
||||
->label('Đã bán')
|
||||
->alignCenter()
|
||||
->sortable()
|
||||
->color('success'),
|
||||
|
||||
TextColumn::make('contract_count')
|
||||
->label('Số HĐ')
|
||||
->alignCenter()
|
||||
->sortable(),
|
||||
|
||||
TextColumn::make('total_revenue')
|
||||
->label('Tổng giá trị HĐ')
|
||||
->money('VND')
|
||||
->sortable()
|
||||
->summarize(\Filament\Tables\Columns\Summarizers\Sum::make()->label('Tổng')->money('VND')),
|
||||
|
||||
TextColumn::make('total_paid')
|
||||
->label('Đã thu')
|
||||
->money('VND')
|
||||
->sortable()
|
||||
->color('success')
|
||||
->summarize(\Filament\Tables\Columns\Summarizers\Sum::make()->label('Tổng')->money('VND')),
|
||||
|
||||
TextColumn::make('total_remaining')
|
||||
->label('Công nợ phải thu')
|
||||
->money('VND')
|
||||
->sortable()
|
||||
->color('danger')
|
||||
->summarize(\Filament\Tables\Columns\Summarizers\Sum::make()->label('Tổng')->money('VND')),
|
||||
])
|
||||
->defaultSort('total_revenue', 'desc')
|
||||
->paginated([10, 25, 50]);
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,8 @@ use App\Models\Customer;
|
||||
use Filament\Forms\Components\DatePicker;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\Section;
|
||||
use Filament\Forms\Components\Actions\Action;
|
||||
use Filament\Schemas\Components\Section;
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Forms\Components\TagsInput;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Schemas\Components\Utilities\Set;
|
||||
|
||||
@@ -149,6 +149,14 @@ class PaymentForm
|
||||
])
|
||||
->default('Chuyển khoản')
|
||||
->required(),
|
||||
|
||||
Select::make('collected_by')
|
||||
->label('Ngườ thu')
|
||||
->relationship('collector', 'name')
|
||||
->searchable()
|
||||
->preload()
|
||||
->default(auth()->id())
|
||||
->required(),
|
||||
]),
|
||||
|
||||
Section::make('Bổ sung')
|
||||
|
||||
@@ -73,6 +73,11 @@ class PaymentsTable
|
||||
->money('VND')
|
||||
->placeholder('-')
|
||||
->color('danger'),
|
||||
|
||||
Tables\Columns\TextColumn::make('collector.name')
|
||||
->label('Ngườ thu')
|
||||
->placeholder('-')
|
||||
->sortable(),
|
||||
])
|
||||
->filters([
|
||||
Tables\Filters\SelectFilter::make('method')
|
||||
|
||||
53
app/Filament/Widgets/RecentNotifications.php
Normal file
53
app/Filament/Widgets/RecentNotifications.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Widgets;
|
||||
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Tables;
|
||||
use Filament\Tables\Table;
|
||||
use Filament\Widgets\TableWidget as BaseWidget;
|
||||
|
||||
class RecentNotifications extends BaseWidget
|
||||
{
|
||||
protected int | string | array $columnSpan = 'full';
|
||||
protected static ?int $sort = 1;
|
||||
|
||||
public function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->query(function () {
|
||||
$user = auth()->user();
|
||||
if (! $user) {
|
||||
return \Illuminate\Notifications\DatabaseNotification::query()->whereRaw('1=0');
|
||||
}
|
||||
return $user->notifications()->whereNull('read_at')->latest()->getQuery();
|
||||
})
|
||||
->columns([
|
||||
Tables\Columns\TextColumn::make('data.title')
|
||||
->label('Tiêu đề')
|
||||
->badge()
|
||||
->color('warning'),
|
||||
|
||||
Tables\Columns\TextColumn::make('data.message')
|
||||
->label('Nội dung')
|
||||
->limit(100),
|
||||
|
||||
Tables\Columns\TextColumn::make('created_at')
|
||||
->label('Thờ gian')
|
||||
->dateTime('d/m/Y H:i')
|
||||
->color('gray'),
|
||||
])
|
||||
->actions([
|
||||
Action::make('markAsRead')
|
||||
->label('Đánh dấu đã đọc')
|
||||
->icon('heroicon-o-check-circle')
|
||||
->color('success')
|
||||
->action(function ($record) {
|
||||
$record->markAsRead();
|
||||
}),
|
||||
])
|
||||
->paginated([5, 10, 25])
|
||||
->emptyStateHeading('Không có thông báo mới')
|
||||
->emptyStateDescription('Bạn sẽ nhận được cảnh báo khi có đợt thanh toán sắp đến hạn.');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user