94 lines
3.7 KiB
PHP
94 lines
3.7 KiB
PHP
<?php
|
|
|
|
namespace Modules\Accounting\Services;
|
|
|
|
use Modules\Accounting\Domain\FinancialPostingRequest;
|
|
use Modules\Accounting\Entities\AccountingBankLoan;
|
|
use Modules\Accounting\Entities\AccountingBankLoanPayment;
|
|
|
|
class BankLoanService
|
|
{
|
|
public function __construct(protected FinancialPostingService $postingService) {}
|
|
|
|
public function disburse(array $data, int $businessId, int $userId): AccountingBankLoan
|
|
{
|
|
$loan = AccountingBankLoan::create(array_merge($data, [
|
|
'business_id' => $businessId,
|
|
'created_by' => $userId,
|
|
'status' => 'active',
|
|
'paid_principal' => 0,
|
|
]));
|
|
|
|
if (! empty($data['loan_account_id']) && ! empty($data['bank_account_id'])) {
|
|
$mapping = $this->postingService->post(new FinancialPostingRequest(
|
|
businessId: $businessId,
|
|
userId: $userId,
|
|
sourceType: 'bank_loan_disbursement',
|
|
sourceId: $loan->id,
|
|
note: 'Loan '.$loan->loan_number,
|
|
lines: [
|
|
['accounting_account_id' => (int) $data['bank_account_id'], 'amount' => (float) $loan->principal_amount, 'type' => 'debit'],
|
|
['accounting_account_id' => (int) $data['loan_account_id'], 'amount' => (float) $loan->principal_amount, 'type' => 'credit'],
|
|
],
|
|
operationDate: $loan->disbursement_date->format('Y-m-d'),
|
|
));
|
|
$loan->journal_mapping_id = $mapping?->id;
|
|
$loan->save();
|
|
}
|
|
|
|
return $loan;
|
|
}
|
|
|
|
public function recordPayment(AccountingBankLoan $loan, array $data, int $userId): AccountingBankLoanPayment
|
|
{
|
|
$principal = (float) ($data['principal_amount'] ?? 0);
|
|
$interest = (float) ($data['interest_amount'] ?? 0);
|
|
$total = $principal + $interest;
|
|
|
|
$payment = AccountingBankLoanPayment::create([
|
|
'bank_loan_id' => $loan->id,
|
|
'payment_date' => $data['payment_date'],
|
|
'principal_amount' => $principal,
|
|
'interest_amount' => $interest,
|
|
'total_amount' => $total,
|
|
'bank_account_id' => $data['bank_account_id'] ?? null,
|
|
'interest_account_id' => $data['interest_account_id'] ?? null,
|
|
'note' => $data['note'] ?? null,
|
|
'created_by' => $userId,
|
|
]);
|
|
|
|
$lines = [];
|
|
if ($principal > 0 && $loan->loan_account_id) {
|
|
$lines[] = ['accounting_account_id' => (int) $loan->loan_account_id, 'amount' => $principal, 'type' => 'debit'];
|
|
}
|
|
if ($interest > 0 && ! empty($data['interest_account_id'])) {
|
|
$lines[] = ['accounting_account_id' => (int) $data['interest_account_id'], 'amount' => $interest, 'type' => 'debit'];
|
|
}
|
|
if ($total > 0 && ! empty($data['bank_account_id'])) {
|
|
$lines[] = ['accounting_account_id' => (int) $data['bank_account_id'], 'amount' => $total, 'type' => 'credit'];
|
|
}
|
|
|
|
if (count($lines) >= 2) {
|
|
$mapping = $this->postingService->post(new FinancialPostingRequest(
|
|
businessId: $loan->business_id,
|
|
userId: $userId,
|
|
sourceType: 'bank_loan_payment',
|
|
sourceId: $payment->id,
|
|
note: 'Loan payment '.$loan->loan_number,
|
|
lines: $lines,
|
|
operationDate: $payment->payment_date->format('Y-m-d'),
|
|
));
|
|
$payment->journal_mapping_id = $mapping?->id;
|
|
$payment->save();
|
|
}
|
|
|
|
$loan->paid_principal = (float) $loan->paid_principal + $principal;
|
|
if ($loan->remainingPrincipal() <= 0.01) {
|
|
$loan->status = 'paid';
|
|
}
|
|
$loan->save();
|
|
|
|
return $payment;
|
|
}
|
|
}
|