Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
95.45% covered (success)
95.45%
21 / 22
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
AccountSummaryData
95.45% covered (success)
95.45%
21 / 22
50.00% covered (danger)
50.00%
1 / 2
2
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
1 / 1
1
 jsonSerialize
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3declare(strict_types=1);
4
5namespace App\Domain\Account\Data;
6
7use App\Support\Row;
8use JsonSerializable;
9
10/**
11 * Data transfer object for account summary information.
12 *
13 * All properties use camelCase. Repository handles snake_case conversion.
14 *
15 * All monetary values and ratios are stored as strings to preserve
16 * exact decimal precision from PostgreSQL NUMERIC types.
17 */
18final class AccountSummaryData implements JsonSerializable
19{
20    public int $accountId;
21
22    public int $investorId;
23
24    public string $accountNumber;
25
26    public string $balance;
27
28    public string $availableBalance;
29
30    public string $availableForLoan;
31
32    public string $maxLoanAmount;
33
34    public string $totalOutstandingLoans;
35
36    public string $earningsYtd;
37
38    /** FSC-68: total loan interest paid since Jan 1 of the current year. */
39    public string $interestPaidYtd;
40    public string $interestRate;
41
42    public string $loanToValueRatio;
43
44    public string $loanInterestRate;
45    public string $status;
46
47    public bool $hasAvailableCredit;
48
49    public bool $hasActiveLoans;
50
51    public string $lendingBalance;
52
53    public bool $lendingPendingDisbursement;
54
55    public ?string $nextLoanPaymentDue;
56
57    /** FSC-48: sum of investments within the configured lock-up window. */
58    public string $lockedBalance;
59
60    /** FSC-48: configured lock-up period in days, surfaced for UI copy. */
61    public int $lockupPeriodDays;
62
63    /**
64     * @param array<mixed> $data Repository row, camelCase keys
65     */
66    public function __construct(array $data)
67    {
68        $this->accountId = Row::int($data, 'accountId');
69        $this->investorId = Row::int($data, 'investorId');
70        $this->accountNumber = Row::string($data, 'accountNumber');
71        $this->balance = Row::string($data, 'balance');
72        $this->availableBalance = Row::string($data, 'availableBalance');
73        $this->availableForLoan = Row::string($data, 'availableForLoan');
74        $this->maxLoanAmount = Row::string($data, 'maxLoanAmount');
75        $this->totalOutstandingLoans = Row::string($data, 'totalOutstandingLoans');
76        $this->earningsYtd = Row::string($data, 'earningsYtd');
77        $this->interestPaidYtd = Row::string($data, 'interestPaidYtd');
78        $this->interestRate = Row::string($data, 'interestRate');
79        $this->loanToValueRatio = Row::string($data, 'loanToValueRatio');
80        $this->loanInterestRate = Row::string($data, 'loanInterestRate');
81        $this->status = Row::string($data, 'status');
82        $this->hasAvailableCredit = Row::nullableBool($data, 'hasAvailableCredit') ?? false;
83        $this->hasActiveLoans = Row::nullableBool($data, 'hasActiveLoans') ?? false;
84        $this->lendingBalance = Row::string($data, 'lendingBalance');
85        $this->lendingPendingDisbursement = Row::nullableBool($data, 'lendingPendingDisbursement') ?? false;
86        $this->nextLoanPaymentDue = Row::nullableString($data, 'nextLoanPaymentDue');
87        $this->lockedBalance = Row::nullableString($data, 'lockedBalance') ?? '0.00';
88        $this->lockupPeriodDays = Row::nullableInt($data, 'lockupPeriodDays') ?? 90;
89    }
90
91    /**
92     * @return array<mixed>
93     */
94    public function jsonSerialize(): array
95    {
96        return get_object_vars($this);
97    }
98}