feat: updates
This commit is contained in:
23
app/Actions/Ledgers/CreateLedgerAction.php
Normal file
23
app/Actions/Ledgers/CreateLedgerAction.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Ledgers;
|
||||
|
||||
use App\Actions\BaseAction;
|
||||
use App\Commands\Ledgers\CreateLedgerCommand;
|
||||
use App\DataObjects\CreateLedgerDTO;
|
||||
use Closure;
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
class CreateLedgerAction extends BaseAction
|
||||
{
|
||||
public function __construct(
|
||||
private readonly CreateLedgerCommand $createLedgerCommand,
|
||||
) {}
|
||||
|
||||
public function __invoke(CreateLedgerDTO|Data $payload, Closure $next)
|
||||
{
|
||||
$this->createLedgerCommand->execute($payload->data);
|
||||
|
||||
return $next($payload);
|
||||
}
|
||||
}
|
||||
91
app/Actions/Transactions/CreateTransactionAction.php
Normal file
91
app/Actions/Transactions/CreateTransactionAction.php
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Transactions;
|
||||
|
||||
use App\Actions\BaseAction;
|
||||
use App\Actions\Ledgers\CreateLedgerAction;
|
||||
use App\DataObjects\CreateLedgerDTO;
|
||||
use App\DataObjects\CreateTransactionDTO;
|
||||
use App\Models\Account;
|
||||
use Closure;
|
||||
use Illuminate\Support\Facades\Pipeline;
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
class CreateTransactionAction extends BaseAction
|
||||
{
|
||||
public function __invoke(CreateTransactionDTO|Data $payload, Closure $next)
|
||||
{
|
||||
$payload->transaction = $payload->transactionable->transactions()->create($payload->data);
|
||||
|
||||
$this->transactionAccountLedger($payload);
|
||||
|
||||
$this->withHoldingAccountLedger($payload);
|
||||
|
||||
return $next($payload);
|
||||
}
|
||||
|
||||
public function transactionAccountLedger($payload): void
|
||||
{
|
||||
$branch = $payload->transaction->branch;
|
||||
|
||||
if ($branch->isClientVatable) {
|
||||
//create transaction account ledger
|
||||
$ledgerPayload = new CreateLedgerDTO(
|
||||
branch_id: $payload->transactionable->branch_id,
|
||||
amount: $payload->transaction->net_amount ?? 0.00,
|
||||
transaction: $payload->transaction,
|
||||
account: $payload->transaction->account,
|
||||
);
|
||||
$this->ledgerPipe($ledgerPayload);
|
||||
|
||||
$this->inputTaxAccountLedger($payload);
|
||||
} else {
|
||||
//create transaction account ledger
|
||||
$ledgerPayload = new CreateLedgerDTO(
|
||||
branch_id: $payload->transactionable->branch_id,
|
||||
amount: $payload->transaction->gross_amount ?? 0.00,
|
||||
transaction: $payload->transaction,
|
||||
account: $payload->transaction->account,
|
||||
);
|
||||
$this->ledgerPipe($ledgerPayload);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function ledgerPipe(CreateLedgerDTO $ledgerPayload): mixed
|
||||
{
|
||||
return Pipeline::send(passable: $ledgerPayload)->through([
|
||||
CreateLedgerAction::class,
|
||||
])->thenReturn();
|
||||
}
|
||||
|
||||
public function inputTaxAccountLedger($payload): void
|
||||
{
|
||||
$inputTax = Account::query()->where('account', 'Input Tax')->whereHas('balances', function ($balance) use ($payload) {
|
||||
return $balance->where('branch_id', $payload->transactionable->branch_id);
|
||||
})->first();
|
||||
|
||||
$ledgerPayload = new CreateLedgerDTO(
|
||||
branch_id: $payload->transactionable->branch_id,
|
||||
amount: $payload->transactionable->input_tax ?? 0.00,
|
||||
transaction: $payload->transaction,
|
||||
account: $inputTax,
|
||||
);
|
||||
$this->ledgerPipe($ledgerPayload);
|
||||
}
|
||||
|
||||
public function withHoldingAccountLedger($payload): void
|
||||
{
|
||||
$withholdingAccount = Account::query()->where('account', 'Payable Withholding Tax')->whereHas('balances', function ($balance) use ($payload) {
|
||||
return $balance->where('branch_id', $payload->transactionable->branch_id);
|
||||
})->first();
|
||||
|
||||
$ledgerPayload = new CreateLedgerDTO(
|
||||
branch_id: $payload->transactionable->branch_id,
|
||||
amount: $payload->transaction->payable_withholding_tax,
|
||||
transaction: $payload->transaction,
|
||||
account: $withholdingAccount,
|
||||
);
|
||||
$this->ledgerPipe($ledgerPayload);
|
||||
}
|
||||
}
|
||||
23
app/Commands/Expenses/GenerateVoucher.php
Normal file
23
app/Commands/Expenses/GenerateVoucher.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Commands\Expenses;
|
||||
|
||||
use App\Models\Branch;
|
||||
use App\Models\Expense;
|
||||
|
||||
class GenerateVoucher
|
||||
{
|
||||
public static function execute(Branch $branch): string
|
||||
{
|
||||
$year = now()->format('y');
|
||||
$lastVoucher = Expense::query()->where('branch_id', $branch->id)->orderBy('created_at', 'desc')->first();
|
||||
|
||||
if (! $lastVoucher) {
|
||||
return $year.'-'.str_pad(1, 6, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
$voucherNumber = (int) explode('-', $lastVoucher->voucher_number)[1];
|
||||
|
||||
return $year.'-'.str_pad($voucherNumber + 1, 6, '0', STR_PAD_LEFT);
|
||||
}
|
||||
}
|
||||
27
app/Commands/Ledgers/CreateLedgerCommand.php
Normal file
27
app/Commands/Ledgers/CreateLedgerCommand.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Commands\Ledgers;
|
||||
|
||||
use App\Commands\Command;
|
||||
use App\Models\Ledger;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class CreateLedgerCommand implements Command
|
||||
{
|
||||
public function execute(array $data): mixed
|
||||
{
|
||||
return DB::transaction(function () use ($data) {
|
||||
return Ledger::query()->updateOrCreate([
|
||||
'id' => $data['id'] ?? null,
|
||||
'transaction_id' => $data['transaction_id'] ?? null,
|
||||
'account_id' => $data['account_id'] ?? null,
|
||||
], [
|
||||
'credit_amount' => $data['credit_amount'] ?? null,
|
||||
'debit_amount' => $data['debit_amount'] ?? null,
|
||||
'description' => $data['description'] ?? null,
|
||||
'branch_id' => $data['branch_id'] ?? null,
|
||||
'client_id' => $data['client_id'] ?? null,
|
||||
]);
|
||||
}, attempts: 2);
|
||||
}
|
||||
}
|
||||
13
app/Commands/Transactions/CreateTransactionCommand.php
Normal file
13
app/Commands/Transactions/CreateTransactionCommand.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Commands\Transactions;
|
||||
|
||||
use App\Commands\Command;
|
||||
|
||||
class CreateTransactionCommand implements Command
|
||||
{
|
||||
public function execute(array $data): mixed
|
||||
{
|
||||
// TODO: Implement execute() method.
|
||||
}
|
||||
}
|
||||
49
app/DataObjects/CreateLedgerDTO.php
Normal file
49
app/DataObjects/CreateLedgerDTO.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace App\DataObjects;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Arr;
|
||||
use Spatie\LaravelData\Attributes\Computed;
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
class CreateLedgerDTO extends Data
|
||||
{
|
||||
#[Computed]
|
||||
public array $data;
|
||||
|
||||
#[Computed]
|
||||
public int $transaction_id;
|
||||
|
||||
#[Computed]
|
||||
public int $account_id;
|
||||
|
||||
#[Computed]
|
||||
public int $client_id;
|
||||
|
||||
#[Computed]
|
||||
public ?string $description;
|
||||
|
||||
#[Computed]
|
||||
public float $credit_amount;
|
||||
|
||||
#[Computed]
|
||||
public float $debit_amount;
|
||||
|
||||
public function __construct(
|
||||
public int $branch_id,
|
||||
public float $amount,
|
||||
public ?Model $ledger = null,
|
||||
public ?Model $transaction = null,
|
||||
public ?Model $account = null,
|
||||
) {
|
||||
$this->transaction_id = $this->transaction->id;
|
||||
$this->account_id = $this->account->id;
|
||||
$this->client_id = $this->transaction->branch->client_id;
|
||||
$this->credit_amount = $this->transaction->account_type == 'credit' ? $this->amount : 0.00;
|
||||
$this->debit_amount = $this->transaction->account_type == 'debit' ? $this->amount : 0.00;
|
||||
$this->description = $this->transaction->description;
|
||||
|
||||
$this->data = Arr::except($this->toArray(), ['transaction', 'ledger', 'account', 'amount']);
|
||||
}
|
||||
}
|
||||
15
app/DataObjects/CreateTransactionDTO.php
Normal file
15
app/DataObjects/CreateTransactionDTO.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\DataObjects;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
class CreateTransactionDTO extends Data
|
||||
{
|
||||
public function __construct(
|
||||
public array $data,
|
||||
public ?Model $transaction = null,
|
||||
public ?Model $transactionable = null,
|
||||
) {}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ namespace App\Filament\Resources;
|
||||
|
||||
use App\Filament\Resources\BranchResource\Pages;
|
||||
use App\Filament\Resources\BranchResource\RelationManagers\BalancesRelationManager;
|
||||
use App\Filament\Resources\BranchResource\RelationManagers\ExpenseRelationManager;
|
||||
use App\Models\Branch;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
@@ -75,6 +76,7 @@ class BranchResource extends Resource
|
||||
return [
|
||||
// AccountsRelationManager::make(),
|
||||
BalancesRelationManager::make(),
|
||||
ExpenseRelationManager::make(),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\BranchResource\RelationManagers;
|
||||
|
||||
use App\Filament\Resources\ExpenseResource;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Resources\RelationManagers\RelationManager;
|
||||
use Filament\Tables\Actions\CreateAction;
|
||||
use Filament\Tables\Table;
|
||||
|
||||
class ExpenseRelationManager extends RelationManager
|
||||
{
|
||||
protected static string $relationship = 'expenses';
|
||||
|
||||
public function form(Form $form): Form
|
||||
{
|
||||
return $form
|
||||
->schema(ExpenseResource::getExpenseFormFields());
|
||||
}
|
||||
|
||||
public function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->recordTitleAttribute('branch_id')
|
||||
->columns(ExpenseResource::getTableColumns())
|
||||
->headerActions([
|
||||
CreateAction::make()
|
||||
->mutateFormDataUsing(
|
||||
fn (array $data): array => app(ExpenseResource\Pages\CreateExpense::class)
|
||||
->getFormDataMutation($data)
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,7 @@ class AccountsRelationManager extends RelationManager
|
||||
->columns([
|
||||
Tables\Columns\TextColumn::make('account')->description(fn (Account $record): string => $record->description ?? ''),
|
||||
Tables\Columns\TextColumn::make('accountType.type'),
|
||||
Tables\Columns\TextColumn::make('normal_balance'),
|
||||
Tables\Columns\TextColumn::make('accountType.normal_balance'),
|
||||
])
|
||||
->filters([
|
||||
//
|
||||
|
||||
@@ -2,12 +2,23 @@
|
||||
|
||||
namespace App\Filament\Resources;
|
||||
|
||||
use App\Commands\Expenses\GenerateVoucher;
|
||||
use App\Filament\Resources\ExpenseResource\Pages;
|
||||
use App\Models\Account;
|
||||
use App\Models\Branch;
|
||||
use App\Models\Client;
|
||||
use App\Models\Expense;
|
||||
use Awcodes\TableRepeater\Components\TableRepeater;
|
||||
use Awcodes\TableRepeater\Header;
|
||||
use Filament\Forms\Components\DatePicker;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Forms\Get;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Tables;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class ExpenseResource extends Resource
|
||||
{
|
||||
@@ -18,21 +29,69 @@ class ExpenseResource extends Resource
|
||||
public static function form(Form $form): Form
|
||||
{
|
||||
return $form
|
||||
->schema([
|
||||
//
|
||||
]);
|
||||
->schema(static::getExpenseFormFields());
|
||||
}
|
||||
|
||||
public static function getExpenseFormFields(): array
|
||||
{
|
||||
return [
|
||||
Select::make('client')
|
||||
->options(Client::query()->get()->pluck('company', 'id'))->live(),
|
||||
Select::make('branch_id')->options(fn ($get) => Branch::query()->where('client_id', $get('client'))->get()->pluck('code', 'id'))
|
||||
->afterStateUpdated(fn ($state, $set) => $set('voucher_number', GenerateVoucher::execute(Branch::find($state))))->live(),
|
||||
TextInput::make('supplier')->label('Supplier Name'),
|
||||
TextInput::make('reference_number')->label('Reference Number'),
|
||||
TextInput::make('voucher_number')->label('Voucher Number'),
|
||||
DatePicker::make('happened_on')->label('Date')->native(false),
|
||||
|
||||
TableRepeater::make('transactions')
|
||||
->headers([
|
||||
Header::make('Charge Account'),
|
||||
Header::make('Description'),
|
||||
Header::make('Gross Amount'),
|
||||
Header::make('Withholding Tax'),
|
||||
Header::make('Net Amount'),
|
||||
])
|
||||
->schema([
|
||||
Select::make('account_id')->options(fn ($get) => static::getAccountOptions($get)),
|
||||
TextInput::make('description')->label('Description'),
|
||||
TextInput::make('gross_amount'),
|
||||
TextInput::make('payable_withholding_tax'),
|
||||
TextInput::make('net_amount'),
|
||||
])->columnSpan('full'),
|
||||
];
|
||||
}
|
||||
|
||||
public static function getAccountOptions(Get $get): Collection
|
||||
{
|
||||
$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', 'Expenses');
|
||||
});
|
||||
|
||||
return $query->get()->pluck('account', 'id');
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
//
|
||||
])
|
||||
->columns(static::getTableColumns())
|
||||
->filters([
|
||||
//
|
||||
])
|
||||
->actions([
|
||||
Tables\Actions\DeleteAction::make(),
|
||||
Tables\Actions\EditAction::make(),
|
||||
])
|
||||
->bulkActions([
|
||||
@@ -42,6 +101,18 @@ class ExpenseResource extends Resource
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getTableColumns(): array
|
||||
{
|
||||
return [
|
||||
Tables\Columns\TextColumn::make('supplier'),
|
||||
Tables\Columns\TextColumn::make('reference_number'),
|
||||
Tables\Columns\TextColumn::make('voucher_number'),
|
||||
Tables\Columns\TextColumn::make('branch.client.company'),
|
||||
Tables\Columns\TextColumn::make('branch.code'),
|
||||
Tables\Columns\TextColumn::make('happened_on'),
|
||||
];
|
||||
}
|
||||
|
||||
public static function getRelations(): array
|
||||
{
|
||||
return [
|
||||
|
||||
@@ -2,10 +2,57 @@
|
||||
|
||||
namespace App\Filament\Resources\ExpenseResource\Pages;
|
||||
|
||||
use App\Actions\Transactions\CreateTransactionAction;
|
||||
use App\DataObjects\CreateTransactionDTO;
|
||||
use App\Filament\Resources\ExpenseResource;
|
||||
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;
|
||||
|
||||
protected function mutateFormDataBeforeCreate(array $data): array
|
||||
{
|
||||
return $this->getFormDataMutation($data);
|
||||
}
|
||||
|
||||
public function getFormDataMutation(array $data): array
|
||||
{
|
||||
return Arr::except($data, ['client', 'transactions']);
|
||||
}
|
||||
|
||||
protected function afterCreate()
|
||||
{
|
||||
$transactions = Arr::only($this->form->getState(), ['transactions']);
|
||||
|
||||
try {
|
||||
$branch = $this->getRecord()->branch;
|
||||
|
||||
foreach ($transactions as $transaction) {
|
||||
|
||||
$data = [
|
||||
'branch_id' => $branch->id,
|
||||
'happened_on' => $this->getRecord()->happened_on,
|
||||
...Arr::first($transaction),
|
||||
];
|
||||
|
||||
$payload = new CreateTransactionDTO(data: $data, transactionable: $this->getRecord());
|
||||
|
||||
Pipeline::send(passable: $payload)->through(
|
||||
[
|
||||
CreateTransactionAction::class,
|
||||
]
|
||||
)->thenReturn();
|
||||
}
|
||||
|
||||
$this->commitDatabaseTransaction();
|
||||
} catch (Exception $exception) {
|
||||
$this->rollBackDatabaseTransaction();
|
||||
throw new LogicException('Failed to save transactions : '.$exception->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@ class RoleResource extends Resource implements HasShieldPermissions
|
||||
);
|
||||
|
||||
return Forms\Components\Section::make($sectionLabel)
|
||||
->description(fn () => new HtmlString('<span style="word-break: break-word;">' . Utils::showModelPath($entity['fqcn']) . '</span>'))
|
||||
->description(fn () => new HtmlString('<span style="word-break: break-word;">'.Utils::showModelPath($entity['fqcn']).'</span>'))
|
||||
->compact()
|
||||
->schema([
|
||||
static::getCheckBoxListComponentForResource($entity),
|
||||
@@ -231,7 +231,7 @@ class RoleResource extends Resource implements HasShieldPermissions
|
||||
{
|
||||
return collect(Utils::getResourcePermissionPrefixes($entity['fqcn']))
|
||||
->flatMap(function ($permission) use ($entity) {
|
||||
$name = $permission . '_' . $entity['resource'];
|
||||
$name = $permission.'_'.$entity['resource'];
|
||||
$label = static::shield()->hasLocalizedPermissionLabels()
|
||||
? FilamentShield::getLocalizedResourcePermissionLabel($permission)
|
||||
: $name;
|
||||
|
||||
@@ -16,6 +16,11 @@ class Account extends Model
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
public function getTypeAttribute(): string
|
||||
{
|
||||
return $this->accountType->type;
|
||||
}
|
||||
|
||||
public function accountType(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(AccountType::class);
|
||||
|
||||
@@ -18,14 +18,6 @@ class Branch extends Model
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
/**
|
||||
* Get the client that owns the Branch
|
||||
*/
|
||||
public function client(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Client::class);
|
||||
}
|
||||
|
||||
public function getCurrentSeriesAttribute()
|
||||
{
|
||||
if ($this->series()->count() > 0) {
|
||||
@@ -43,8 +35,21 @@ class Branch extends Model
|
||||
return $this->hasMany(Series::class);
|
||||
}
|
||||
|
||||
public function getIsClientVatableAttribute(): bool
|
||||
{
|
||||
return $this->client->vatable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the sales for the Branch
|
||||
* Get the client that owns the Branch
|
||||
*/
|
||||
public function client(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Client::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the sales for the Branch
|
||||
*/
|
||||
public function sales(): HasMany
|
||||
{
|
||||
@@ -52,7 +57,7 @@ class Branch extends Model
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the expenses for the Branch
|
||||
* Get all the expenses for the Branch
|
||||
*/
|
||||
public function expenses(): HasMany
|
||||
{
|
||||
@@ -68,4 +73,9 @@ class Branch extends Model
|
||||
{
|
||||
return $this->belongsToThrough(Account::class, Balance::class);
|
||||
}
|
||||
|
||||
public function transactions(): HasMany
|
||||
{
|
||||
return $this->hasMany(Transaction::class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,13 +24,13 @@ class Client extends Model
|
||||
return $this->lname.', '.$this->fname.' '.$this->mname;
|
||||
}
|
||||
|
||||
public function getVatableAttribute()
|
||||
public function getVatableAttribute(): bool
|
||||
{
|
||||
return $this->type->type == 'Vatable' ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the branches for the Client
|
||||
* Get all the branches for the Client
|
||||
*/
|
||||
public function branches(): HasMany
|
||||
{
|
||||
|
||||
@@ -4,8 +4,29 @@ 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;
|
||||
|
||||
class Expense extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
protected $casts = [
|
||||
'happened_on' => 'date:Y-m-d',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get all the transactions for the Sale
|
||||
*/
|
||||
public function transactions(): MorphToMany
|
||||
{
|
||||
return $this->morphToMany(Transaction::class, 'transactionable');
|
||||
}
|
||||
|
||||
public function branch(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Branch::class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,14 @@ namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphToMany;
|
||||
|
||||
class Sale extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
public function transactions(): MorphToMany
|
||||
{
|
||||
return $this->morphToMany(Transaction::class, 'transactionable');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||
|
||||
class Transaction extends Model
|
||||
{
|
||||
@@ -13,43 +15,36 @@ class Transaction extends Model
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
/**
|
||||
* Get the expense that owns the Transaction
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function expense(): BelongsTo
|
||||
public function transactionable(): MorphTo
|
||||
{
|
||||
return $this->belongsTo(Expense::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sale that owns the Transaction
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function sale(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Sale::class);
|
||||
return $this->morphTo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the account that owns the Transaction
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function account(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Account::class);
|
||||
}
|
||||
|
||||
public function getAccountTypeAttribute(): string
|
||||
{
|
||||
return $this->account->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ledgers associated with the Transaction
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasOne
|
||||
* @return HasOne
|
||||
*/
|
||||
public function ledgers(): HasMany
|
||||
{
|
||||
return $this->hasMany(Ledger::class);
|
||||
}
|
||||
|
||||
public function branch(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Branch::class);
|
||||
}
|
||||
}
|
||||
|
||||
68
app/Observers/ExpenseObserver.php
Normal file
68
app/Observers/ExpenseObserver.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace App\Observers;
|
||||
|
||||
use App\Commands\Ledgers\CreateLedgerCommand;
|
||||
use App\Models\Expense;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class ExpenseObserver
|
||||
{
|
||||
/**
|
||||
* Handle the Expense "created" event.
|
||||
*/
|
||||
public function created(Expense $expense): void
|
||||
{
|
||||
DB::transaction(
|
||||
callback: function () use ($expense) {
|
||||
$branch = $expense->branch;
|
||||
//check if client is vatable
|
||||
if ($branch->isClientVatable) {
|
||||
// create a ledgers for vatable
|
||||
$data = [
|
||||
'transaction_id' => $expense->transaction_id,
|
||||
];
|
||||
|
||||
$payload = new CreateLedgerCommand(data: $data);
|
||||
} else {
|
||||
// create a lkedgers for non vatable
|
||||
}
|
||||
|
||||
//create cash transaction
|
||||
},
|
||||
attempts: 2
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the Expense "updated" event.
|
||||
*/
|
||||
public function updated(Expense $expense): void
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the Expense "deleted" event.
|
||||
*/
|
||||
public function deleted(Expense $expense): void
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the Expense "restored" event.
|
||||
*/
|
||||
public function restored(Expense $expense): void
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the Expense "force deleted" event.
|
||||
*/
|
||||
public function forceDeleted(Expense $expense): void
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
108
app/Policies/BranchPolicy.php
Normal file
108
app/Policies/BranchPolicy.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Models\Branch;
|
||||
use App\Models\User;
|
||||
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||
|
||||
class BranchPolicy
|
||||
{
|
||||
use HandlesAuthorization;
|
||||
|
||||
/**
|
||||
* Determine whether the user can view any models.
|
||||
*/
|
||||
public function viewAny(User $user): bool
|
||||
{
|
||||
return $user->can('view_any_branch');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can view the model.
|
||||
*/
|
||||
public function view(User $user, Branch $branch): bool
|
||||
{
|
||||
return $user->can('view_branch');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can create models.
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
return $user->can('create_branch');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can update the model.
|
||||
*/
|
||||
public function update(User $user, Branch $branch): bool
|
||||
{
|
||||
return $user->can('update_branch');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can delete the model.
|
||||
*/
|
||||
public function delete(User $user, Branch $branch): bool
|
||||
{
|
||||
return $user->can('delete_branch');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can bulk delete.
|
||||
*/
|
||||
public function deleteAny(User $user): bool
|
||||
{
|
||||
return $user->can('delete_any_branch');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can permanently delete.
|
||||
*/
|
||||
public function forceDelete(User $user, Branch $branch): bool
|
||||
{
|
||||
return $user->can('force_delete_branch');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can permanently bulk delete.
|
||||
*/
|
||||
public function forceDeleteAny(User $user): bool
|
||||
{
|
||||
return $user->can('force_delete_any_branch');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can restore.
|
||||
*/
|
||||
public function restore(User $user, Branch $branch): bool
|
||||
{
|
||||
return $user->can('restore_branch');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can bulk restore.
|
||||
*/
|
||||
public function restoreAny(User $user): bool
|
||||
{
|
||||
return $user->can('restore_any_branch');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can replicate.
|
||||
*/
|
||||
public function replicate(User $user, Branch $branch): bool
|
||||
{
|
||||
return $user->can('replicate_branch');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can reorder.
|
||||
*/
|
||||
public function reorder(User $user): bool
|
||||
{
|
||||
return $user->can('reorder_branch');
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Models\Client;
|
||||
use App\Models\User;
|
||||
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||
|
||||
class ClientPolicy
|
||||
|
||||
108
app/Policies/ExpensePolicy.php
Normal file
108
app/Policies/ExpensePolicy.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Models\Expense;
|
||||
use App\Models\User;
|
||||
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||
|
||||
class ExpensePolicy
|
||||
{
|
||||
use HandlesAuthorization;
|
||||
|
||||
/**
|
||||
* Determine whether the user can view any models.
|
||||
*/
|
||||
public function viewAny(User $user): bool
|
||||
{
|
||||
return $user->can('view_any_expense');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can view the model.
|
||||
*/
|
||||
public function view(User $user, Expense $expense): bool
|
||||
{
|
||||
return $user->can('view_expense');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can create models.
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
return $user->can('create_expense');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can update the model.
|
||||
*/
|
||||
public function update(User $user, Expense $expense): bool
|
||||
{
|
||||
return $user->can('update_expense');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can delete the model.
|
||||
*/
|
||||
public function delete(User $user, Expense $expense): bool
|
||||
{
|
||||
return $user->can('delete_expense');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can bulk delete.
|
||||
*/
|
||||
public function deleteAny(User $user): bool
|
||||
{
|
||||
return $user->can('delete_any_expense');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can permanently delete.
|
||||
*/
|
||||
public function forceDelete(User $user, Expense $expense): bool
|
||||
{
|
||||
return $user->can('force_delete_expense');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can permanently bulk delete.
|
||||
*/
|
||||
public function forceDeleteAny(User $user): bool
|
||||
{
|
||||
return $user->can('force_delete_any_expense');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can restore.
|
||||
*/
|
||||
public function restore(User $user, Expense $expense): bool
|
||||
{
|
||||
return $user->can('restore_expense');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can bulk restore.
|
||||
*/
|
||||
public function restoreAny(User $user): bool
|
||||
{
|
||||
return $user->can('restore_any_expense');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can replicate.
|
||||
*/
|
||||
public function replicate(User $user, Expense $expense): bool
|
||||
{
|
||||
return $user->can('replicate_expense');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can reorder.
|
||||
*/
|
||||
public function reorder(User $user): bool
|
||||
{
|
||||
return $user->can('reorder_expense');
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,8 @@
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Models\User;
|
||||
use Spatie\Permission\Models\Role;
|
||||
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||
use Spatie\Permission\Models\Role;
|
||||
|
||||
class RolePolicy
|
||||
{
|
||||
|
||||
108
app/Policies/SalePolicy.php
Normal file
108
app/Policies/SalePolicy.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Models\Sale;
|
||||
use App\Models\User;
|
||||
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||
|
||||
class SalePolicy
|
||||
{
|
||||
use HandlesAuthorization;
|
||||
|
||||
/**
|
||||
* Determine whether the user can view any models.
|
||||
*/
|
||||
public function viewAny(User $user): bool
|
||||
{
|
||||
return $user->can('view_any_sale');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can view the model.
|
||||
*/
|
||||
public function view(User $user, Sale $sale): bool
|
||||
{
|
||||
return $user->can('view_sale');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can create models.
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
return $user->can('create_sale');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can update the model.
|
||||
*/
|
||||
public function update(User $user, Sale $sale): bool
|
||||
{
|
||||
return $user->can('update_sale');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can delete the model.
|
||||
*/
|
||||
public function delete(User $user, Sale $sale): bool
|
||||
{
|
||||
return $user->can('delete_sale');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can bulk delete.
|
||||
*/
|
||||
public function deleteAny(User $user): bool
|
||||
{
|
||||
return $user->can('delete_any_sale');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can permanently delete.
|
||||
*/
|
||||
public function forceDelete(User $user, Sale $sale): bool
|
||||
{
|
||||
return $user->can('force_delete_sale');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can permanently bulk delete.
|
||||
*/
|
||||
public function forceDeleteAny(User $user): bool
|
||||
{
|
||||
return $user->can('force_delete_any_sale');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can restore.
|
||||
*/
|
||||
public function restore(User $user, Sale $sale): bool
|
||||
{
|
||||
return $user->can('restore_sale');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can bulk restore.
|
||||
*/
|
||||
public function restoreAny(User $user): bool
|
||||
{
|
||||
return $user->can('restore_any_sale');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can replicate.
|
||||
*/
|
||||
public function replicate(User $user, Sale $sale): bool
|
||||
{
|
||||
return $user->can('replicate_sale');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can reorder.
|
||||
*/
|
||||
public function reorder(User $user): bool
|
||||
{
|
||||
return $user->can('reorder_sale');
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Models\Transmittal;
|
||||
use App\Models\User;
|
||||
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||
|
||||
class TransmittalPolicy
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||
|
||||
class UserPolicy
|
||||
@@ -12,9 +11,6 @@ class UserPolicy
|
||||
|
||||
/**
|
||||
* Determine whether the user can view any models.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return bool
|
||||
*/
|
||||
public function viewAny(User $user): bool
|
||||
{
|
||||
@@ -23,9 +19,6 @@ class UserPolicy
|
||||
|
||||
/**
|
||||
* Determine whether the user can view the model.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return bool
|
||||
*/
|
||||
public function view(User $user): bool
|
||||
{
|
||||
@@ -34,9 +27,6 @@ class UserPolicy
|
||||
|
||||
/**
|
||||
* Determine whether the user can create models.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return bool
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
@@ -45,9 +35,6 @@ class UserPolicy
|
||||
|
||||
/**
|
||||
* Determine whether the user can update the model.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return bool
|
||||
*/
|
||||
public function update(User $user): bool
|
||||
{
|
||||
@@ -56,9 +43,6 @@ class UserPolicy
|
||||
|
||||
/**
|
||||
* Determine whether the user can delete the model.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return bool
|
||||
*/
|
||||
public function delete(User $user): bool
|
||||
{
|
||||
@@ -67,9 +51,6 @@ class UserPolicy
|
||||
|
||||
/**
|
||||
* Determine whether the user can bulk delete.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return bool
|
||||
*/
|
||||
public function deleteAny(User $user): bool
|
||||
{
|
||||
@@ -78,9 +59,6 @@ class UserPolicy
|
||||
|
||||
/**
|
||||
* Determine whether the user can permanently delete.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return bool
|
||||
*/
|
||||
public function forceDelete(User $user): bool
|
||||
{
|
||||
@@ -89,9 +67,6 @@ class UserPolicy
|
||||
|
||||
/**
|
||||
* Determine whether the user can permanently bulk delete.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return bool
|
||||
*/
|
||||
public function forceDeleteAny(User $user): bool
|
||||
{
|
||||
@@ -100,9 +75,6 @@ class UserPolicy
|
||||
|
||||
/**
|
||||
* Determine whether the user can restore.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return bool
|
||||
*/
|
||||
public function restore(User $user): bool
|
||||
{
|
||||
@@ -111,9 +83,6 @@ class UserPolicy
|
||||
|
||||
/**
|
||||
* Determine whether the user can bulk restore.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return bool
|
||||
*/
|
||||
public function restoreAny(User $user): bool
|
||||
{
|
||||
@@ -122,9 +91,6 @@ class UserPolicy
|
||||
|
||||
/**
|
||||
* Determine whether the user can bulk restore.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return bool
|
||||
*/
|
||||
public function replicate(User $user): bool
|
||||
{
|
||||
@@ -133,9 +99,6 @@ class UserPolicy
|
||||
|
||||
/**
|
||||
* Determine whether the user can reorder.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return bool
|
||||
*/
|
||||
public function reorder(User $user): bool
|
||||
{
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Policies\RolePolicy;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Spatie\Permission\Models\Role;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
@@ -19,6 +22,6 @@ class AppServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
//
|
||||
Gate::policy(Role::class, RolePolicy::class);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user