ultimatepos/Modules/Accounting/Services/BankLoanService.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;
}
}