diff --git a/app/DataObjects/CreateSaleDTO.php b/app/DataObjects/CreateSaleDTO.php new file mode 100644 index 0000000..735e1fe --- /dev/null +++ b/app/DataObjects/CreateSaleDTO.php @@ -0,0 +1,29 @@ + $this->reference_number, + 'happened_on' => $this->happened_on, + 'branch_id' => $this->branch_id, + 'user_id' => $this->user_id, + ]; + } +} diff --git a/app/Filament/Resources/ExpenseResource.php b/app/Filament/Resources/ExpenseResource.php index 741a620..a3ab5e9 100644 --- a/app/Filament/Resources/ExpenseResource.php +++ b/app/Filament/Resources/ExpenseResource.php @@ -273,6 +273,7 @@ class ExpenseResource extends Resource Tables\Columns\TextColumn::make('branch.client.company'), Tables\Columns\TextColumn::make('branch.code'), Tables\Columns\TextColumn::make('happened_on'), + Tables\Columns\TextColumn::make('accounts_list')->label('Accounts'), ]; } diff --git a/app/Filament/Resources/ExpenseResource/Pages/CreateExpense.php b/app/Filament/Resources/ExpenseResource/Pages/CreateExpense.php index d4c98ea..8e0acc6 100644 --- a/app/Filament/Resources/ExpenseResource/Pages/CreateExpense.php +++ b/app/Filament/Resources/ExpenseResource/Pages/CreateExpense.php @@ -58,6 +58,16 @@ class CreateExpense extends CreateRecord 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']); } @@ -85,6 +95,15 @@ class CreateExpense extends CreateRecord )->thenReturn(); } + $accountIds = collect($transactions) + ->pluck('account_id') + ->filter() + ->unique() + ->values() + ->all(); + + $this->getRecord()->accounts()->sync($accountIds); + $this->commitDatabaseTransaction(); } catch (Exception $exception) { $this->rollBackDatabaseTransaction(); diff --git a/app/Filament/Resources/SaleResource.php b/app/Filament/Resources/SaleResource.php index ac9efde..4ba7f7f 100644 --- a/app/Filament/Resources/SaleResource.php +++ b/app/Filament/Resources/SaleResource.php @@ -54,7 +54,7 @@ class SaleResource extends Resource ->live(), TextInput::make('current_series') ->label('Series') - ->disabled(), + ->readOnly(), DatePicker::make('happened_on')->label('Date') ->required() ->afterStateUpdated(function ($set, $get) { @@ -220,17 +220,10 @@ class SaleResource extends Resource { return $table ->columns([ - TextColumn::make('id')->label('ID')->sortable(), - TextColumn::make('client.name')->label('Client')->sortable(), - TextColumn::make('branch.name')->label('Branch')->sortable(), + TextColumn::make('branch.code')->label('Branch')->sortable(), + TextColumn::make('reference_number')->label('Reference Number')->sortable(), TextColumn::make('happened_on')->label('Date')->date()->sortable(), - TextColumn::make('gross_amount')->label('Gross Amount')->numeric()->sortable(), - TextColumn::make('exempt')->label('Exempt')->numeric()->sortable(), - TextColumn::make('vatable_amount')->label('Vatable Amount')->numeric()->sortable(), - TextColumn::make('output_tax')->label('Output Tax')->numeric()->sortable(), - TextColumn::make('payable_withholding_tax')->label('Payable Withholding Tax')->numeric()->sortable(), - TextColumn::make('discount')->label('Discount')->numeric()->sortable(), - TextColumn::make('net_amount')->label('Net Amount')->numeric()->sortable(), + TextColumn::make('user.name')->label('Created By')->sortable(), ]) ->filters([ // diff --git a/app/Filament/Resources/SaleResource/Pages/CreateSale.php b/app/Filament/Resources/SaleResource/Pages/CreateSale.php index be47ad9..2278109 100644 --- a/app/Filament/Resources/SaleResource/Pages/CreateSale.php +++ b/app/Filament/Resources/SaleResource/Pages/CreateSale.php @@ -9,6 +9,7 @@ use App\Filament\Resources\SaleResource; use App\Models\Branch; use App\Models\Client; use App\Models\Sale; +use App\Services\Sales\SaleService; use Filament\Resources\Pages\CreateRecord; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Arr; @@ -65,6 +66,16 @@ class CreateSale extends CreateRecord 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['vatable_amount'] = collect($transactions)->sum(fn (array $transaction) => (float) ($transaction['vatable_amount'] ?? 0)); + $data['output_tax'] = collect($transactions)->sum(fn (array $transaction) => (float) ($transaction['output_tax'] ?? 0)); + $data['payable_withholding_tax'] = collect($transactions)->sum(fn (array $transaction) => (float) ($transaction['payable_withholding_tax'] ?? 0)); + $data['discount'] = collect($transactions)->sum(fn (array $transaction) => (float) ($transaction['discount'] ?? 0)); + $data['net_amount'] = collect($transactions)->sum(fn (array $transaction) => (float) ($transaction['net_amount'] ?? 0)); + return Arr::except($data, ['client', 'transactions', 'with_discount']); } @@ -72,7 +83,7 @@ class CreateSale extends CreateRecord { try { DB::beginTransaction(); - $record = Sale::create($data); + $record = app(SaleService::class)->create($this->getFormDataMutation($data)); $branch = $record->branch; foreach ($transactions as $transaction) { @@ -90,6 +101,16 @@ class CreateSale extends CreateRecord ] )->thenReturn(); } + + $accountIds = collect($transactions) + ->pluck('account_id') + ->filter() + ->unique() + ->values() + ->all(); + + $record->accounts()->sync($accountIds); + DB::commit(); } catch (\Exception $exception) { DB::rollBack(); diff --git a/app/Filament/Resources/SaleResource/Pages/EditSale.php b/app/Filament/Resources/SaleResource/Pages/EditSale.php index e5b59ff..c56cf9a 100644 --- a/app/Filament/Resources/SaleResource/Pages/EditSale.php +++ b/app/Filament/Resources/SaleResource/Pages/EditSale.php @@ -36,6 +36,16 @@ class EditSale extends EditRecord 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['vatable_amount'] = collect($transactions)->sum(fn (array $transaction) => (float) ($transaction['vatable_amount'] ?? 0)); + $data['output_tax'] = collect($transactions)->sum(fn (array $transaction) => (float) ($transaction['output_tax'] ?? 0)); + $data['payable_withholding_tax'] = collect($transactions)->sum(fn (array $transaction) => (float) ($transaction['payable_withholding_tax'] ?? 0)); + $data['discount'] = collect($transactions)->sum(fn (array $transaction) => (float) ($transaction['discount'] ?? 0)); + $data['net_amount'] = collect($transactions)->sum(fn (array $transaction) => (float) ($transaction['net_amount'] ?? 0)); + return Arr::except($data, ['client', 'transactions', 'with_discount']); } @@ -71,6 +81,16 @@ class EditSale extends EditRecord ] )->thenReturn(); } + + $accountIds = collect($transactions) + ->pluck('account_id') + ->filter() + ->unique() + ->values() + ->all(); + + $record->accounts()->sync($accountIds); + DB::commit(); } catch (\Exception $exception) { DB::rollBack(); diff --git a/app/Models/Expense.php b/app/Models/Expense.php index 248a04b..6f6d025 100644 --- a/app/Models/Expense.php +++ b/app/Models/Expense.php @@ -5,6 +5,7 @@ namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\MorphMany; class Expense extends Model @@ -43,4 +44,14 @@ class Expense extends Model { return $this->belongsTo(Branch::class); } + + public function accounts(): BelongsToMany + { + return $this->belongsToMany(Account::class, 'account_expense')->withTimestamps(); + } + + public function getAccountsListAttribute(): string + { + return $this->accounts->pluck('account')->implode(', '); + } } diff --git a/app/Models/Sale.php b/app/Models/Sale.php index bf59284..b83bed0 100644 --- a/app/Models/Sale.php +++ b/app/Models/Sale.php @@ -5,6 +5,7 @@ namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\MorphMany; class Sale extends Model @@ -43,4 +44,19 @@ class Sale extends Model { return $this->belongsTo(Branch::class); } + + public function accounts(): BelongsToMany + { + return $this->belongsToMany(Account::class, 'account_sale')->withTimestamps(); + } + + public function getAccountsListAttribute(): string + { + return $this->accounts->pluck('account')->implode(', '); + } + + public function user(): BelongsTo + { + return $this->belongsTo(User::class); + } } diff --git a/app/Services/Sales/SaleService.php b/app/Services/Sales/SaleService.php new file mode 100644 index 0000000..0f51c61 --- /dev/null +++ b/app/Services/Sales/SaleService.php @@ -0,0 +1,31 @@ +id, + ); + return Sale::create($tData->toArray()); + } +} diff --git a/database/migrations/2026_02_15_000002_create_account_sale_and_account_expense_tables.php b/database/migrations/2026_02_15_000002_create_account_sale_and_account_expense_tables.php new file mode 100644 index 0000000..a820f96 --- /dev/null +++ b/database/migrations/2026_02_15_000002_create_account_sale_and_account_expense_tables.php @@ -0,0 +1,36 @@ +id(); + $table->foreignId('sale_id')->constrained()->onDelete('cascade'); + $table->foreignId('account_id')->constrained()->onDelete('cascade'); + $table->timestamps(); + + $table->unique(['sale_id', 'account_id']); + }); + + Schema::create('account_expense', function (Blueprint $table) { + $table->id(); + $table->foreignId('expense_id')->constrained()->onDelete('cascade'); + $table->foreignId('account_id')->constrained()->onDelete('cascade'); + $table->timestamps(); + + $table->unique(['expense_id', 'account_id']); + }); + } + + public function down(): void + { + Schema::dropIfExists('account_expense'); + Schema::dropIfExists('account_sale'); + } +}; +