This commit is contained in:
Dennis Eichhorn 2024-04-07 17:31:42 +00:00
parent d0e97083f1
commit 7707a72946
19 changed files with 799 additions and 159 deletions

View File

@ -57,21 +57,6 @@
"permission": { "permission": 2, "type": null, "element": null },
"parent": 1008301001,
"children": []
},
{
"id": 1008305001,
"pid": "/finance/loan",
"type": 3,
"subtype": 1,
"name": "Entries",
"uri": "{/base}/finance/loan/entry/list?{?}",
"target": "self",
"icon": null,
"order": 15,
"from": "LoanManagement",
"permission": { "permission": 2, "type": null, "element": null },
"parent": 1008301001,
"children": []
}
]
}

View File

@ -1,6 +1,17 @@
[
{
"name": "loan",
"sign": 1,
"isLoan": true,
"l11n": {
"en": "Loan",
"de": "Darlehen"
}
},
{
"name": "disagio",
"sign": -1,
"isLoan": true,
"l11n": {
"en": "Disagio",
"de": "Disagio"
@ -8,6 +19,7 @@
},
{
"name": "interest",
"sign": -1,
"l11n": {
"en": "Interest",
"de": "Zinsen"
@ -15,6 +27,8 @@
},
{
"name": "repayment",
"sign": -1,
"isLoan": true,
"l11n": {
"en": "Repayment",
"de": "Tilgung"
@ -22,6 +36,8 @@
},
{
"name": "unscheduled_repayment",
"sign": -1,
"isLoan": true,
"l11n": {
"en": "Unscheduled repayment",
"de": "Sondertilgung"
@ -29,6 +45,7 @@
},
{
"name": "commitment_fee",
"sign": -1,
"l11n": {
"en": "Commitment fee",
"de": "Bereitstellungsgebühr"
@ -36,6 +53,7 @@
},
{
"name": "taxes",
"sign": -1,
"l11n": {
"en": "Taxes",
"de": "Steuern"
@ -43,6 +61,7 @@
},
{
"name": "other",
"sign": -1,
"l11n": {
"en": "Others",
"de": "Sonstige"

View File

@ -14,6 +14,16 @@
"type": "VARCHAR(255)",
"null": false,
"unique": true
},
"loanmgmt_cost_type_sign": {
"name": "loanmgmt_cost_type_sign",
"type": "TINYINT(1)",
"null": false
},
"loanmgmt_cost_type_loan": {
"name": "loanmgmt_cost_type_loan",
"type": "TINYINT(1)",
"null": false
}
}
},
@ -59,13 +69,8 @@
"primary": true,
"autoincrement": true
},
"loanmgmt_loan_start": {
"name": "loanmgmt_loan_start",
"type": "DATETIME",
"null": true
},
"loanmgmt_loan_title": {
"name": "loanmgmt_loan_title",
"loanmgmt_loan_name": {
"name": "loanmgmt_loan_name",
"type": "VARCHAR(255)",
"null": false
},
@ -74,58 +79,47 @@
"type": "TEXT",
"null": false
},
"loanmgmt_loan_payout_date": {
"name": "loanmgmt_loan_payout_date",
"loanmgmt_loan_status": {
"name": "loanmgmt_loan_status",
"type": "INT",
"null": false
},
"loanmgmt_loan_borrowing_rate": {
"name": "loanmgmt_loan_borrowing_rate",
"type": "INT",
"null": false
},
"loanmgmt_loan_post_rate": {
"name": "loanmgmt_loan_post_rate",
"type": "INT",
"null": false
},
"loanmgmt_loan_special_payment": {
"name": "loanmgmt_loan_special_payment",
"type": "INT",
"null": false
},
"loanmgmt_loan_supplier": {
"name": "loanmgmt_loan_supplier",
"type": "INT",
"null": false,
"foreignTable": "suppliermgmt_supplier",
"foreignKey": "suppliermgmt_supplier_id"
},
"loanmgmt_loan_start": {
"name": "loanmgmt_loan_start",
"type": "DATETIME",
"null": true
},
"loanmgmt_loan_amount": {
"name": "loanmgmt_loan_amount",
"type": "BIGINT",
"null": false
},
"loanmgmt_loan_disagio": {
"name": "loanmgmt_loan_disagio",
"type": "BIGINT",
"null": false
},
"loanmgmt_loan_provision": {
"description": "Bereitstellungsgebuehr",
"name": "loanmgmt_loan_provision",
"type": "BIGINT",
"null": false
},
"loanmgmt_loan_provision_rate": {
"description": "Bereitstellungsgebuehr",
"name": "loanmgmt_loan_provision_rate",
"type": "BIGINT",
"null": false
},
"loanmgmt_loan_interest_start": {
"name": "loanmgmt_loan_interest_start",
"loanmgmt_loan_end": {
"name": "loanmgmt_loan_end",
"type": "DATETIME",
"null": true
},
"loanmgmt_loan_interest_rate": {
"name": "loanmgmt_loan_interest_rate",
"type": "INT",
"null": false
},
"loanmgmt_loan_interest_rate_post": {
"description": "Interest rate after binding period",
"name": "loanmgmt_loan_interest_rate_post",
"type": "INT",
"null": false
},
"loanmgmt_loan_rate_binding": {
"name": "loanmgmt_loan_rate_binding",
"type": "INT",
"null": false
},
"loanmgmt_loan_repayment_type": {
"name": "loanmgmt_loan_repayment_type",
"type": "TINYINT",
"null": false
"loanmgmt_loan_created_at": {
"name": "loanmgmt_loan_created_at",
"type": "DATETIME",
"null": true
},
"loanmgmt_loan_created_by": {
"name": "loanmgmt_loan_created_by",
@ -143,5 +137,48 @@
"foreignKey": "unit_id"
}
}
},
"loanmgmt_loan_element": {
"name": "loanmgmt_loan_element",
"fields": {
"loanmgmt_loan_element_id": {
"name": "loanmgmt_loan_element_id",
"type": "INT",
"null": false,
"primary": true,
"autoincrement": true
},
"loanmgmt_loan_description": {
"name": "loanmgmt_loan_description",
"type": "TEXT",
"null": false
},
"loanmgmt_loan_element_amount": {
"name": "loanmgmt_loan_element_amount",
"type": "BIGINT",
"null": false
},
"loanmgmt_loan_element_date": {
"name": "loanmgmt_loan_element_date",
"type": "DATETIME",
"null": true
},
"loanmgmt_loan_element_type": {
"name": "loanmgmt_loan_element_type",
"type": "INT",
"default": null,
"null": true,
"foreignTable": "loanmgmt_cost_type",
"foreignKey": "loanmgmt_cost_type_id"
},
"loanmgmt_loan_element_loan": {
"name": "loanmgmt_loan_element_loan",
"type": "INT",
"default": null,
"null": true,
"foreignTable": "loanmgmt_loan",
"foreignKey": "loanmgmt_loan_id"
}
}
}
}

View File

@ -83,6 +83,8 @@ final class Installer extends InstallerAbstract
$request->header->account = 1;
$request->setData('name', $type['name'] ?? '');
$request->setData('title', \reset($type['l11n']));
$request->setData('sign', $type['sign'] ?? -1);
$request->setData('is_loan', $type['isLoan'] ?? false);
$module->apiLoanCostTypeCreate($request, $response);

View File

@ -10,6 +10,7 @@ return [
[
'dest' => '\Modules\LoanManagement\Controller\BackendController:viewLoanList',
'verb' => RouteVerb::GET,
'active' => true,
'permission' => [
'module' => BackendController::MODULE_NAME,
'type' => PermissionType::READ,
@ -21,6 +22,7 @@ return [
[
'dest' => '\Modules\LoanManagement\Controller\BackendController:viewLoanView',
'verb' => RouteVerb::GET,
'active' => true,
'permission' => [
'module' => BackendController::MODULE_NAME,
'type' => PermissionType::READ,
@ -32,6 +34,7 @@ return [
[
'dest' => '\Modules\LoanManagement\Controller\BackendController:viewLoanCreate',
'verb' => RouteVerb::GET,
'active' => true,
'permission' => [
'module' => BackendController::MODULE_NAME,
'type' => PermissionType::CREATE,
@ -43,28 +46,7 @@ return [
[
'dest' => '\Modules\LoanManagement\Controller\BackendController:viewLoanTable',
'verb' => RouteVerb::GET,
'permission' => [
'module' => BackendController::MODULE_NAME,
'type' => PermissionType::READ,
'state' => PermissionCategory::LOAN,
],
],
],
'^/finance/loan/entry/list(\?.*$|$)' => [
[
'dest' => '\Modules\LoanManagement\Controller\BackendController:viewLoanEntryList',
'verb' => RouteVerb::GET,
'permission' => [
'module' => BackendController::MODULE_NAME,
'type' => PermissionType::READ,
'state' => PermissionCategory::LOAN,
],
],
],
'^/finance/loan/entry/view(\?.*$|$)' => [
[
'dest' => '\Modules\LoanManagement\Controller\BackendController:viewLoanEntryView',
'verb' => RouteVerb::GET,
'active' => true,
'permission' => [
'module' => BackendController::MODULE_NAME,
'type' => PermissionType::READ,

View File

@ -14,14 +14,23 @@ declare(strict_types=1);
namespace Modules\LoanManagement\Controller;
use Modules\LoanManagement\Models\CostType;
use Modules\LoanManagement\Models\CostTypeL11nMapper;
use Modules\LoanManagement\Models\CostTypeMapper;
use Modules\LoanManagement\Models\Loan;
use Modules\LoanManagement\Models\LoanElement;
use phpOMS\Business\Finance\Loan as FinanceLoan;
use Modules\LoanManagement\Models\LoanMapper;
use Modules\LoanManagement\Models\LoanStatus;
use Modules\LoanManagement\Models\NullCostType;
use Modules\SupplierManagement\Models\NullSupplier;
use phpOMS\Localization\BaseStringL11n;
use phpOMS\Localization\BaseStringL11nType;
use phpOMS\Localization\ISO639x1Enum;
use phpOMS\Message\Http\RequestStatusCode;
use phpOMS\Message\RequestAbstract;
use phpOMS\Message\ResponseAbstract;
use phpOMS\Stdlib\Base\FloatInt;
use phpOMS\Stdlib\Base\SmartDateTime;
/**
* LoanManagement class.
@ -34,7 +43,7 @@ use phpOMS\Message\ResponseAbstract;
final class ApiController extends Controller
{
/**
* Api method to create tag
* Api method to create loan
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response
@ -48,10 +57,135 @@ final class ApiController extends Controller
*/
public function apiLoanCreate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void
{
if (!empty($val = $this->validateLoanCreate($request))) {
$response->header->status = RequestStatusCode::R_400;
$this->createInvalidCreateResponse($request, $response, $val);
return;
}
$costType = $this->createLoanFromRequest($request);
$this->createModel($request->header->account, $costType, LoanMapper::class, 'loan', $request->getOrigin());
$this->createStandardCreateResponse($request, $response, $costType);
}
/**
* Api method to create tag
* Validate cost type create request
*
* @param RequestAbstract $request Request
*
* @return array<string, bool>
*
* @since 1.0.0
*/
private function validateLoanCreate(RequestAbstract $request) : array
{
$val = [];
if (($val['name'] = !$request->hasData('name'))
|| ($val['supplier'] = !$request->hasData('supplier'))
|| ($val['start'] = !$request->hasData('start'))
|| ($val['duration'] = !$request->hasData('duration'))
|| ($val['amount'] = !$request->hasData('amount'))
|| ($val['interest_rate'] = !$request->hasData('interest_rate'))
) {
return $val;
}
return [];
}
/**
* Method to create cost type from request.
*
* @param RequestAbstract $request Request
*
* @return Loan
*
* @since 1.0.0
*/
private function createLoanFromRequest(RequestAbstract $request) : Loan
{
$loan = new Loan();
$loan->createdBy = $request->header->account;
$loan->name = $request->getDataString('name');
$loan->description = $request->getDataString('description');
$loan->loanProvider = new NullSupplier((int) $request->getDataInt('supplier'));
$loan->status = LoanStatus::tryFromValue($request->getData('status')) ?? LoanStatus::ACTIVE;
$loan->nominalBorrowingRate = new FloatInt($request->getDataString('interest_rate') ?? 0);
$loan->interestRateAfterDuration = new FloatInt($request->getDataString('post_interest_rate') ?? 0);
$loan->start = $request->getDataDateTime('start') ?? new \DateTime('now');
$loan->end = SmartDateTime::createFromDateTime($loan->start)->smartModify(0, (int) $request->getDataInt('duration'));
$loan->isSpecialPaymentAllowed = $request->getDataBool('special_payment_allowed') ?? false;
$loan->unit = $request->getDataInt('unit') ?? $this->app->unitId;
$paymentInterval = $request->getDataInt('payment_interval') ?? 12;
/** @var CostType[] $types */
$types = CostTypeMapper::getAll()->executeGetArray();
$loanType = new NullCostType();
$repaymentType = new NullCostType();
$interestType = new NullCostType();
foreach ($types as $type) {
if ($type->name === 'loan') {
$loanType = $type;
} elseif ($type->name === 'repayment') {
$repaymentType = $type;
} elseif ($type->name === 'interest') {
$interestType = $type;
}
}
// Loan
$element = new LoanElement();
$element->amount = new FloatInt($request->getDataString('amount') ?? 0);
$element->date = $loan->start;
$element->type = $loanType;
$loan->elements[] = $element;
$currentDate = SmartDateTime::createFromDateTime($loan->start);
$currentDate->smartModify(0, (int) (12 / $paymentInterval), -1);
// @feature Handle different loan types
$schedule = FinanceLoan::getAmortizationSchedule(
$element->amount->getNormalizedValue(),
$loan->nominalBorrowingRate->getNormalizedValue() / 100,
(int) $request->getDataInt('duration'),
$paymentInterval
);
foreach ($schedule as $idx => $e) {
if ($idx === 0) {
continue;
}
// Repayment
$element = new LoanElement();
$element->amount = new FloatInt($e['principal']);
$element->date = clone $currentDate;
$element->type = $repaymentType;
$loan->elements[] = $element;
// Interest
$element = new LoanElement();
$element->amount = new FloatInt($e['interest']);
$element->date = clone $currentDate;
$element->type = $interestType;
$loan->elements[] = $element;
$currentDate->smartModify(0, (int) (12 / $paymentInterval));
}
return $loan;
}
/**
* Api method to calculate loan timeline based on definitions
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response
@ -68,7 +202,7 @@ final class ApiController extends Controller
}
/**
* Api method to create tag
* Api method to create loan elements
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response
@ -85,7 +219,7 @@ final class ApiController extends Controller
}
/**
* Api method to create item cost type
* Api method to create loan cost type
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response
@ -112,7 +246,7 @@ final class ApiController extends Controller
}
/**
* Validate cost create request
* Validate cost type create request
*
* @param RequestAbstract $request Request
*
@ -133,17 +267,20 @@ final class ApiController extends Controller
}
/**
* Method to create cost from request.
* Method to create cost type from request.
*
* @param RequestAbstract $request Request
*
* @return BaseStringL11nType
* @return CostType
*
* @since 1.0.0
*/
private function createCostTypeFromRequest(RequestAbstract $request) : BaseStringL11nType
private function createCostTypeFromRequest(RequestAbstract $request) : CostType
{
$costType = new BaseStringL11nType($request->getDataString('name') ?? '');
$costType = new CostType();
$costType->name = $request->getDataString('name');
$costType->sign = $request->getDataInt('sign') ?? -1;
$costType->isLoan = $request->getDataBool('is_loan') ?? false;
$costType->setL11n(
$request->getDataString('title') ?? '',
ISO639x1Enum::tryFromValue($request->getDataString('language')) ?? ISO639x1Enum::_EN
@ -153,7 +290,7 @@ final class ApiController extends Controller
}
/**
* Api method to create item cost l11n
* Api method to create loan cost l11n
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response

103
Models/CostType.php Executable file
View File

@ -0,0 +1,103 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package Modules\LoanManagement\Models
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace Modules\LoanManagement\Models;
use phpOMS\Localization\BaseStringL11n;
use phpOMS\Localization\ISO639x1Enum;
/**
* CostType class.
*
* @package Modules\LoanManagement\Models
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class CostType implements \JsonSerializable
{
/**
* Article ID.
*
* @var int
* @since 1.0.0
*/
public int $id = 0;
public string $name = '';
/**
* Title.
*
* @var string|BaseStringL11n
* @since 1.0.0
*/
public string | BaseStringL11n $l11n = '';
public int $sign = -1;
public bool $isLoan = false;
/**
* @return string
*
* @since 1.0.0
*/
public function getL11n() : string
{
return $this->l11n instanceof BaseStringL11n ? $this->l11n->content : $this->l11n;
}
/**
* Set l11n
*
* @param string|BaseStringL11n $l11n Tag article l11n
* @param string $lang Language
*
* @return void
*
* @since 1.0.0
*/
public function setL11n(string | BaseStringL11n $l11n, string $lang = ISO639x1Enum::_EN) : void
{
if ($l11n instanceof BaseStringL11n) {
$this->l11n = $l11n;
} elseif (isset($this->l11n) && $this->l11n instanceof BaseStringL11n) {
$this->l11n->content = $l11n;
} else {
$this->l11n = new BaseStringL11n();
$this->l11n->content = $l11n;
$this->l11n->language = $lang;
}
}
/**
* {@inheritdoc}
*/
public function toArray() : array
{
return [
'id' => $this->id,
'l11n' => $this->l11n,
];
}
/**
* {@inheritdoc}
*/
public function jsonSerialize() : mixed
{
return $this->toArray();
}
}

View File

@ -18,7 +18,7 @@ use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
use phpOMS\Localization\BaseStringL11n;
/**
* Item mapper class.
* CostTypeL11n mapper class.
*
* @package Modules\LoanManagement\Models
* @license OMS License 2.0

View File

@ -15,17 +15,16 @@ declare(strict_types=1);
namespace Modules\LoanManagement\Models;
use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
use phpOMS\Localization\BaseStringL11nType;
/**
* Item mapper class.
* CostType mapper class.
*
* @package Modules\LoanManagement\Models
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*
* @template T of BaseStringL11nType
* @template T of CostType
* @extends DataMapperFactory<T>
*/
final class CostTypeMapper extends DataMapperFactory
@ -38,7 +37,9 @@ final class CostTypeMapper extends DataMapperFactory
*/
public const COLUMNS = [
'loanmgmt_cost_type_id' => ['name' => 'loanmgmt_cost_type_id', 'type' => 'int', 'internal' => 'id'],
'loanmgmt_cost_type_name' => ['name' => 'loanmgmt_cost_type_name', 'type' => 'string', 'internal' => 'title', 'autocomplete' => true],
'loanmgmt_cost_type_name' => ['name' => 'loanmgmt_cost_type_name', 'type' => 'string', 'internal' => 'name', 'autocomplete' => true],
'loanmgmt_cost_type_sign' => ['name' => 'loanmgmt_cost_type_sign', 'type' => 'int', 'internal' => 'sign'],
'loanmgmt_cost_type_loan' => ['name' => 'loanmgmt_cost_type_loan', 'type' => 'bool', 'internal' => 'isLoan'],
];
/**
@ -63,7 +64,7 @@ final class CostTypeMapper extends DataMapperFactory
* @var class-string<T>
* @since 1.0.0
*/
public const MODEL = BaseStringL11nType::class;
public const MODEL = CostType::class;
/**
* Primary table.

View File

@ -16,6 +16,7 @@ namespace Modules\LoanManagement\Models;
use Modules\SupplierManagement\Models\NullSupplier;
use Modules\SupplierManagement\Models\Supplier;
use phpOMS\Stdlib\Base\FloatInt;
/**
* Loan model.
@ -37,40 +38,10 @@ class Loan
public int $status = LoanStatus::DRAFT;
public int $amount = 0;
public FloatInt $nominalBorrowingRate;
public int $acquisitionFee = 0;
public int $disagio = 0;
public int $nominalBorrowingRate = 0;
public int $startingRepaymentRate = 0;
public int $startingRepayment = 0;
// 0 = end of month
public int $dayOfRepayment = 0;
// monthly, quarterly, annually, end of duration
public int $interestInterval = 0;
public int $interestTaxRate = 0;
// monthly, quarterly, annually, end of duration
public int $repaymentInterval = 0;
// months
public int $duration = 0;
public int $repaymentFreeTime = 0;
// Either separate (during the repayment free time) or during the repayment time
public int $repaymentFreeInterest = 1;
public int $residualAmountAfterDuration = 0;
public int $annualSpecialPayment = 0;
// 0 = not possible
public FloatInt $interestRateAfterDuration;
public bool $isSpecialPaymentAllowed = false;
@ -78,24 +49,13 @@ class Loan
public \DateTime $end;
public \DateTime $payout;
public \DateTimeImmutable $createdAt;
// 0 = not possible
public int $interestRateAfterDuration = 0;
public int $createdBy = 0;
// used to indicate if the interests/payments/taxes are manually adjusted
public bool $hasManualInterestAmounts = false;
public int $unit = 0;
public array $interests = [];
// in and out
public array $payments = [];
public bool $hasManualPaymentAmounts = false;
public array $taxes = [];
public bool $hasManualTaxAmounts = false;
public array $elements = [];
/**
* Constructor.
@ -104,9 +64,13 @@ class Loan
*/
public function __construct()
{
$this->createdAt = new \DateTimeImmutable();
$this->loanProvider = new NullSupplier();
$this->start = new \DateTime();
$this->end = $this->start->modify('+1 year');
$this->payout = $this->start;
$this->nominalBorrowingRate = new FloatInt();
$this->interestRateAfterDuration = new FloatInt();
}
}

47
Models/LoanElement.php Normal file
View File

@ -0,0 +1,47 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package Modules\LoanManagement\Models
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace Modules\LoanManagement\Models;
use phpOMS\Stdlib\Base\FloatInt;
/**
* Loan model.
*
* @package Modules\LoanManagement\Models
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class LoanElement
{
public int $id = 0;
public string $description = '';
public FloatInt $amount;
public \DateTime $date;
public int $loan = 0;
public CostType $type;
public function __construct()
{
$this->amount = new FloatInt();
$this->date = new \DateTime();
$this->type = new NullCostType();
}
}

View File

@ -0,0 +1,84 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package Modules\LoanManagement\Models
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace Modules\LoanManagement\Models;
use Modules\SupplierManagement\Models\SupplierMapper;
use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
/**
* LoanElement mapper class.
*
* @package Modules\LoanManagement\Models
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*
* @template T of LoanElement
* @extends DataMapperFactory<T>
*/
final class LoanElementMapper extends DataMapperFactory
{
/**
* Columns.
*
* @var array<string, array{name:string, type:string, internal:string, autocomplete?:bool, readonly?:bool, writeonly?:bool, annotations?:array}>
* @since 1.0.0
*/
public const COLUMNS = [
'loanmgmt_loan_element_id' => ['name' => 'loanmgmt_loan_element_id', 'type' => 'int', 'internal' => 'id'],
'loanmgmt_loan_element_description' => ['name' => 'loanmgmt_loan_element_description', 'type' => 'string', 'internal' => 'description'],
'loanmgmt_loan_element_date' => ['name' => 'loanmgmt_loan_element_date', 'type' => 'DateTime', 'internal' => 'date'],
'loanmgmt_loan_element_type' => ['name' => 'loanmgmt_loan_element_type', 'type' => 'int', 'internal' => 'type'],
'loanmgmt_loan_element_loan' => ['name' => 'loanmgmt_loan_element_loan', 'type' => 'int', 'internal' => 'loan'],
'loanmgmt_loan_element_amount' => ['name' => 'loanmgmt_loan_element_amount', 'type' => 'Serializable', 'internal' => 'amount'],
];
/**
* Has one relation.
*
* @var array<string, array{mapper:class-string, external:string, by?:string, column?:string, conditional?:bool}>
* @since 1.0.0
*/
public const OWNS_ONE = [
'type' => [
'mapper' => CostTypeMapper::class,
'external' => 'loanmgmt_loan_element_type',
],
];
/**
* Model to use by the mapper.
*
* @var class-string<T>
* @since 1.0.0
*/
public const MODEL = LoanElement::class;
/**
* Primary table.
*
* @var string
* @since 1.0.0
*/
public const TABLE = 'loanmgmt_loan';
/**
* Primary field name.
*
* @var string
* @since 1.0.0
*/
public const PRIMARYFIELD = 'loanmgmt_loan_element_id';
}

106
Models/LoanMapper.php Normal file
View File

@ -0,0 +1,106 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package Modules\LoanManagement\Models
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace Modules\LoanManagement\Models;
use Modules\SupplierManagement\Models\SupplierMapper;
use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
/**
* Loan mapper class.
*
* @package Modules\LoanManagement\Models
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*
* @template T of Loan
* @extends DataMapperFactory<T>
*/
final class LoanMapper extends DataMapperFactory
{
/**
* Columns.
*
* @var array<string, array{name:string, type:string, internal:string, autocomplete?:bool, readonly?:bool, writeonly?:bool, annotations?:array}>
* @since 1.0.0
*/
public const COLUMNS = [
'loanmgmt_loan_id' => ['name' => 'loanmgmt_loan_id', 'type' => 'int', 'internal' => 'id'],
'loanmgmt_loan_name' => ['name' => 'loanmgmt_loan_name', 'type' => 'string', 'internal' => 'name', 'autocomplete' => true],
'loanmgmt_loan_description' => ['name' => 'loanmgmt_loan_description', 'type' => 'string', 'internal' => 'description'],
'loanmgmt_loan_start' => ['name' => 'loanmgmt_loan_start', 'type' => 'DateTime', 'internal' => 'start'],
'loanmgmt_loan_end' => ['name' => 'loanmgmt_loan_end', 'type' => 'DateTime', 'internal' => 'end'],
'loanmgmt_loan_created_at' => ['name' => 'loanmgmt_loan_created_at', 'type' => 'DateTimeImmutable', 'internal' => 'createdAt'],
'loanmgmt_loan_created_by' => ['name' => 'loanmgmt_loan_created_by', 'type' => 'int', 'internal' => 'createdBy'],
'loanmgmt_loan_unit' => ['name' => 'loanmgmt_loan_unit', 'type' => 'int', 'internal' => 'unit'],
'loanmgmt_loan_supplier' => ['name' => 'loanmgmt_loan_supplier', 'type' => 'int', 'internal' => 'supplier'],
'loanmgmt_loan_status' => ['name' => 'loanmgmt_loan_status', 'type' => 'int', 'internal' => 'status'],
'loanmgmt_loan_borrowing_rate' => ['name' => 'loanmgmt_loan_borrowing_rate', 'type' => 'Serializable', 'internal' => 'nominalBorrowingRate'],
'loanmgmt_loan_post_rate' => ['name' => 'loanmgmt_loan_post_rate', 'type' => 'Serializable', 'internal' => 'interestRateAfterDuration'],
'loanmgmt_loan_special_payment' => ['name' => 'loanmgmt_loan_special_payment', 'type' => 'bool', 'internal' => 'isSpecialPaymentAllowed'],
];
/**
* Has one relation.
*
* @var array<string, array{mapper:class-string, external:string, by?:string, column?:string, conditional?:bool}>
* @since 1.0.0
*/
public const OWNS_ONE = [
'supplier' => [
'mapper' => SupplierMapper::class,
'external' => 'loanmgmt_loan_supplier',
],
];
/**
* Has many relation.
*
* @var array<string, array{mapper:class-string, table:string, self?:?string, external?:?string, column?:string}>
* @since 1.0.0
*/
public const HAS_MANY = [
'elements' => [
'mapper' => LoanElementMapper::class,
'table' => 'loanmgmt_loan_element',
'self' => 'loanmgmt_loan_element_loan',
'external' => null,
],
];
/**
* Model to use by the mapper.
*
* @var class-string<T>
* @since 1.0.0
*/
public const MODEL = Loan::class;
/**
* Primary table.
*
* @var string
* @since 1.0.0
*/
public const TABLE = 'loanmgmt_loan';
/**
* Primary field name.
*
* @var string
* @since 1.0.0
*/
public const PRIMARYFIELD = 'loanmgmt_loan_id';
}

View File

@ -17,7 +17,7 @@ namespace Modules\LoanManagement\Models;
use phpOMS\Stdlib\Base\Enum;
/**
* Loanment status enum.
* Loan status enum.
*
* @package Modules\LoanManagement\Models
* @license OMS License 2.0

34
Models/LoanType.php Normal file
View File

@ -0,0 +1,34 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package Modules\LoanManagement\Models
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace Modules\LoanManagement\Models;
use phpOMS\Stdlib\Base\Enum;
/**
* Loan type enum.
*
* @package Modules\LoanManagement\Models
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
abstract class LoanType extends Enum
{
public const AMORTIZED_LOAN = 1;
public const DEFERRED_PAYMENT_LOAN = 2;
public const BOND_LOAN = 3;
}

46
Models/NullCostType.php Normal file
View File

@ -0,0 +1,46 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package Modules\LoanManagement\Models
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace Modules\LoanManagement\Models;
/**
* Null model
*
* @package Modules\LoanManagement\Models
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class NullCostType extends CostType
{
/**
* Constructor
*
* @param int $id Model id
*
* @since 1.0.0
*/
public function __construct(int $id = 0)
{
$this->id = $id;
}
/**
* {@inheritdoc}
*/
public function jsonSerialize() : mixed
{
return ['id' => $this->id];
}
}

47
Models/NullLoan.php Normal file
View File

@ -0,0 +1,47 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package Modules\LoanManagement\Models
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace Modules\LoanManagement\Models;
/**
* Null model
*
* @package Modules\LoanManagement\Models
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class NullLoan extends Loan
{
/**
* Constructor
*
* @param int $id Model id
*
* @since 1.0.0
*/
public function __construct(int $id = 0)
{
$this->id = $id;
parent::__construct();
}
/**
* {@inheritdoc}
*/
public function jsonSerialize() : mixed
{
return ['id' => $this->id];
}
}

View File

@ -0,0 +1,47 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package Modules\LoanManagement\Models
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace Modules\LoanManagement\Models;
/**
* Null model
*
* @package Modules\LoanManagement\Models
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class NullLoanElement extends LoanElement
{
/**
* Constructor
*
* @param int $id Model id
*
* @since 1.0.0
*/
public function __construct(int $id = 0)
{
$this->id = $id;
parent::__construct();
}
/**
* {@inheritdoc}
*/
public function jsonSerialize() : mixed
{
return ['id' => $this->id];
}
}

View File

@ -22,8 +22,7 @@
},
"providing": {
"Admin": "*",
"Navigation": "*",
"Organization": "*"
"Navigation": "*"
},
"load": [
{