Đóng gói cuối tuần
This commit is contained in:
@@ -4,6 +4,9 @@ namespace App\Filament\Resources\Contracts;
|
||||
|
||||
use App\Filament\Resources\Contracts\Pages;
|
||||
use App\Models\Contract;
|
||||
use App\Models\Product;
|
||||
use App\Models\PaymentTemplate;
|
||||
use App\Enums\NavigationGroup;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Components\DatePicker;
|
||||
@@ -12,40 +15,38 @@ use Filament\Schemas\Schema;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Tables;
|
||||
use Filament\Tables\Table;
|
||||
use Filament\Schemas\Components\Utilities\Get;
|
||||
use App\Filament\Resources\Contracts\ContractResource\RelationManagers\ScheduleItemsRelationManager;
|
||||
|
||||
class ContractResource extends Resource
|
||||
{
|
||||
protected static ?string $model = Contract::class;
|
||||
protected static string | \BackedEnum | null $navigationIcon = 'heroicon-o-document-text';
|
||||
protected static string | \UnitEnum | null $navigationGroup = 'Quản lý Giao dịch';
|
||||
protected static string | \UnitEnum | null $navigationGroup = NavigationGroup::TRANSACTION->value;
|
||||
protected static ?int $navigationSort = 4;
|
||||
|
||||
protected static ?string $modelLabel = 'Hợp đồng';
|
||||
protected static ?string $pluralModelLabel = 'Hợp đồng';
|
||||
|
||||
public static function form(Schema $schema): Schema
|
||||
{
|
||||
return $schema
|
||||
->components([
|
||||
Section::make('Thông tin Liên kết')
|
||||
Section::make('Liên kết & Mẫu thanh toán')
|
||||
->columns(2)
|
||||
->schema([
|
||||
Select::make('product_id')->label('Mã Sản phẩm')->relationship('product', 'code')->searchable()->preload()->required(),
|
||||
Select::make('customers')->label('Khách hàng')->relationship('customers', 'full_name')->multiple()->searchable()->preload()->required(),
|
||||
Select::make('product_id')->label('Sản phẩm')->relationship('product', 'code')->required()->live(),
|
||||
Select::make('payment_template_id')->label('Mẫu thanh toán')
|
||||
->options(fn (Get $get) => PaymentTemplate::pluck('name', 'id'))
|
||||
->required()->dehydrated(false),
|
||||
Select::make('customers')->label('Khách hàng')->relationship('customers', 'full_name')->multiple()->required()->columnSpanFull(),
|
||||
]),
|
||||
Section::make('Chi tiết Hợp đồng')
|
||||
->columns(2)
|
||||
->schema([
|
||||
TextInput::make('contract_number')->label('Số Hợp đồng')->required()->unique(ignoreRecord: true),
|
||||
Select::make('contract_type')->label('Loại Hợp đồng')->options(['HĐMB' => 'HĐ Mua bán', 'HĐĐC' => 'HĐ Đặt cọc', 'HĐGV' => 'HĐ Góp vốn', 'VBCN' => 'VBCN'])->default('HĐMB'),
|
||||
DatePicker::make('signing_date')->label('Ngày ký')->displayFormat('d/m/Y'),
|
||||
TextInput::make('transfer_order')->label('Thứ tự chuyển nhượng')->numeric()->default(0),
|
||||
Select::make('status')->label('Trạng thái')
|
||||
->options(['Đang hiệu lực' => 'Đang hiệu lực', 'Đã thanh lý' => 'Đã thanh lý', 'Đã chuyển nhượng' => 'Đã chuyển nhượng'])
|
||||
->default('Đang hiệu lực'),
|
||||
]),
|
||||
Section::make('Tài chính')
|
||||
->columns(2)
|
||||
->schema([
|
||||
TextInput::make('total_value')->label('Tổng giá trị (VND)')->numeric()->required(),
|
||||
TextInput::make('paid_amount')->label('Đã thanh toán (VND)')->numeric()->default(0),
|
||||
]),
|
||||
TextInput::make('contract_number')->label('Số HĐ')->required(),
|
||||
DatePicker::make('signing_date')->label('Ngày ký')->required(),
|
||||
])
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -54,23 +55,13 @@ class ContractResource extends Resource
|
||||
return $table
|
||||
->columns([
|
||||
Tables\Columns\TextColumn::make('contract_number')->label('Số HĐ')->searchable(),
|
||||
Tables\Columns\TextColumn::make('contract_type')->label('Loại HĐ')->badge(),
|
||||
Tables\Columns\TextColumn::make('product.code')->label('Mã SP')->searchable(),
|
||||
Tables\Columns\TextColumn::make('customers.full_name')->label('Khách hàng')->badge(),
|
||||
Tables\Columns\TextColumn::make('status')->label('Trạng thái')
|
||||
->color(fn (string $state): string => match ($state) {
|
||||
'Đang hiệu lực' => 'success',
|
||||
'Đã thanh lý' => 'warning',
|
||||
'Đã chuyển nhượng' => 'gray',
|
||||
default => 'gray',
|
||||
})->badge(),
|
||||
Tables\Columns\TextColumn::make('total_value')->label('Tổng giá trị')->money('VND'),
|
||||
Tables\Columns\TextColumn::make('paid_amount')->label('Đã TT')->money('VND'),
|
||||
Tables\Columns\TextColumn::make('remaining_amount')->label('Còn lại')->money('VND')->color('danger'),
|
||||
])
|
||||
->defaultSort('created_at', 'desc');
|
||||
Tables\Columns\TextColumn::make('product.code')->label('Sản phẩm'),
|
||||
Tables\Columns\TextColumn::make('total_value')->label('Giá trị')->money('VND'),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getRelations(): array { return [ScheduleItemsRelationManager::class]; }
|
||||
|
||||
public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\Contracts\ContractResource\RelationManagers;
|
||||
|
||||
use Filament\Resources\RelationManagers\RelationManager;
|
||||
use Filament\Tables;
|
||||
use Filament\Tables\Table;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Actions\ViewAction;
|
||||
use Filament\Actions\EditAction;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Schemas\Components\Section;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Components\DatePicker;
|
||||
use Filament\Forms\Components\Placeholder;
|
||||
|
||||
class ScheduleItemsRelationManager extends RelationManager
|
||||
{
|
||||
protected static string $relationship = 'scheduleItems';
|
||||
|
||||
protected static ?string $title = 'Lịch thanh toán thực tế';
|
||||
|
||||
protected static ?string $modelLabel = 'Đợt thanh toán';
|
||||
protected static ?string $pluralModelLabel = 'Đợt thanh toán';
|
||||
|
||||
public function form(Schema $schema): Schema
|
||||
{
|
||||
return $schema
|
||||
->components([
|
||||
Section::make('Chi tiết đợt thanh toán')
|
||||
->columns(2)
|
||||
->schema([
|
||||
Placeholder::make('installment_no')->label('Đợt số')->content(fn ($record) => $record->installment_no),
|
||||
Placeholder::make('type')->label('Loại đợt')->content(fn ($record) => $record->type?->getLabel()),
|
||||
TextInput::make('amount')->label('Số tiền (VND)')->numeric()->required(),
|
||||
DatePicker::make('due_date')->label('Ngày đến hạn')->required(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
public function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
TextColumn::make('installment_no')->label('Đợt')->badge(),
|
||||
TextColumn::make('type')->label('Loại')->badge(),
|
||||
TextColumn::make('amount')->label('Số tiền dự kiến')->money('VND'),
|
||||
TextColumn::make('due_date')->label('Hạn thanh toán')->date('d/m/Y'),
|
||||
])
|
||||
->defaultSort('installment_no', 'asc')
|
||||
->actions([
|
||||
ViewAction::make(),
|
||||
EditAction::make(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,59 @@
|
||||
namespace App\Filament\Resources\Contracts\Pages;
|
||||
|
||||
use App\Filament\Resources\Contracts\ContractResource;
|
||||
use App\Models\PaymentTemplate;
|
||||
use App\Models\PaymentSchedule;
|
||||
use App\Models\PaymentScheduleItem;
|
||||
use Filament\Resources\Pages\CreateRecord;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class CreateContract extends CreateRecord
|
||||
{
|
||||
protected static string $resource = ContractResource::class;
|
||||
|
||||
protected function afterCreate(): void
|
||||
{
|
||||
$contract = $this->record;
|
||||
$templateId = $this->data['payment_template_id'] ?? null;
|
||||
|
||||
if ($templateId) {
|
||||
$template = PaymentTemplate::find($templateId);
|
||||
|
||||
// 1. Tạo Schedule cho Hợp đồng
|
||||
$schedule = PaymentSchedule::create([
|
||||
'contract_id' => $contract->id,
|
||||
'template_id' => $template->id,
|
||||
]);
|
||||
|
||||
// 2. Clone từng Item từ Template sang Schedule thực tế
|
||||
$items = $template->items()->orderBy('installment_no')->get();
|
||||
$lastDueDate = Carbon::parse($contract->signing_date);
|
||||
|
||||
foreach ($items as $item) {
|
||||
$dueDate = null;
|
||||
|
||||
// Logic tính ngày đến hạn chuẩn v5.5
|
||||
if ($item->days_after_signing !== null) {
|
||||
$dueDate = Carbon::parse($contract->signing_date)->addDays($item->days_after_signing);
|
||||
} elseif ($item->days_after_previous !== null) {
|
||||
$dueDate = $lastDueDate->copy()->addDays($item->days_after_previous);
|
||||
} elseif ($item->due_date !== null) {
|
||||
$dueDate = $item->due_date;
|
||||
}
|
||||
|
||||
PaymentScheduleItem::create([
|
||||
'schedule_id' => $schedule->id,
|
||||
'installment_no' => $item->installment_no,
|
||||
'type' => $item->type,
|
||||
'percentage' => $item->percentage,
|
||||
'amount' => $contract->total_value * ($item->percentage / 100),
|
||||
'due_date' => $dueDate,
|
||||
]);
|
||||
|
||||
if ($dueDate) {
|
||||
$lastDueDate = $dueDate;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user