Files
MKM/app/Filament/Resources/ExpenseResource/Pages/CreateExpense.php
Jp f5c8ec04ad feat: add account linking and improve sales table
- Add many-to-many relationships between Sale/Expense and Account models
- Create pivot tables for account_sale and account_expense with migrations
- Implement account syncing during sale/expense creation and editing
- Add accounts_list attribute to display comma-separated account names
- Introduce SaleService with DTO for sale creation logic
- Simplify sales table columns to show branch, reference, date, and creator
- Calculate and store aggregated financial fields from transactions
- Make series field read-only instead of disabled in sale form
2026-02-15 18:57:18 +08:00

114 lines
3.8 KiB
PHP

<?php
namespace App\Filament\Resources\ExpenseResource\Pages;
use App\Actions\Transactions\CreateTransactionAction;
use App\DataObjects\CreateTransactionDTO;
use App\Filament\Resources\ClientResource;
use App\Filament\Resources\ExpenseResource;
use App\Models\Client;
use Exception;
use Filament\Resources\Pages\CreateRecord;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Pipeline;
use Symfony\Component\Console\Exception\LogicException;
class CreateExpense extends CreateRecord
{
protected static string $resource = ExpenseResource::class;
public ?int $clientId = null;
public function mount(): void
{
parent::mount();
$this->clientId = request()->integer('client_id');
}
public function getBreadcrumbs(): array
{
$client = $this->getClient();
if (! $client) {
return parent::getBreadcrumbs();
}
return [
ClientResource::getUrl('view', ['record' => $client->id]) => $client->company,
ClientResource::getUrl('view', ['record' => $client->id]).'?activeRelationManager=4' => 'Expenses',
$this->getResource()::getUrl('create', ['client_id' => $client->id]) => 'Create',
];
}
protected function getClient(): Client|null
{
if (! $this->clientId) {
return null;
}
return Client::find($this->clientId);
}
protected function mutateFormDataBeforeCreate(array $data): array
{
return $this->getFormDataMutation($data);
}
public function getFormDataMutation(array $data): array
{
$transactions = $data['transactions'] ?? [];
$data['gross_amount'] = collect($transactions)->sum(fn (array $transaction) => (float) ($transaction['gross_amount'] ?? 0));
$data['exempt'] = collect($transactions)->sum(fn (array $transaction) => (float) ($transaction['exempt'] ?? 0));
$data['zero_rated'] = collect($transactions)->sum(fn (array $transaction) => (float) ($transaction['zero_rated'] ?? 0));
$data['vatable_amount'] = collect($transactions)->sum(fn (array $transaction) => (float) ($transaction['vatable_amount'] ?? 0));
$data['input_tax'] = collect($transactions)->sum(fn (array $transaction) => (float) ($transaction['input_tax'] ?? 0));
$data['payable_withholding_tax'] = collect($transactions)->sum(fn (array $transaction) => (float) ($transaction['payable_withholding_tax'] ?? 0));
$data['net_amount'] = collect($transactions)->sum(fn (array $transaction) => (float) ($transaction['net_amount'] ?? 0));
return Arr::except($data, ['client', 'transactions']);
}
protected function afterCreate(): void
{
$transactions = $this->form->getState()['transactions'] ?? [];
try {
$branch = $this->getRecord()->branch;
foreach ($transactions as $transaction) {
$data = [
'branch_id' => $branch->id,
'happened_on' => $this->getRecord()->happened_on,
...$transaction,
];
$payload = new CreateTransactionDTO(data: $data, transactionable: $this->getRecord());
Pipeline::send(passable: $payload)->through(
[
CreateTransactionAction::class,
]
)->thenReturn();
}
$accountIds = collect($transactions)
->pluck('account_id')
->filter()
->unique()
->values()
->all();
$this->getRecord()->accounts()->sync($accountIds);
$this->commitDatabaseTransaction();
} catch (Exception $exception) {
$this->rollBackDatabaseTransaction();
throw new LogicException('Failed to save transactions : '.$exception->getMessage());
}
}
}