diff --git a/Admin/Install/db.json b/Admin/Install/db.json index a4a8174..26bef02 100755 --- a/Admin/Install/db.json +++ b/Admin/Install/db.json @@ -80,11 +80,6 @@ "foreignTable": "investmgmt_investment_type", "foreignKey": "investmgmt_investment_type_id" }, - "investmgmt_investment_depreciation_type": { - "name": "investmgmt_investment_depreciation_type", - "type": "TINYINT", - "null": false - }, "investmgmt_investment_created_by": { "name": "investmgmt_investment_created_by", "type": "INT", @@ -232,6 +227,235 @@ } } }, + "investmgmt_attr_type": { + "name": "investmgmt_attr_type", + "fields": { + "investmgmt_attr_type_id": { + "name": "investmgmt_attr_type_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "investmgmt_attr_type_name": { + "name": "investmgmt_attr_type_name", + "type": "VARCHAR(255)", + "null": false, + "unique": true + }, + "investmgmt_attr_type_datatype": { + "name": "investmgmt_attr_type_datatype", + "type": "INT(11)", + "null": false + }, + "investmgmt_attr_type_fields": { + "name": "investmgmt_attr_type_fields", + "type": "INT(11)", + "null": false + }, + "investmgmt_attr_type_custom": { + "name": "investmgmt_attr_type_custom", + "type": "TINYINT(1)", + "null": false + }, + "investmgmt_attr_type_required": { + "description": "Every item must have this attribute type if set to true.", + "name": "investmgmt_attr_type_required", + "type": "TINYINT(1)", + "null": false + }, + "investmgmt_attr_type_pattern": { + "description": "This is a regex validation pattern.", + "name": "investmgmt_attr_type_pattern", + "type": "VARCHAR(255)", + "null": false + } + } + }, + "investmgmt_attr_type_l11n": { + "name": "investmgmt_attr_type_l11n", + "fields": { + "investmgmt_attr_type_l11n_id": { + "name": "investmgmt_attr_type_l11n_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "investmgmt_attr_type_l11n_title": { + "name": "investmgmt_attr_type_l11n_title", + "type": "VARCHAR(255)", + "null": false + }, + "investmgmt_attr_type_l11n_type": { + "name": "investmgmt_attr_type_l11n_type", + "type": "INT(11)", + "null": false, + "foreignTable": "investmgmt_attr_type", + "foreignKey": "investmgmt_attr_type_id" + }, + "investmgmt_attr_type_l11n_lang": { + "name": "investmgmt_attr_type_l11n_lang", + "type": "VARCHAR(2)", + "null": false, + "foreignTable": "language", + "foreignKey": "language_639_1" + } + } + }, + "investmgmt_attr_value": { + "name": "investmgmt_attr_value", + "fields": { + "investmgmt_attr_value_id": { + "name": "investmgmt_attr_value_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "investmgmt_attr_value_default": { + "name": "investmgmt_attr_value_default", + "type": "TINYINT(1)", + "null": false + }, + "investmgmt_attr_value_valueStr": { + "name": "investmgmt_attr_value_valueStr", + "type": "VARCHAR(255)", + "null": true, + "default": null + }, + "investmgmt_attr_value_valueInt": { + "name": "investmgmt_attr_value_valueInt", + "type": "INT(11)", + "null": true, + "default": null + }, + "investmgmt_attr_value_valueDec": { + "name": "investmgmt_attr_value_valueDec", + "type": "DECIMAL(19,5)", + "null": true, + "default": null + }, + "investmgmt_attr_value_valueDat": { + "name": "investmgmt_attr_value_valueDat", + "type": "DATETIME", + "null": true, + "default": null + }, + "investmgmt_attr_value_unit": { + "name": "investmgmt_attr_value_unit", + "type": "VARCHAR(255)", + "null": false + }, + "investmgmt_attr_value_deptype": { + "name": "investmgmt_attr_value_deptype", + "type": "INT(11)", + "null": true, + "default": null, + "foreignTable": "investmgmt_attr_type", + "foreignKey": "investmgmt_attr_type_id" + }, + "investmgmt_attr_value_depvalue": { + "name": "investmgmt_attr_value_depvalue", + "type": "INT(11)", + "null": true, + "default": null, + "foreignTable": "investmgmt_attr_value", + "foreignKey": "investmgmt_attr_value_id" + } + } + }, + "investmgmt_attr_value_l11n": { + "name": "investmgmt_attr_value_l11n", + "fields": { + "investmgmt_attr_value_l11n_id": { + "name": "investmgmt_attr_value_l11n_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "investmgmt_attr_value_l11n_title": { + "name": "investmgmt_attr_value_l11n_title", + "type": "VARCHAR(255)", + "null": false + }, + "investmgmt_attr_value_l11n_value": { + "name": "investmgmt_attr_value_l11n_value", + "type": "INT(11)", + "null": false, + "foreignTable": "investmgmt_attr_value", + "foreignKey": "investmgmt_attr_value_id" + }, + "investmgmt_attr_value_l11n_lang": { + "name": "investmgmt_attr_value_l11n_lang", + "type": "VARCHAR(2)", + "null": false, + "foreignTable": "language", + "foreignKey": "language_639_1" + } + } + }, + "investmgmt_option_attr_default": { + "name": "investmgmt_option_attr_default", + "fields": { + "investmgmt_option_attr_default_id": { + "name": "investmgmt_option_attr_default_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "investmgmt_option_attr_default_type": { + "name": "investmgmt_option_attr_default_type", + "type": "INT(11)", + "null": false, + "foreignTable": "investmgmt_attr_type", + "foreignKey": "investmgmt_attr_type_id" + }, + "investmgmt_option_attr_default_value": { + "name": "investmgmt_option_attr_default_value", + "type": "INT(11)", + "null": false, + "foreignTable": "investmgmt_attr_value", + "foreignKey": "investmgmt_attr_value_id" + } + } + }, + "investmgmt_option_attr": { + "name": "investmgmt_option_attr", + "fields": { + "investmgmt_option_attr_id": { + "name": "investmgmt_option_attr_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "investmgmt_option_attr_option": { + "name": "investmgmt_option_attr_option", + "type": "INT(11)", + "null": false, + "foreignTable": "investmgmt_option", + "foreignKey": "investmgmt_option_id" + }, + "investmgmt_option_attr_type": { + "name": "investmgmt_option_attr_type", + "type": "INT(11)", + "null": false, + "foreignTable": "investmgmt_attr_type", + "foreignKey": "investmgmt_attr_type_id" + }, + "investmgmt_option_attr_value": { + "name": "investmgmt_option_attr_value", + "type": "INT(11)", + "null": true, + "default": null, + "foreignTable": "investmgmt_attr_value", + "foreignKey": "investmgmt_attr_value_id" + } + } + }, "investmgmt_option_media": { "name": "investmgmt_option_media", "fields": { diff --git a/Admin/Routes/Web/Api.php b/Admin/Routes/Web/Api.php new file mode 100644 index 0000000..44fef03 --- /dev/null +++ b/Admin/Routes/Web/Api.php @@ -0,0 +1,132 @@ + [ + [ + 'dest' => '\Modules\InvestmentManagement\Controller\ApiController:apiInvestmentFind', + 'verb' => RouteVerb::GET, + 'permission' => [ + 'module' => ApiController::NAME, + 'type' => PermissionType::READ, + 'state' => PermissionCategory::INVESTMENT, + ], + ], + ], + '^.*/finance/investment/attribute$' => [ + [ + 'dest' => '\Modules\InvestmentManagement\Controller\ApiAttributeController:apiInvestmentAttributeCreate', + 'verb' => RouteVerb::PUT, + 'permission' => [ + 'module' => ApiController::NAME, + 'type' => PermissionType::READ, + 'state' => PermissionCategory::INVESTMENT, + ], + ], + [ + 'dest' => '\Modules\InvestmentManagement\Controller\ApiAttributeController:apiInvestmentAttributeUpdate', + 'verb' => RouteVerb::SET, + 'permission' => [ + 'module' => ApiController::NAME, + 'type' => PermissionType::READ, + 'state' => PermissionCategory::INVESTMENT, + ], + ], + ], + '^.*/finance/investment/attribute/type$' => [ + [ + 'dest' => '\Modules\InvestmentManagement\Controller\ApiAttributeController:apiInvestmentAttributeTypeCreate', + 'verb' => RouteVerb::PUT, + 'permission' => [ + 'module' => ApiController::NAME, + 'type' => PermissionType::READ, + 'state' => PermissionCategory::INVESTMENT, + ], + ], + [ + 'dest' => '\Modules\InvestmentManagement\Controller\ApiAttributeController:apiInvestmentAttributeTypeUpdate', + 'verb' => RouteVerb::SET, + 'permission' => [ + 'module' => ApiController::NAME, + 'type' => PermissionType::READ, + 'state' => PermissionCategory::INVESTMENT, + ], + ], + ], + '^.*/finance/investment/attribute/type/l11n$' => [ + [ + 'dest' => '\Modules\InvestmentManagement\Controller\ApiAttributeController:apiInvestmentAttributeTypeL11nCreate', + 'verb' => RouteVerb::PUT, + 'permission' => [ + 'module' => ApiController::NAME, + 'type' => PermissionType::READ, + 'state' => PermissionCategory::INVESTMENT, + ], + ], + [ + 'dest' => '\Modules\InvestmentManagement\Controller\ApiAttributeController:apiInvestmentAttributeTypeL11nUpdate', + 'verb' => RouteVerb::SET, + 'permission' => [ + 'module' => ApiController::NAME, + 'type' => PermissionType::READ, + 'state' => PermissionCategory::INVESTMENT, + ], + ], + ], + '^.*/finance/investment/attribute/value$' => [ + [ + 'dest' => '\Modules\InvestmentManagement\Controller\ApiAttributeController:apiInvestmentAttributeValueCreate', + 'verb' => RouteVerb::PUT, + 'permission' => [ + 'module' => ApiController::NAME, + 'type' => PermissionType::READ, + 'state' => PermissionCategory::INVESTMENT, + ], + ], + [ + 'dest' => '\Modules\InvestmentManagement\Controller\ApiAttributeController:apiInvestmentAttributeValueUpdate', + 'verb' => RouteVerb::SET, + 'permission' => [ + 'module' => ApiController::NAME, + 'type' => PermissionType::READ, + 'state' => PermissionCategory::INVESTMENT, + ], + ], + ], + '^.*/finance/investment/attribute/value$' => [ + [ + 'dest' => '\Modules\InvestmentManagement\Controller\ApiAttributeController:apiInvestmentAttributeValueL11nCreate', + 'verb' => RouteVerb::PUT, + 'permission' => [ + 'module' => ApiController::NAME, + 'type' => PermissionType::READ, + 'state' => PermissionCategory::INVESTMENT, + ], + ], + [ + 'dest' => '\Modules\InvestmentManagement\Controller\ApiAttributeController:apiInvestmentAttributeValueL11nUpdate', + 'verb' => RouteVerb::SET, + 'permission' => [ + 'module' => ApiController::NAME, + 'type' => PermissionType::READ, + 'state' => PermissionCategory::INVESTMENT, + ], + ], + ], +]; diff --git a/Admin/Routes/Web/Backend.php b/Admin/Routes/Web/Backend.php index af696f0..5a5797d 100755 --- a/Admin/Routes/Web/Backend.php +++ b/Admin/Routes/Web/Backend.php @@ -17,9 +17,9 @@ return [ ], ], ], - '^.*/finance/investment/single.*$' => [ + '^.*/finance/investment/profile.*$' => [ [ - 'dest' => '\Modules\InvestmentManagement\Controller\BackendController:viewInvestmentSingle', + 'dest' => '\Modules\InvestmentManagement\Controller\BackendController:viewInvestmentProfile', 'verb' => RouteVerb::GET, 'permission' => [ 'module' => BackendController::MODULE_NAME, @@ -39,6 +39,17 @@ return [ ], ], ], + '^.*/finance/investment/object.*$' => [ + [ + 'dest' => '\Modules\InvestmentManagement\Controller\BackendController:viewInvestmentObjectProfile', + 'verb' => RouteVerb::GET, + 'permission' => [ + 'module' => BackendController::MODULE_NAME, + 'type' => PermissionType::READ, + 'state' => PermissionCategory::INVESTMENT, + ], + ], + ], '^.*/private/investment/list.*$' => [ [ @@ -51,9 +62,9 @@ return [ ], ], ], - '^.*/private/investment/single.*$' => [ + '^.*/private/investment/profile.*$' => [ [ - 'dest' => '\Modules\InvestmentManagement\Controller\BackendController:viewInvestmentSingle', + 'dest' => '\Modules\InvestmentManagement\Controller\BackendController:viewInvestmentProfile', 'verb' => RouteVerb::GET, 'permission' => [ 'module' => BackendController::MODULE_NAME, diff --git a/Controller/ApiAttributeController.php b/Controller/ApiAttributeController.php new file mode 100644 index 0000000..e25d875 --- /dev/null +++ b/Controller/ApiAttributeController.php @@ -0,0 +1,524 @@ +validateAttributeCreate($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidCreateResponse($request, $response, $val); + + return; + } + + $type = InvestmentObjectAttributeTypeMapper::get()->with('defaults')->where('id', (int) $request->getData('type'))->execute(); + $attribute = $this->createAttributeFromRequest($request, $type); + $this->createModel($request->header->account, $attribute, InvestmentObjectAttributeMapper::class, 'attribute', $request->getOrigin()); + $this->createStandardCreateResponse($request, $response, $attribute); + } + + /** + * Api method to create option attribute l11n + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiInvestmentObjectAttributeTypeL11nCreate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAttributeTypeL11nCreate($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidCreateResponse($request, $response, $val); + + return; + } + + $attrL11n = $this->createAttributeTypeL11nFromRequest($request); + $this->createModel($request->header->account, $attrL11n, InvestmentObjectAttributeTypeL11nMapper::class, 'attr_type_l11n', $request->getOrigin()); + $this->createStandardCreateResponse($request, $response, $attrL11n); + } + + /** + * Api method to create option attribute type + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiInvestmentObjectAttributeTypeCreate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAttributeTypeCreate($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidCreateResponse($request, $response, $val); + + return; + } + + $attrType = $this->createAttributeTypeFromRequest($request); + $this->createModel($request->header->account, $attrType, InvestmentObjectAttributeTypeMapper::class, 'attr_type', $request->getOrigin()); + $this->createStandardCreateResponse($request, $response, $attrType); + } + + /** + * Api method to create option attribute value + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiInvestmentObjectAttributeValueCreate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAttributeValueCreate($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidCreateResponse($request, $response, $val); + + return; + } + + /** @var \Modules\Attribute\Models\AttributeType $type */ + $type = InvestmentObjectAttributeTypeMapper::get() + ->where('id', $request->getDataInt('type') ?? 0) + ->execute(); + + $attrValue = $this->createAttributeValueFromRequest($request, $type); + $this->createModel($request->header->account, $attrValue, InvestmentObjectAttributeValueMapper::class, 'attr_value', $request->getOrigin()); + + if ($attrValue->isDefault) { + $this->createModelRelation( + $request->header->account, + (int) $request->getData('type'), + $attrValue->id, + InvestmentObjectAttributeTypeMapper::class, 'defaults', '', $request->getOrigin() + ); + } + + $this->createStandardCreateResponse($request, $response, $attrValue); + } + + /** + * Api method to create option attribute l11n + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiInvestmentObjectAttributeValueL11nCreate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAttributeValueL11nCreate($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidCreateResponse($request, $response, $val); + + return; + } + + $attrL11n = $this->createAttributeValueL11nFromRequest($request); + $this->createModel($request->header->account, $attrL11n, InvestmentObjectAttributeValueL11nMapper::class, 'attr_value_l11n', $request->getOrigin()); + $this->createStandardCreateResponse($request, $response, $attrL11n); + } + + /** + * Api method to update InvestmentObjectAttribute + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiInvestmentObjectAttributeUpdate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAttributeUpdate($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidUpdateResponse($request, $response, $val); + + return; + } + + /** @var Attribute $old */ + $old = InvestmentObjectAttributeMapper::get() + ->with('type') + ->with('type/defaults') + ->with('value') + ->where('id', (int) $request->getData('id')) + ->execute(); + + $new = $this->updateAttributeFromRequest($request, clone $old); + + if ($new->id === 0) { + // Set response header to invalid request because of invalid data + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidUpdateResponse($request, $response, $new); + + return; + } + + $this->updateModel($request->header->account, $old, $new, InvestmentObjectAttributeMapper::class, 'option_attribute', $request->getOrigin()); + + if ($new->value->getValue() !== $old->value->getValue() + && $new->type->custom + ) { + $this->updateModel($request->header->account, $old->value, $new->value, InvestmentObjectAttributeValueMapper::class, 'attribute_value', $request->getOrigin()); + } + + $this->createStandardUpdateResponse($request, $response, $new); + } + + /** + * Api method to delete InvestmentObjectAttribute + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiInvestmentObjectAttributeDelete(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAttributeDelete($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidDeleteResponse($request, $response, $val); + + return; + } + + $optionAttribute = InvestmentObjectAttributeMapper::get() + ->with('type') + ->where('id', (int) $request->getData('id')) + ->execute(); + + if ($optionAttribute->type->isRequired) { + $this->createInvalidDeleteResponse($request, $response, []); + + return; + } + + $this->deleteModel($request->header->account, $optionAttribute, InvestmentObjectAttributeMapper::class, 'option_attribute', $request->getOrigin()); + $this->createStandardDeleteResponse($request, $response, $optionAttribute); + } + + /** + * Api method to update InvestmentObjectAttributeTypeL11n + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiInvestmentObjectAttributeTypeL11nUpdate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAttributeTypeL11nUpdate($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidUpdateResponse($request, $response, $val); + + return; + } + + /** @var BaseStringL11n $old */ + $old = InvestmentObjectAttributeTypeL11nMapper::get()->where('id', (int) $request->getData('id'))->execute(); + $new = $this->updateAttributeTypeL11nFromRequest($request, clone $old); + + $this->updateModel($request->header->account, $old, $new, InvestmentObjectAttributeTypeL11nMapper::class, 'option_attribute_type_l11n', $request->getOrigin()); + $this->createStandardUpdateResponse($request, $response, $new); + } + + /** + * Api method to delete InvestmentObjectAttributeTypeL11n + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiInvestmentObjectAttributeTypeL11nDelete(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAttributeTypeL11nDelete($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidDeleteResponse($request, $response, $val); + + return; + } + + /** @var BaseStringL11n $optionAttributeTypeL11n */ + $optionAttributeTypeL11n = InvestmentObjectAttributeTypeL11nMapper::get()->where('id', (int) $request->getData('id'))->execute(); + $this->deleteModel($request->header->account, $optionAttributeTypeL11n, InvestmentObjectAttributeTypeL11nMapper::class, 'option_attribute_type_l11n', $request->getOrigin()); + $this->createStandardDeleteResponse($request, $response, $optionAttributeTypeL11n); + } + + /** + * Api method to update InvestmentObjectAttributeType + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiInvestmentObjectAttributeTypeUpdate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAttributeTypeUpdate($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidUpdateResponse($request, $response, $val); + + return; + } + + /** @var AttributeType $old */ + $old = InvestmentObjectAttributeTypeMapper::get()->with('defaults')->where('id', (int) $request->getData('id'))->execute(); + $new = $this->updateAttributeTypeFromRequest($request, clone $old); + + $this->updateModel($request->header->account, $old, $new, InvestmentObjectAttributeTypeMapper::class, 'option_attribute_type', $request->getOrigin()); + $this->createStandardUpdateResponse($request, $response, $new); + } + + /** + * Api method to delete InvestmentObjectAttributeType + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @todo Implement API function + * + * @since 1.0.0 + */ + public function apiInvestmentObjectAttributeTypeDelete(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAttributeTypeDelete($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidDeleteResponse($request, $response, $val); + + return; + } + + /** @var AttributeType $optionAttributeType */ + $optionAttributeType = InvestmentObjectAttributeTypeMapper::get()->with('defaults')->where('id', (int) $request->getData('id'))->execute(); + $this->deleteModel($request->header->account, $optionAttributeType, InvestmentObjectAttributeTypeMapper::class, 'option_attribute_type', $request->getOrigin()); + $this->createStandardDeleteResponse($request, $response, $optionAttributeType); + } + + /** + * Api method to update InvestmentObjectAttributeValue + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiInvestmentObjectAttributeValueUpdate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAttributeValueUpdate($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidUpdateResponse($request, $response, $val); + + return; + } + + /** @var AttributeValue $old */ + $old = InvestmentObjectAttributeValueMapper::get()->where('id', (int) $request->getData('id'))->execute(); + + /** @var \Modules\Attribute\Models\Attribute $attr */ + $attr = InvestmentObjectAttributeMapper::get() + ->with('type') + ->where('id', $request->getDataInt('attribute') ?? 0) + ->execute(); + + $new = $this->updateAttributeValueFromRequest($request, clone $old, $attr); + + $this->updateModel($request->header->account, $old, $new, InvestmentObjectAttributeValueMapper::class, 'option_attribute_value', $request->getOrigin()); + $this->createStandardUpdateResponse($request, $response, $new); + } + + /** + * Api method to delete InvestmentObjectAttributeValue + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiInvestmentObjectAttributeValueDelete(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + // @todo I don't think values can be deleted? Only Attributes + // However, It should be possible to remove UNUSED default values + // either here or other function? + // if (!empty($val = $this->validateAttributeValueDelete($request))) { + // $response->header->status = RequestStatusCode::R_400; + // $this->createInvalidDeleteResponse($request, $response, $val); + + // return; + // } + + // /** @var \Modules\InvestmentManagement\Models\InvestmentObjectAttributeValue $optionAttributeValue */ + // $optionAttributeValue = InvestmentObjectAttributeValueMapper::get()->where('id', (int) $request->getData('id'))->execute(); + // $this->deleteModel($request->header->account, $optionAttributeValue, InvestmentObjectAttributeValueMapper::class, 'option_attribute_value', $request->getOrigin()); + // $this->createStandardDeleteResponse($request, $response, $optionAttributeValue); + } + + /** + * Api method to update InvestmentObjectAttributeValueL11n + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiInvestmentObjectAttributeValueL11nUpdate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAttributeValueL11nUpdate($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidUpdateResponse($request, $response, $val); + + return; + } + + /** @var BaseStringL11n $old */ + $old = InvestmentObjectAttributeValueL11nMapper::get()->where('id', (int) $request->getData('id')); + $new = $this->updateAttributeValueL11nFromRequest($request, clone $old); + + $this->updateModel($request->header->account, $old, $new, InvestmentObjectAttributeValueL11nMapper::class, 'option_attribute_value_l11n', $request->getOrigin()); + $this->createStandardUpdateResponse($request, $response, $new); + } + + /** + * Api method to delete InvestmentObjectAttributeValueL11n + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiInvestmentObjectAttributeValueL11nDelete(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAttributeValueL11nDelete($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidDeleteResponse($request, $response, $val); + + return; + } + + /** @var BaseStringL11n $optionAttributeValueL11n */ + $optionAttributeValueL11n = InvestmentObjectAttributeValueL11nMapper::get()->where('id', (int) $request->getData('id'))->execute(); + $this->deleteModel($request->header->account, $optionAttributeValueL11n, InvestmentObjectAttributeValueL11nMapper::class, 'option_attribute_value_l11n', $request->getOrigin()); + $this->createStandardDeleteResponse($request, $response, $optionAttributeValueL11n); + } +} diff --git a/Controller/ApiController.php b/Controller/ApiController.php index 910b653..904a02e 100644 --- a/Controller/ApiController.php +++ b/Controller/ApiController.php @@ -478,7 +478,7 @@ final class ApiController extends Controller $investment->investment = (int) $request->getData('investment'); $investment->parent = $request->getDataInt('parent'); $investment->supplier = $request->getDataInt('supplier'); - $investment->supplierName = $request->getDataString('supplierName') ?? ''; + $investment->supplierName = $request->getDataString('suppliername') ?? ''; $investment->item = $request->getDataInt('item'); // @todo reconsider the following lines. This seems rather complicated. diff --git a/Controller/BackendController.php b/Controller/BackendController.php index 61a2d13..8ad8713 100755 --- a/Controller/BackendController.php +++ b/Controller/BackendController.php @@ -14,8 +14,16 @@ declare(strict_types=1); namespace Modules\InvestmentManagement\Controller; +use Modules\Admin\Models\LocalizationMapper; +use Modules\Admin\Models\SettingsEnum; use Modules\InvestmentManagement\Models\InvestmentMapper; +use Modules\InvestmentManagement\Models\InvestmentObjectMapper; +use Modules\InvestmentManagement\Models\InvestmentTypeMapper; +use Modules\Media\Models\MediaMapper; +use Modules\Media\Models\MediaTypeMapper; +use Modules\Organization\Models\UnitMapper; use phpOMS\Contract\RenderableInterface; +use phpOMS\DataStorage\Database\Query\Builder; use phpOMS\Message\RequestAbstract; use phpOMS\Message\ResponseAbstract; use phpOMS\Views\View; @@ -31,7 +39,7 @@ use phpOMS\Views\View; final class BackendController extends Controller { /** - * Routing end-point for application behaviour. + * Routing end-point for application behavior. * * @param RequestAbstract $request Request * @param ResponseAbstract $response Response @@ -59,7 +67,7 @@ final class BackendController extends Controller } /** - * Routing end-point for application behaviour. + * Routing end-point for application behavior. * * @param RequestAbstract $request Request * @param ResponseAbstract $response Response @@ -70,17 +78,105 @@ final class BackendController extends Controller * @since 1.0.0 * @codeCoverageIgnore */ - public function viewInvestmentSingle(RequestAbstract $request, ResponseAbstract $response, $data = null) : RenderableInterface + public function viewInvestmentObjectProfile(RequestAbstract $request, ResponseAbstract $response, $data = null) : RenderableInterface { $view = new View($this->app->l11nManager, $request, $response); - $view->setTemplate('/Modules/InvestmentManagement/Theme/Backend/investment-create'); + $view->setTemplate('/Modules/InvestmentManagement/Theme/Backend/investment-object-profile'); $view->data['nav'] = $this->app->moduleManager->get('Navigation')->createNavigationMid(1007101001, $request, $response); + $object = InvestmentObjectMapper::get() + ->with('files') + ->with('notes') + ->with('amountGroups') + ->with('amountGroups/type') + ->with('amountGroups/amounts') + ->where('id', (int) $request->getData('id')) + ->execute(); + + $view->data['object'] = $object; + + /** @var \Model\Setting $settings */ + $settings = $this->app->appSettings->get(null, [ + SettingsEnum::DEFAULT_LOCALIZATION, + ]); + + $view->data['attributeView'] = new \Modules\Attribute\Theme\Backend\Components\AttributeView($this->app->l11nManager, $request, $response); + $view->data['attributeView']->data['defaultlocalization'] = LocalizationMapper::get()->where('id', (int) $settings->id)->execute(); + + $view->data['media-upload'] = new \Modules\Media\Theme\Backend\Components\Upload\BaseView($this->app->l11nManager, $request, $response); + return $view; } /** - * Routing end-point for application behaviour. + * Routing end-point for application behavior. + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return RenderableInterface + * + * @since 1.0.0 + * @codeCoverageIgnore + */ + public function viewInvestmentProfile(RequestAbstract $request, ResponseAbstract $response, $data = null) : RenderableInterface + { + $view = new View($this->app->l11nManager, $request, $response); + $view->setTemplate('/Modules/InvestmentManagement/Theme/Backend/investment-profile'); + $view->data['nav'] = $this->app->moduleManager->get('Navigation')->createNavigationMid(1007101001, $request, $response); + + $investment = InvestmentMapper::get() + ->with('notes') + ->with('files') + ->with('supplier') + ->with('supplier/account') + ->with('item') + ->with('createdBy') + ->with('options') + ->with('options/files') + ->with('options/notes') + ->with('options/amountGroups') + ->with('options/amountGroups/type') + ->with('options/amountGroups/amounts') + ->with('options/attributes') + ->with('options/attributes/type') + ->with('options/attributes/type/l11n') + ->with('options/attributes/value') + ->where('id', (int) $request->getData('id')) + ->where('options/attributes/type/l11n/language', $response->header->l11n->language) + ->execute(); + + $view->data['investment'] = $investment; + + /** @var \Model\Setting $settings */ + $settings = $this->app->appSettings->get(null, [ + SettingsEnum::DEFAULT_LOCALIZATION, + ]); + + $view->data['attributeView'] = new \Modules\Attribute\Theme\Backend\Components\AttributeView($this->app->l11nManager, $request, $response); + $view->data['attributeView']->data['defaultlocalization'] = LocalizationMapper::get()->where('id', (int) $settings->id)->execute(); + + $investmentTypes = InvestmentTypeMapper::getAll() + ->with('l11n') + ->where('l11n/language', $response->header->l11n->language) + ->execute(); + + $view->data['types'] = $investmentTypes; + + $units = UnitMapper::getAll() + ->execute(); + + $view->data['units'] = $units; + + $view->data['media-upload'] = new \Modules\Media\Theme\Backend\Components\Upload\BaseView($this->app->l11nManager, $request, $response); + $view->data['note'] = new \Modules\Editor\Theme\Backend\Components\Note\BaseView($this->app->l11nManager, $request, $response); + + return $view; + } + + /** + * Routing end-point for application behavior. * * @param RequestAbstract $request Request * @param ResponseAbstract $response Response diff --git a/Docs/Dev/en/SUMMARY.md b/Docs/Dev/en/SUMMARY.md new file mode 100644 index 0000000..8a97952 --- /dev/null +++ b/Docs/Dev/en/SUMMARY.md @@ -0,0 +1,3 @@ +# Developer Content + +* [Structure]({%}&page=Dev/structure) diff --git a/Docs/Dev/en/structure.md b/Docs/Dev/en/structure.md new file mode 100644 index 0000000..f917d9f --- /dev/null +++ b/Docs/Dev/en/structure.md @@ -0,0 +1,5 @@ +# Structure + +## ER + +![ER](Modules/InvestmentManagement/Docs/Dev/img/er.png) \ No newline at end of file diff --git a/Docs/Dev/img/er.png b/Docs/Dev/img/er.png new file mode 100644 index 0000000..2945977 Binary files /dev/null and b/Docs/Dev/img/er.png differ diff --git a/Docs/introduction.md b/Docs/introduction.md new file mode 100644 index 0000000..e10b99d --- /dev/null +++ b/Docs/introduction.md @@ -0,0 +1 @@ +# Introduction diff --git a/Models/AmountGroup.php b/Models/AmountGroup.php index eb07610..59a29a6 100644 --- a/Models/AmountGroup.php +++ b/Models/AmountGroup.php @@ -15,6 +15,7 @@ declare(strict_types=1); namespace Modules\InvestmentManagement\Models; use phpOMS\Localization\BaseStringL11nType; +use phpOMS\Stdlib\Base\FloatInt; /** * Costs/Earnings. @@ -30,6 +31,12 @@ class AmountGroup public string $name = ''; + /** + * Amounts + * + * @var Amount[] + * @since 1.0.0 + */ public array $amounts = []; public BaseStringL11nType $type; @@ -45,4 +52,14 @@ class AmountGroup { $this->type = new BaseStringL11nType(); } + + public function sum() : FloatInt + { + $sum = new FloatInt(); + foreach ($this->amounts as $value) { + $sum->add($value->amount); + } + + return $sum; + } } diff --git a/Models/AmountGroupMapper.php b/Models/AmountGroupMapper.php index a8209fe..0f1b13a 100644 --- a/Models/AmountGroupMapper.php +++ b/Models/AmountGroupMapper.php @@ -63,7 +63,7 @@ final class AmountGroupMapper extends DataMapperFactory */ public const HAS_MANY = [ 'amounts' => [ - 'mapper' => self::class, + 'mapper' => AmountMapper::class, 'table' => 'investmgmt_amount', 'self' => 'investmgmt_amount_group', 'external' => null, diff --git a/Models/Attribute/InvestmentObjectAttributeMapper.php b/Models/Attribute/InvestmentObjectAttributeMapper.php new file mode 100644 index 0000000..15f33ef --- /dev/null +++ b/Models/Attribute/InvestmentObjectAttributeMapper.php @@ -0,0 +1,86 @@ + + */ +final class InvestmentObjectAttributeMapper extends DataMapperFactory +{ + /** + * Columns. + * + * @var array + * @since 1.0.0 + */ + public const COLUMNS = [ + 'investmgmt_option_attr_id' => ['name' => 'investmgmt_option_attr_id', 'type' => 'int', 'internal' => 'id'], + 'investmgmt_option_attr_option' => ['name' => 'investmgmt_option_attr_option', 'type' => 'int', 'internal' => 'ref'], + 'investmgmt_option_attr_type' => ['name' => 'investmgmt_option_attr_type', 'type' => 'int', 'internal' => 'type'], + 'investmgmt_option_attr_value' => ['name' => 'investmgmt_option_attr_value', 'type' => 'int', 'internal' => 'value'], + ]; + + /** + * Has one relation. + * + * @var array + * @since 1.0.0 + */ + public const OWNS_ONE = [ + 'type' => [ + 'mapper' => InvestmentObjectAttributeTypeMapper::class, + 'external' => 'investmgmt_option_attr_type', + ], + 'value' => [ + 'mapper' => InvestmentObjectAttributeValueMapper::class, + 'external' => 'investmgmt_option_attr_value', + ], + ]; + + /** + * Model to use by the mapper. + * + * @var class-string + * @since 1.0.0 + */ + public const MODEL = Attribute::class; + + /** + * Primary table. + * + * @var string + * @since 1.0.0 + */ + public const TABLE = 'investmgmt_option_attr'; + + /** + * Primary field name. + * + * @var string + * @since 1.0.0 + */ + public const PRIMARYFIELD = 'investmgmt_option_attr_id'; +} diff --git a/Models/Attribute/InvestmentObjectAttributeTypeL11nMapper.php b/Models/Attribute/InvestmentObjectAttributeTypeL11nMapper.php new file mode 100644 index 0000000..2eda610 --- /dev/null +++ b/Models/Attribute/InvestmentObjectAttributeTypeL11nMapper.php @@ -0,0 +1,69 @@ + + */ +final class InvestmentObjectAttributeTypeL11nMapper extends DataMapperFactory +{ + /** + * Columns. + * + * @var array + * @since 1.0.0 + */ + public const COLUMNS = [ + 'investmgmt_attr_type_l11n_id' => ['name' => 'investmgmt_attr_type_l11n_id', 'type' => 'int', 'internal' => 'id'], + 'investmgmt_attr_type_l11n_title' => ['name' => 'investmgmt_attr_type_l11n_title', 'type' => 'string', 'internal' => 'content', 'autocomplete' => true], + 'investmgmt_attr_type_l11n_type' => ['name' => 'investmgmt_attr_type_l11n_type', 'type' => 'int', 'internal' => 'ref'], + 'investmgmt_attr_type_l11n_lang' => ['name' => 'investmgmt_attr_type_l11n_lang', 'type' => 'string', 'internal' => 'language'], + ]; + + /** + * Primary table. + * + * @var string + * @since 1.0.0 + */ + public const TABLE = 'investmgmt_attr_type_l11n'; + + /** + * Primary field name. + * + * @var string + * @since 1.0.0 + */ + public const PRIMARYFIELD = 'investmgmt_attr_type_l11n_id'; + + /** + * Model to use by the mapper. + * + * @var class-string + * @since 1.0.0 + */ + public const MODEL = BaseStringL11n::class; +} diff --git a/Models/Attribute/InvestmentObjectAttributeTypeMapper.php b/Models/Attribute/InvestmentObjectAttributeTypeMapper.php new file mode 100644 index 0000000..00eef59 --- /dev/null +++ b/Models/Attribute/InvestmentObjectAttributeTypeMapper.php @@ -0,0 +1,94 @@ + + */ +final class InvestmentObjectAttributeTypeMapper extends DataMapperFactory +{ + /** + * Columns. + * + * @var array + * @since 1.0.0 + */ + public const COLUMNS = [ + 'investmgmt_attr_type_id' => ['name' => 'investmgmt_attr_type_id', 'type' => 'int', 'internal' => 'id'], + 'investmgmt_attr_type_name' => ['name' => 'investmgmt_attr_type_name', 'type' => 'string', 'internal' => 'name', 'autocomplete' => true], + 'investmgmt_attr_type_datatype' => ['name' => 'investmgmt_attr_type_datatype', 'type' => 'int', 'internal' => 'datatype'], + 'investmgmt_attr_type_fields' => ['name' => 'investmgmt_attr_type_fields', 'type' => 'int', 'internal' => 'fields'], + 'investmgmt_attr_type_custom' => ['name' => 'investmgmt_attr_type_custom', 'type' => 'bool', 'internal' => 'custom'], + 'investmgmt_attr_type_pattern' => ['name' => 'investmgmt_attr_type_pattern', 'type' => 'string', 'internal' => 'validationPattern'], + 'investmgmt_attr_type_required' => ['name' => 'investmgmt_attr_type_required', 'type' => 'bool', 'internal' => 'isRequired'], + ]; + + /** + * Has many relation. + * + * @var array + * @since 1.0.0 + */ + public const HAS_MANY = [ + 'l11n' => [ + 'mapper' => InvestmentObjectAttributeTypeL11nMapper::class, + 'table' => 'investmgmt_attr_type_l11n', + 'self' => 'investmgmt_attr_type_l11n_type', + 'column' => 'content', + 'external' => null, + ], + 'defaults' => [ + 'mapper' => InvestmentObjectAttributeValueMapper::class, + 'table' => 'investmgmt_option_attr_default', + 'self' => 'investmgmt_option_attr_default_type', + 'external' => 'investmgmt_option_attr_default_value', + ], + ]; + + /** + * Model to use by the mapper. + * + * @var class-string + * @since 1.0.0 + */ + public const MODEL = AttributeType::class; + + /** + * Primary table. + * + * @var string + * @since 1.0.0 + */ + public const TABLE = 'investmgmt_attr_type'; + + /** + * Primary field name. + * + * @var string + * @since 1.0.0 + */ + public const PRIMARYFIELD = 'investmgmt_attr_type_id'; +} diff --git a/Models/Attribute/InvestmentObjectAttributeValueL11nMapper.php b/Models/Attribute/InvestmentObjectAttributeValueL11nMapper.php new file mode 100644 index 0000000..2653c58 --- /dev/null +++ b/Models/Attribute/InvestmentObjectAttributeValueL11nMapper.php @@ -0,0 +1,69 @@ + + */ +final class InvestmentObjectAttributeValueL11nMapper extends DataMapperFactory +{ + /** + * Columns. + * + * @var array + * @since 1.0.0 + */ + public const COLUMNS = [ + 'investmgmt_attr_value_l11n_id' => ['name' => 'investmgmt_attr_value_l11n_id', 'type' => 'int', 'internal' => 'id'], + 'investmgmt_attr_value_l11n_title' => ['name' => 'investmgmt_attr_value_l11n_title', 'type' => 'string', 'internal' => 'content', 'autocomplete' => true], + 'investmgmt_attr_value_l11n_value' => ['name' => 'investmgmt_attr_value_l11n_value', 'type' => 'int', 'internal' => 'ref'], + 'investmgmt_attr_value_l11n_lang' => ['name' => 'investmgmt_attr_value_l11n_lang', 'type' => 'string', 'internal' => 'language'], + ]; + + /** + * Primary table. + * + * @var string + * @since 1.0.0 + */ + public const TABLE = 'investmgmt_attr_value_l11n'; + + /** + * Primary field name. + * + * @var string + * @since 1.0.0 + */ + public const PRIMARYFIELD = 'investmgmt_attr_value_l11n_id'; + + /** + * Model to use by the mapper. + * + * @var class-string + * @since 1.0.0 + */ + public const MODEL = BaseStringL11n::class; +} diff --git a/Models/Attribute/InvestmentObjectAttributeValueMapper.php b/Models/Attribute/InvestmentObjectAttributeValueMapper.php new file mode 100644 index 0000000..80ba9a7 --- /dev/null +++ b/Models/Attribute/InvestmentObjectAttributeValueMapper.php @@ -0,0 +1,90 @@ + + */ +final class InvestmentObjectAttributeValueMapper extends DataMapperFactory +{ + /** + * Columns. + * + * @var array + * @since 1.0.0 + */ + public const COLUMNS = [ + 'investmgmt_attr_value_id' => ['name' => 'investmgmt_attr_value_id', 'type' => 'int', 'internal' => 'id'], + 'investmgmt_attr_value_default' => ['name' => 'investmgmt_attr_value_default', 'type' => 'bool', 'internal' => 'isDefault'], + 'investmgmt_attr_value_valueStr' => ['name' => 'investmgmt_attr_value_valueStr', 'type' => 'string', 'internal' => 'valueStr'], + 'investmgmt_attr_value_valueInt' => ['name' => 'investmgmt_attr_value_valueInt', 'type' => 'int', 'internal' => 'valueInt'], + 'investmgmt_attr_value_valueDec' => ['name' => 'investmgmt_attr_value_valueDec', 'type' => 'float', 'internal' => 'valueDec'], + 'investmgmt_attr_value_valueDat' => ['name' => 'investmgmt_attr_value_valueDat', 'type' => 'DateTime', 'internal' => 'valueDat'], + 'investmgmt_attr_value_unit' => ['name' => 'investmgmt_attr_value_unit', 'type' => 'string', 'internal' => 'unit'], + 'investmgmt_attr_value_deptype' => ['name' => 'investmgmt_attr_value_deptype', 'type' => 'int', 'internal' => 'dependingAttributeType'], + 'investmgmt_attr_value_depvalue' => ['name' => 'investmgmt_attr_value_depvalue', 'type' => 'int', 'internal' => 'dependingAttributeValue'], + ]; + + /** + * Has many relation. + * + * @var array + * @since 1.0.0 + */ + public const HAS_MANY = [ + 'l11n' => [ + 'mapper' => InvestmentObjectAttributeValueL11nMapper::class, + 'table' => 'investmgmt_attr_value_l11n', + 'self' => 'investmgmt_attr_value_l11n_value', + 'column' => 'content', + 'external' => null, + ], + ]; + + /** + * Model to use by the mapper. + * + * @var class-string + * @since 1.0.0 + */ + public const MODEL = AttributeValue::class; + + /** + * Primary table. + * + * @var string + * @since 1.0.0 + */ + public const TABLE = 'investmgmt_attr_value'; + + /** + * Primary field name. + * + * @var string + * @since 1.0.0 + */ + public const PRIMARYFIELD = 'investmgmt_attr_value_id'; +} diff --git a/Models/Investment.php b/Models/Investment.php index a3fa781..36eca0c 100644 --- a/Models/Investment.php +++ b/Models/Investment.php @@ -35,8 +35,6 @@ class Investment public string $description = ''; - public int $depreciationType = DepreciationType::NONE; - public int $status = InvestmentStatus::DRAFT; public ?BaseStringL11nType $type = null; diff --git a/Models/InvestmentMapper.php b/Models/InvestmentMapper.php index 047819f..aaf31c8 100644 --- a/Models/InvestmentMapper.php +++ b/Models/InvestmentMapper.php @@ -43,7 +43,6 @@ final class InvestmentMapper extends DataMapperFactory 'investmgmt_investment_name' => ['name' => 'investmgmt_investment_name', 'type' => 'string', 'internal' => 'name'], 'investmgmt_investment_description' => ['name' => 'investmgmt_investment_description', 'type' => 'string', 'internal' => 'description'], 'investmgmt_investment_status' => ['name' => 'investmgmt_investment_status', 'type' => 'int', 'internal' => 'status'], - 'investmgmt_investment_depreciation_type' => ['name' => 'investmgmt_investment_depreciation_type', 'type' => 'int', 'internal' => 'depreciationType'], 'investmgmt_investment_unit' => ['name' => 'investmgmt_investment_unit', 'type' => 'int', 'internal' => 'unit'], 'investmgmt_investment_created_by' => ['name' => 'investmgmt_investment_created_by', 'type' => 'int', 'internal' => 'createdBy', 'readonly' => true], 'investmgmt_investment_performance' => ['name' => 'investmgmt_investment_performance', 'type' => 'DateTime', 'internal' => 'performanceDate'], @@ -84,8 +83,8 @@ final class InvestmentMapper extends DataMapperFactory ], 'options' => [ 'mapper' => InvestmentObjectMapper::class, - 'table' => 'investmgmt_investment_option', - 'self' => 'investmgmt_investment_option_investment', + 'table' => 'investmgmt_option', + 'self' => 'investmgmt_option_investment', 'external' => null, ], ]; diff --git a/Models/InvestmentObject.php b/Models/InvestmentObject.php index 9a64bb7..3f7f566 100644 --- a/Models/InvestmentObject.php +++ b/Models/InvestmentObject.php @@ -14,6 +14,9 @@ declare(strict_types=1); namespace Modules\InvestmentManagement\Models; +use Modules\ItemManagement\Models\Item; +use Modules\SupplierManagement\Models\Supplier; + /** * Investment object. * @@ -30,7 +33,7 @@ class InvestmentObject public string $description = ''; - public ?int $supplier = null; + public ?Supplier $supplier = null; public string $supplierName = ''; @@ -38,6 +41,9 @@ class InvestmentObject /** * Costs / Revenue + * + * @var AmountGroup[] + * @since 1.0.0 */ public array $amountGroups = []; @@ -49,8 +55,20 @@ class InvestmentObject public int $investment = 0; - public ?int $item = null; + public ?Item $item = null; + + public function getAmountByTypeName(string $type) : AmountGroup + { + foreach ($this->amountGroups as $group) { + if ($group->type->title === $type) { + return $group; + } + } + + return new NullAmountGroup(); + } use \Modules\Media\Models\MediaListTrait; use \Modules\Editor\Models\EditorDocListTrait; + use \Modules\Attribute\Models\AttributeHolderTrait; } diff --git a/Models/InvestmentObjectMapper.php b/Models/InvestmentObjectMapper.php index 86a71ed..f10c557 100644 --- a/Models/InvestmentObjectMapper.php +++ b/Models/InvestmentObjectMapper.php @@ -15,6 +15,7 @@ declare(strict_types=1); namespace Modules\InvestmentManagement\Models; use Modules\Editor\Models\EditorDocMapper; +use Modules\InvestmentManagement\Models\Attribute\InvestmentObjectAttributeMapper; use Modules\ItemManagement\Models\ItemMapper; use Modules\Media\Models\MediaMapper; use Modules\SupplierManagement\Models\SupplierMapper; @@ -93,6 +94,12 @@ final class InvestmentObjectMapper extends DataMapperFactory 'self' => 'investmgmt_amount_group_option', 'external' => null, ], + 'attributes' => [ + 'mapper' => InvestmentObjectAttributeMapper::class, + 'table' => 'investmgmt_option_attr', + 'self' => 'investmgmt_option_attr_item', + 'external' => null, + ], ]; /** diff --git a/Models/NullAmount.php b/Models/NullAmount.php new file mode 100644 index 0000000..60a05aa --- /dev/null +++ b/Models/NullAmount.php @@ -0,0 +1,46 @@ +id = $id; + } + + /** + * {@inheritdoc} + */ + public function jsonSerialize() : mixed + { + return ['id' => $this->id]; + } +} diff --git a/Models/NullAmountGroup.php b/Models/NullAmountGroup.php new file mode 100644 index 0000000..dffa6b5 --- /dev/null +++ b/Models/NullAmountGroup.php @@ -0,0 +1,46 @@ +id = $id; + } + + /** + * {@inheritdoc} + */ + public function jsonSerialize() : mixed + { + return ['id' => $this->id]; + } +} diff --git a/Models/PermissionCategory.php b/Models/PermissionCategory.php index 6bd9289..a9ce99f 100755 --- a/Models/PermissionCategory.php +++ b/Models/PermissionCategory.php @@ -17,7 +17,7 @@ namespace Modules\InvestmentManagement\Models; use phpOMS\Stdlib\Base\Enum; /** - * Permision state enum. + * Permission category enum. * * @package Modules\InvestmentManagement\Models * @license OMS License 2.0 diff --git a/Theme/Backend/Lang/de.lang.php b/Theme/Backend/Lang/de.lang.php index 84e04a4..e80adf8 100644 --- a/Theme/Backend/Lang/de.lang.php +++ b/Theme/Backend/Lang/de.lang.php @@ -23,4 +23,20 @@ return ['InvestmentManagement' => [ 'Name' => 'Name', 'Status' => 'Status', 'Title' => 'Titel', + 'Files' => 'Dateien', + 'Notes' => 'Notizen', + 'Options' => 'Optionen', + 'Option' => 'Option', + 'Description' => 'Beschreibung', + 'Link' => 'Link', + 'Amounts' => 'Beträge', + 'Amount' => 'Betrag', + 'Quantity' => 'Menge', + 'Attributes' => 'Attribute', + 'Type' => 'Typ', + 'Purchase' => 'Kauf', + 'Price' => 'Preis', + 'Supplier' => 'Lieferant', + 'Approved' => 'Genehmigt', + 'Approve' => 'Genehmigen', ]]; diff --git a/Theme/Backend/Lang/en.lang.php b/Theme/Backend/Lang/en.lang.php index 7fc003a..44578f8 100755 --- a/Theme/Backend/Lang/en.lang.php +++ b/Theme/Backend/Lang/en.lang.php @@ -22,5 +22,21 @@ return ['InvestmentManagement' => [ 'Investments' => 'Investments', 'Name' => 'Name', 'Status' => 'Status', - 'Title' => 'Titel', + 'Title' => 'Title', + 'Files' => 'Files', + 'Notes' => 'Notes', + 'Options' => 'Options', + 'Option' => 'Option', + 'Description' => 'Description', + 'Link' => 'Link', + 'Amounts' => 'Amounts', + 'Amount' => 'Amount', + 'Quantity' => 'Quantity', + 'Attributes' => 'Attributes', + 'Type' => 'Type', + 'Purchase' => 'Purchase', + 'Price' => 'Price', + 'Supplier' => 'Supplier', + 'Approved' => 'Approved', + 'Approve' => 'Approve', ]]; diff --git a/Theme/Backend/investment-object-profile.tpl.php b/Theme/Backend/investment-object-profile.tpl.php new file mode 100644 index 0000000..e3b836a --- /dev/null +++ b/Theme/Backend/investment-object-profile.tpl.php @@ -0,0 +1,67 @@ +data['object'] ?? null; + +$attributeView = $this->data['attributeView']; +$languages = ISO639Enum::getConstants(); + +echo $this->data['nav']->render(); ?> +
+
+ +
+
+ request->uri->fragment === 'c-tab-1' ? ' checked' : ''; ?>> +
+
+ + request->uri->fragment === 'c-tab-2' ? ' checked' : ''; ?>> +
+
+ render( + $object->attributes, + $this->data['attributeTypes'] ?? [], + $this->data['units'] ?? [], + '{/api}finance/investment/object', + $object->id + ); + ?> +
+
+ + request->uri->fragment === 'c-tab-3' ? ' checked' : ''; ?>> +
+
+ + request->uri->fragment === 'c-tab-4' ? ' checked' : ''; ?>> +
+ data['media-upload']->render('object-file', 'files', '', $object->files); ?> +
+ + request->uri->fragment === 'c-tab-5' ? ' checked' : ''; ?>> +
+ data['note']->render('object-note', 'notes', $object->notes); ?> +
+
+
\ No newline at end of file diff --git a/Theme/Backend/investment-profile.tpl.php b/Theme/Backend/investment-profile.tpl.php new file mode 100644 index 0000000..d70e0d9 --- /dev/null +++ b/Theme/Backend/investment-profile.tpl.php @@ -0,0 +1,246 @@ +data['investment'] ?? null; +$investmentStatus = InvestmentStatus::getConstants(); +$files = $investment->files; +$investmentTypes = $this->data['types'] ?? []; + +echo $this->data['nav']->render(); ?> +
+
+ +
+
+ request->uri->fragment === 'c-tab-1' ? ' checked' : ''; ?>> +
+
+
+
+
getHtml('Investment'); ?>
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ id === 0) : ?> + + + + +
+
+
+ +
+
+
+ getHtml('Options'); ?> + download +
+
+ + + + + options as $option) : ?> + +
+ getHtml('Name'); ?> + getHtml('Supplier'); ?> + getHtml('Price'); ?> + getHtml('Link'); ?> +
approved) : ?>check + printHtml($option->name); ?> + supplier === null + ? $this->printHtml($option->supplierName) + : $option->supplier->account->name1; + ?> + getCurrency($option->getAmountByTypeName('costs')->sum(), '', 'medium'); ?> + link)) : ?> + printHtml($option->link); ?> + + +
+
+
+
+
+
+ + request->uri->fragment === 'c-tab-2' ? ' checked' : ''; ?>> +
+ data['media-upload']->render('investment-file', 'files', '', $investment->files); ?> +
+ + request->uri->fragment === 'c-tab-3' ? ' checked' : ''; ?>> +
+ data['note']->render('investment-notes', '', $investment->notes); ?> +
+ + request->uri->fragment === 'c-tab-4' ? ' checked' : ''; ?>> +
+
+ options as $option) : + if ($option->parent !== null) { + continue; + } + + ++$count; + ?> +
+
+
getHtml('Option'); ?>
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + + +
+ +
+ + + + + attributes as $attribute) : ?> + +
getHtml('Attributes'); ?> +
+ + attributes)) : ?> +
getHtml('Empty', '0', '0'); ?> + +
+
+ +
+ + + + + amountGroups as $group) : ?> + +
getHtml('Amounts'); ?> +
getCurrency($group->sum(), '', 'medium'); ?> + + files)) : ?> +
getHtml('Empty', '0', '0'); ?> + +
+
+ +
+ + + + + files as $file) : ?> + +
getHtml('Files'); ?> +
+ + files)) : ?> +
getHtml('Empty', '0', '0'); ?> + +
+
+ +
+ + + + + notes as $note) : ?> + +
getHtml('Notes'); ?> +
+ + notes)) : ?> +
getHtml('Empty', '0', '0'); ?> + +
+
+
+ +
+
+ +
+
+ +
+