diff --git a/app/Filament/Resources/ExpenseResource.php b/app/Filament/Resources/ExpenseResource.php index ebbdd92..c56c54d 100644 --- a/app/Filament/Resources/ExpenseResource.php +++ b/app/Filament/Resources/ExpenseResource.php @@ -11,6 +11,7 @@ use App\Models\Expense; use Awcodes\TableRepeater\Components\TableRepeater; use Awcodes\TableRepeater\Header; use Filament\Forms\Components\DatePicker; +use Filament\Forms\Components\Hidden; use Filament\Forms\Components\Select; use Filament\Forms\Components\TextInput; use Filament\Forms\Form; @@ -50,7 +51,10 @@ class ExpenseResource extends Resource Select::make('branch_id') ->relationship('branch', 'code') ->options(fn ($get) => Branch::query()->where('client_id', $get('client'))->get()->pluck('code', 'id')) - ->afterStateUpdated(fn ($set, $get) => $set('voucher_number', static::getVoucherNumber($get))) + ->afterStateUpdated(function ($set, $get) { + $set('voucher_number', static::getVoucherNumber($get)); + $set('transactions.*.branch_id', $get('branch_id')); + }) ->required() ->live(), TextInput::make('supplier')->label('Supplier Name')->required(), @@ -60,13 +64,17 @@ class ExpenseResource extends Resource ->readOnly(), DatePicker::make('happened_on')->label('Date') ->required() + ->afterStateUpdated(function ($set, $get) { + $set('transactions.*.happened_on', $get('happened_on')); + }) + ->live() ->native(false), TableRepeater::make('transactions') ->headers(fn (Get $get): array => static::getTransactionTableHeader($get)) ->relationship('transactions') ->schema(fn (Get $get): array => static::getTransactionTableFormSchema($get)) - + ->visible(fn (Get $get) => $get('branch_id') != null) ->columnSpan('full'), ]; } @@ -98,6 +106,7 @@ class ExpenseResource extends Resource return [ Header::make('Charge Account'), Header::make('Description'), + // Header::make('Branch'), Header::make('Gross Amount'), Header::make('Exempt'), Header::make('Zero Rated'), @@ -130,9 +139,10 @@ class ExpenseResource extends Resource return [ Select::make('account_id')->options(fn ($get) => static::getAccountOptions($get)), TextInput::make('description')->label('Description'), + Hidden::make('branch_id')->default(fn (Get $get) => $get('../../branch_id')), TextInput::make('gross_amount') ->numeric() - ->live() + ->live(false, 500) ->afterStateUpdated(function (Get $get, Set $set, ?string $old, ?string $state) { static::setDefaultFormValues($get, $set, $old, $state); })->default(0), @@ -151,11 +161,11 @@ class ExpenseResource extends Resource })->default(0), TextInput::make('vatable_amount') ->numeric() + ->nullable() ->live() - ->afterStateUpdated(function (Get $get, Set $set, ?string $old, ?string $state) { - - static::setDefaultFormValues($get, $set, $old, $state); - })->default(0), + ->readOnly() + ->default(0), + Hidden::make('happened_on')->default(fn (Get $get) => $get('../../happened_on')), TextInput::make('input_tax') ->numeric() ->live() @@ -202,19 +212,22 @@ class ExpenseResource extends Resource $exempt = (float) $get('exempt'); $withHoldingTax = (float) $get('payable_withholding_tax'); $vatableSales = $get('gross_amount'); - $vatableAmount = $vatableSales / 1.12; + $vatableAmount = 0; + if ($vatableSales) { + $vatableAmount = $vatableSales / 1.12; + } $inputTax = $vatableAmount * 0.12; - $netAmount = $get('gross_amount') - $get('payable_withholding_tax'); + $netAmount = (int) $vatableSales - $get('payable_withholding_tax'); if (static::getIsVatable($get)) { $netAmount = ($vatableAmount + $exempt) - $withHoldingTax; } - $set('input_tax', number_format($inputTax, 2)); - $set('vatable_amount', number_format($vatableAmount, 2)); - $set('net_amount', number_format($netAmount, 2)); + $set('input_tax', number_format($inputTax, 2, '.', '')); + $set('vatable_amount', number_format($vatableAmount, 2, '.', '')); + $set('net_amount', number_format($netAmount, 2, '.', '')); } public static function getIsVatable(Get $get): bool @@ -228,7 +241,6 @@ class ExpenseResource extends Resource public static function isVatable(bool $value): void { static::$isVatable = $value; - dump('sett'); } public static function table(Table $table): Table diff --git a/app/Filament/Resources/ExpenseResource/Pages/CreateExpense.php b/app/Filament/Resources/ExpenseResource/Pages/CreateExpense.php index 981e821..27fcca8 100644 --- a/app/Filament/Resources/ExpenseResource/Pages/CreateExpense.php +++ b/app/Filament/Resources/ExpenseResource/Pages/CreateExpense.php @@ -17,6 +17,7 @@ class CreateExpense extends CreateRecord protected function mutateFormDataBeforeCreate(array $data): array { + return $this->getFormDataMutation($data); } @@ -25,7 +26,7 @@ class CreateExpense extends CreateRecord return Arr::except($data, ['client', 'transactions']); } - protected function afterCreate() + protected function afterCreate(): void { $transactions = Arr::only($this->form->getState(), ['transactions']); diff --git a/app/Filament/Resources/SaleResource.php b/app/Filament/Resources/SaleResource.php index 7249910..9189215 100644 --- a/app/Filament/Resources/SaleResource.php +++ b/app/Filament/Resources/SaleResource.php @@ -3,8 +3,20 @@ namespace App\Filament\Resources; use App\Filament\Resources\SaleResource\Pages; +use App\Models\Account; +use App\Models\Branch; +use App\Models\Client; use App\Models\Sale; +use Awcodes\TableRepeater\Components\TableRepeater; +use Awcodes\TableRepeater\Header; +use Filament\Forms\Components\Checkbox; +use Filament\Forms\Components\DatePicker; +use Filament\Forms\Components\Hidden; +use Filament\Forms\Components\Select; +use Filament\Forms\Components\TextInput; use Filament\Forms\Form; +use Filament\Forms\Get; +use Filament\Forms\Set; use Filament\Resources\Resource; use Filament\Tables; use Filament\Tables\Table; @@ -19,10 +31,186 @@ class SaleResource extends Resource { return $form ->schema([ - // + Select::make('client') + ->options(Client::query()->get()->pluck('company', 'id')) + ->afterStateUpdated(function ($set, $get) { + $set('branch_id', ''); + }) + ->required() + ->live(), + Select::make('branch_id') + ->relationship('branch', 'code') + ->options(fn ($get) => Branch::query()->where('client_id', $get('client'))->get()->pluck('code', 'id')) + ->required() + ->afterStateUpdated(function ($set, $get) { + $set('current_series', static::getSeries($get)); + $set('transactions.*.branch_id', $get('branch_id')); + }) + ->live(), + TextInput::make('current_series') + ->label('Series') + ->disabled(), + DatePicker::make('happened_on')->label('Date') + ->required() + ->afterStateUpdated(function ($set, $get) { + $set('transactions.*.happened_on', $get('happened_on')); + }) + ->native(false), + Checkbox::make('with_discount')->label('With Discount?')->default(false)->live(), + + TableRepeater::make('transactions') + ->headers(fn (Get $get): array => static::getTransactionTableHeader($get)) + ->relationship('transactions') + ->schema(fn (Get $get): array => static::getTransactionTableFormSchema($get)) + ->visible(fn (Get $get) => $get('branch_id') != null) + ->columnSpan('full'), ]); } + public static function getSeries(Get $get): string + { + $branch = Branch::find($get('branch_id')); + + if ($branch) { + $currentSeries = $branch->current_series; + + return str_pad($currentSeries + 1, 6, '0', STR_PAD_LEFT); + } + + return ''; + + } + + private static function getTransactionTableHeader(Get $get): array + { + if ($get('with_discount')) { + return [ + Header::make('Charge Account'), + Header::make('Description'), + Header::make('Gross Amount'), + Header::make('Exempt'), + Header::make('Vatable Amount'), + Header::make('Output Tax'), + Header::make('Withholding Tax'), + Header::make('Discount'), + Header::make('Net Amount'), + ]; + } + + return [ + Header::make('Charge Account'), + Header::make('Description'), + Header::make('Gross Amount'), + Header::make('Exempt'), + Header::make('Vatable Amount'), + Header::make('Output Tax'), + Header::make('Withholding Tax'), + Header::make('Net Amount'), + ]; + } + + private static function getTransactionTableFormSchema(Get $get): array + { + return [ + Select::make('account_id')->options(fn ($get) => static::getAccountOptions($get)), + TextInput::make('description')->label('Description'), + Hidden::make('branch_id')->default(fn (Get $get) => $get('../../branch_id')), + TextInput::make('gross_amount') + ->numeric() + ->live(false, 500) + ->afterStateUpdated(function (Get $get, Set $set, ?string $old, ?string $state) { + static::setDefaultFormValues($get, $set, $old, $state); + })->default(0), + TextInput::make('exempt') + ->numeric() + ->live() + ->afterStateUpdated(function (Get $get, Set $set, ?string $old, ?string $state) { + static::setDefaultFormValues($get, $set, $old, $state); + })->default(0), + TextInput::make('vatable_amount') + ->numeric() + ->nullable() + ->live() + ->readOnly() + ->default(0), + Hidden::make('happened_on')->default(fn (Get $get) => $get('../../happened_on')), + Hidden::make('with_discount')->default(fn (Get $get) => $get('../../with_discount')), + TextInput::make('output_tax') + ->numeric() + ->live() + ->afterStateUpdated(function (Get $get, Set $set, ?string $old, ?string $state) { + + static::setDefaultFormValues($get, $set, $old, $state); + })->default(0), + TextInput::make('payable_withholding_tax') + ->numeric() + ->live() + ->afterStateUpdated(function (Get $get, Set $set, ?string $old, ?string $state) { + + static::setDefaultFormValues($get, $set, $old, $state); + })->default(0), + TextInput::make('discount') + ->numeric() + ->readOnly() + ->visible(fn (Get $get) => $get('../../with_discount')) + ->live(), + TextInput::make('net_amount')->numeric()->default(0), + ]; + } + + private static function getAccountOptions($get) + { + $query = Account::query(); + + $query->where([ + 'client_id' => $get('../../client'), + ]); + + if ($get('../../branch_id')) { + $query->whereHas('balances', function ($query) use ($get) { + return $query->where('branch_id', $get('../../branch_id')); + }); + } + + $query->whereHas('accountType', function ($query) { + return $query->where('type', 'Revenue'); + }); + + return $query->get()->pluck('account', 'id'); + } + + private static function setDefaultFormValues(Get $get, Set $set, ?string $old, ?string $state) + { + $exempt = (float) $get('exempt'); + $withHoldingTax = (float) $get('payable_withholding_tax'); + $vatableSales = $get('gross_amount'); + $vatableAmount = 0; + if ($vatableSales) { + $vatableAmount = $vatableSales / 1.12; + } + + $discount = $exempt * .20; + $outputTax = $vatableAmount * 0.12; + + //default net amount + $netAmount = (int) $vatableSales - $get('payable_withholding_tax'); + + //net amount if vatable + if (ExpenseResource::getIsVatable($get)) { + $netAmount = ($vatableAmount + $exempt) - $withHoldingTax; + } + + //if discounted + if ($get('../../with_discount')) { + $netAmount = $netAmount - $discount; + } + + $set('output_tax', number_format($outputTax, 2, '.', '')); + $set('discount', number_format($discount, 2, '.', '')); + $set('vatable_amount', number_format($vatableAmount, 2, '.', '')); + $set('net_amount', number_format($netAmount, 2, '.', '')); + } + public static function table(Table $table): Table { return $table diff --git a/app/Filament/Resources/SaleResource/Pages/CreateSale.php b/app/Filament/Resources/SaleResource/Pages/CreateSale.php index f6d96fc..310f1aa 100644 --- a/app/Filament/Resources/SaleResource/Pages/CreateSale.php +++ b/app/Filament/Resources/SaleResource/Pages/CreateSale.php @@ -3,9 +3,27 @@ namespace App\Filament\Resources\SaleResource\Pages; use App\Filament\Resources\SaleResource; +use App\Models\Branch; use Filament\Resources\Pages\CreateRecord; +use Illuminate\Support\Arr; class CreateSale extends CreateRecord { protected static string $resource = SaleResource::class; + + protected function mutateFormDataBeforeCreate(array $data): array + { + return $this->getFormDataMutation($data); + } + + public function getFormDataMutation(array $data): array + { + return Arr::except($data, ['client', 'transactions', 'with_discount']); + } + + protected function afterCreate(): void + { + $branch = Branch::find($this->data['branch_id']); + dd($branch); + } } diff --git a/app/Models/Expense.php b/app/Models/Expense.php index be177c8..b41f733 100644 --- a/app/Models/Expense.php +++ b/app/Models/Expense.php @@ -5,7 +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\MorphToMany; +use Illuminate\Database\Eloquent\Relations\MorphMany; class Expense extends Model { @@ -20,9 +20,9 @@ class Expense extends Model /** * Get all the transactions for the Sale */ - public function transactions(): MorphToMany + public function transactions(): MorphMany { - return $this->morphToMany(Transaction::class, 'transactionable'); + return $this->morphMany(Transaction::class, 'transactionable'); } public function branch(): BelongsTo diff --git a/app/Models/Sale.php b/app/Models/Sale.php index 196a5f9..97707d8 100644 --- a/app/Models/Sale.php +++ b/app/Models/Sale.php @@ -4,14 +4,29 @@ namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\Relations\MorphToMany; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\MorphMany; class Sale extends Model { use HasFactory; - public function transactions(): MorphToMany + protected $guarded = []; + + protected $casts = [ + 'happened_on' => 'date:Y-m-d', + ]; + + /** + * Get all the transactions for the Sale + */ + public function transactions(): MorphMany { - return $this->morphToMany(Transaction::class, 'transactionable'); + return $this->morphMany(Transaction::class, 'transactionable'); + } + + public function branch(): BelongsTo + { + return $this->belongsTo(Branch::class); } } diff --git a/database/migrations/2024_08_12_070246_create_transactionables_table.php b/database/migrations/2024_08_12_070246_create_transactionables_table.php deleted file mode 100644 index a7f38e9..0000000 --- a/database/migrations/2024_08_12_070246_create_transactionables_table.php +++ /dev/null @@ -1,29 +0,0 @@ -id(); - $table->unsignedBigInteger('transaction_id'); - $table->unsignedBigInteger('transactionable_id'); - $table->string('transactionable_type'); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::dropIfExists('transactionables'); - } -};