diff --git a/Admin/Install/Navigation.install.json b/Admin/Install/Navigation.install.json index c6eb094..f7beb18 100755 --- a/Admin/Install/Navigation.install.json +++ b/Admin/Install/Navigation.install.json @@ -13,7 +13,7 @@ "permission": { "permission": 2, "category": null, "element": null }, "parent": 1003301001, "children": [ - { + { "id": 1007902001, "pid": "/contract", "type": 3, @@ -27,6 +27,21 @@ "permission": { "permission": 2, "category": null, "element": null }, "parent": 1007901001, "children": [] + }, + { + "id": 1007903001, + "pid": "/contract", + "type": 3, + "subtype": 1, + "name": "ContractTypes", + "uri": "{/base}/contract/type/list?{?}", + "target": "self", + "icon": null, + "order": 1, + "from": "Kanban", + "permission": { "permission": 2, "category": null, "element": null }, + "parent": 1007901001, + "children": [] } ] } diff --git a/Admin/Install/db.json b/Admin/Install/db.json index edd7e23..80e7419 100755 --- a/Admin/Install/db.json +++ b/Admin/Install/db.json @@ -185,5 +185,260 @@ "foreignKey": "media_id" } } - } + }, + "contractmgmt_contract_note": { + "name": "contractmgmt_contract_note", + "fields": { + "contractmgmt_contract_note_id": { + "name": "contractmgmt_contract_note_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "contractmgmt_contract_note_contract": { + "name": "contractmgmt_contract_note_contract", + "type": "INT", + "null": false, + "foreignTable": "contractmgmt_contract", + "foreignKey": "contractmgmt_contract_id" + }, + "contractmgmt_contract_note_doc": { + "name": "contractmgmt_contract_note_doc", + "type": "INT", + "null": false, + "foreignTable": "editor_doc", + "foreignKey": "editor_doc_id" + } + } + }, + "contractmgmt_attr_type": { + "name": "contractmgmt_attr_type", + "fields": { + "contractmgmt_attr_type_id": { + "name": "contractmgmt_attr_type_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "contractmgmt_attr_type_name": { + "name": "contractmgmt_attr_type_name", + "type": "VARCHAR(255)", + "null": false, + "unique": true + }, + "contractmgmt_attr_type_datatype": { + "name": "contractmgmt_attr_type_datatype", + "type": "INT(11)", + "null": false + }, + "contractmgmt_attr_type_fields": { + "name": "contractmgmt_attr_type_fields", + "type": "INT(11)", + "null": false + }, + "contractmgmt_attr_type_custom": { + "name": "contractmgmt_attr_type_custom", + "type": "TINYINT(1)", + "null": false + }, + "contractmgmt_attr_type_required": { + "description": "Every contract must have this attribute type if set to true.", + "name": "contractmgmt_attr_type_required", + "type": "TINYINT(1)", + "null": false + }, + "contractmgmt_attr_type_pattern": { + "description": "This is a regex validation pattern.", + "name": "contractmgmt_attr_type_pattern", + "type": "VARCHAR(255)", + "null": false + } + } + }, + "contractmgmt_attr_type_l11n": { + "name": "contractmgmt_attr_type_l11n", + "fields": { + "contractmgmt_attr_type_l11n_id": { + "name": "contractmgmt_attr_type_l11n_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "contractmgmt_attr_type_l11n_title": { + "name": "contractmgmt_attr_type_l11n_title", + "type": "VARCHAR(255)", + "null": false + }, + "contractmgmt_attr_type_l11n_type": { + "name": "contractmgmt_attr_type_l11n_type", + "type": "INT(11)", + "null": false, + "foreignTable": "contractmgmt_attr_type", + "foreignKey": "contractmgmt_attr_type_id" + }, + "contractmgmt_attr_type_l11n_lang": { + "name": "contractmgmt_attr_type_l11n_lang", + "type": "VARCHAR(2)", + "null": false, + "foreignTable": "language", + "foreignKey": "language_639_1" + } + } + }, + "contractmgmt_attr_value": { + "name": "contractmgmt_attr_value", + "fields": { + "contractmgmt_attr_value_id": { + "name": "contractmgmt_attr_value_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "contractmgmt_attr_value_default": { + "name": "contractmgmt_attr_value_default", + "type": "TINYINT(1)", + "null": false + }, + "contractmgmt_attr_value_valueStr": { + "name": "contractmgmt_attr_value_valueStr", + "type": "VARCHAR(255)", + "null": true, + "default": null + }, + "contractmgmt_attr_value_valueInt": { + "name": "contractmgmt_attr_value_valueInt", + "type": "INT(11)", + "null": true, + "default": null + }, + "contractmgmt_attr_value_valueDec": { + "name": "contractmgmt_attr_value_valueDec", + "type": "DECIMAL(19,5)", + "null": true, + "default": null + }, + "contractmgmt_attr_value_valueDat": { + "name": "contractmgmt_attr_value_valueDat", + "type": "DATETIME", + "null": true, + "default": null + }, + "contractmgmt_attr_value_unit": { + "name": "contractmgmt_attr_value_unit", + "type": "VARCHAR(255)", + "null": false + }, + "contractmgmt_attr_value_deptype": { + "name": "contractmgmt_attr_value_deptype", + "type": "INT(11)", + "null": true, + "default": null, + "foreignTable": "contractmgmt_attr_type", + "foreignKey": "contractmgmt_attr_type_id" + }, + "contractmgmt_attr_value_depvalue": { + "name": "contractmgmt_attr_value_depvalue", + "type": "INT(11)", + "null": true, + "default": null, + "foreignTable": "contractmgmt_attr_value", + "foreignKey": "contractmgmt_attr_value_id" + } + } + }, + "contractmgmt_attr_value_l11n": { + "name": "contractmgmt_attr_value_l11n", + "fields": { + "contractmgmt_attr_value_l11n_id": { + "name": "contractmgmt_attr_value_l11n_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "contractmgmt_attr_value_l11n_title": { + "name": "contractmgmt_attr_value_l11n_title", + "type": "VARCHAR(255)", + "null": false + }, + "contractmgmt_attr_value_l11n_value": { + "name": "contractmgmt_attr_value_l11n_value", + "type": "INT(11)", + "null": false, + "foreignTable": "contractmgmt_attr_value", + "foreignKey": "contractmgmt_attr_value_id" + }, + "contractmgmt_attr_value_l11n_lang": { + "name": "contractmgmt_attr_value_l11n_lang", + "type": "VARCHAR(2)", + "null": false, + "foreignTable": "language", + "foreignKey": "language_639_1" + } + } + }, + "contractmgmt_contract_attr_default": { + "name": "contractmgmt_contract_attr_default", + "fields": { + "contractmgmt_contract_attr_default_id": { + "name": "contractmgmt_contract_attr_default_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "contractmgmt_contract_attr_default_type": { + "name": "contractmgmt_contract_attr_default_type", + "type": "INT(11)", + "null": false, + "foreignTable": "contractmgmt_attr_type", + "foreignKey": "contractmgmt_attr_type_id" + }, + "contractmgmt_contract_attr_default_value": { + "name": "contractmgmt_contract_attr_default_value", + "type": "INT(11)", + "null": false, + "foreignTable": "contractmgmt_attr_value", + "foreignKey": "contractmgmt_attr_value_id" + } + } + }, + "contractmgmt_contract_attr": { + "name": "contractmgmt_contract_attr", + "fields": { + "contractmgmt_contract_attr_id": { + "name": "contractmgmt_contract_attr_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "contractmgmt_contract_attr_contract": { + "name": "contractmgmt_contract_attr_contract", + "type": "INT(11)", + "null": false, + "foreignTable": "contractmgmt_contract", + "foreignKey": "contractmgmt_contract_id" + }, + "contractmgmt_contract_attr_type": { + "name": "contractmgmt_contract_attr_type", + "type": "INT(11)", + "null": false, + "foreignTable": "contractmgmt_attr_type", + "foreignKey": "contractmgmt_attr_type_id" + }, + "contractmgmt_contract_attr_value": { + "name": "contractmgmt_contract_attr_value", + "type": "INT(11)", + "null": true, + "default": null, + "foreignTable": "contractmgmt_attr_value", + "foreignKey": "contractmgmt_attr_value_id" + } + } + }, } \ No newline at end of file diff --git a/Admin/Routes/Web/Api.php b/Admin/Routes/Web/Api.php new file mode 100644 index 0000000..db9ac85 --- /dev/null +++ b/Admin/Routes/Web/Api.php @@ -0,0 +1,83 @@ + [ + [ + 'dest' => '\Modules\ContractManagement\Controller\ApiController:apiContractTypeCreate', + 'verb' => RouteVerb::PUT, + 'permission' => [ + 'module' => Controller::NAME, + 'type' => PermissionType::READ, + 'state' => PermissionCategory::CONTRACT_TYPE, + ], + ], + [ + 'dest' => '\Modules\ContractManagement\Controller\ApiController:apiContractTypeUpdate', + 'verb' => RouteVerb::SET, + 'permission' => [ + 'module' => Controller::NAME, + 'type' => PermissionType::READ, + 'state' => PermissionCategory::CONTRACT_TYPE, + ], + ], + ], + + '^.*/contract$' => [ + [ + 'dest' => '\Modules\ContractManagement\Controller\ApiController:apiContractCreate', + 'verb' => RouteVerb::PUT, + 'permission' => [ + 'module' => Controller::NAME, + 'type' => PermissionType::READ, + 'state' => PermissionCategory::CONTRACT, + ], + ], + [ + 'dest' => '\Modules\ContractManagement\Controller\ApiController:apiContractUpdate', + 'verb' => RouteVerb::SET, + 'permission' => [ + 'module' => Controller::NAME, + 'type' => PermissionType::READ, + 'state' => PermissionCategory::CONTRACT, + ], + ], + ], + + '^.*/contract/attribute.*$' => [ + [ + 'dest' => '\Modules\ContractManagement\Controller\ApiAttributeController:apiAttributeCreate', + 'verb' => RouteVerb::PUT, + 'permission' => [ + 'module' => Controller::NAME, + 'type' => PermissionType::READ, + 'state' => PermissionCategory::CONTRACT, + ], + ], + [ + 'dest' => '\Modules\ContractManagement\Controller\ApiAttributeController:apiAttributeUpdate', + 'verb' => RouteVerb::SET, + 'permission' => [ + 'module' => Controller::NAME, + 'type' => PermissionType::READ, + 'state' => PermissionCategory::CONTRACT, + ], + ], + ], +]; diff --git a/Admin/Routes/Web/Backend.php b/Admin/Routes/Web/Backend.php index e7bb0cc..a79d4a5 100755 --- a/Admin/Routes/Web/Backend.php +++ b/Admin/Routes/Web/Backend.php @@ -40,4 +40,26 @@ return [ ], ], ], + '^.*/contract/type/list.*$' => [ + [ + 'dest' => '\Modules\ContractManagement\Controller\BackendController:viewContractTypeList', + 'verb' => RouteVerb::GET, + 'permission' => [ + 'module' => BackendController::NAME, + 'type' => PermissionType::READ, + 'state' => PermissionCategory::CONTRACT_TYPE, + ], + ], + ], + '^.*/contract/type/profile.*$' => [ + [ + 'dest' => '\Modules\ContractManagement\Controller\BackendController:viewContractType', + 'verb' => RouteVerb::GET, + 'permission' => [ + 'module' => BackendController::NAME, + 'type' => PermissionType::READ, + 'state' => PermissionCategory::CONTRACT_TYPE, + ], + ], + ], ]; diff --git a/Controller/ApiAttributeController.php b/Controller/ApiAttributeController.php new file mode 100644 index 0000000..564baf5 --- /dev/null +++ b/Controller/ApiAttributeController.php @@ -0,0 +1,534 @@ +validateContractAttributeCreate($request))) { + $response->data['attribute_create'] = new FormValidation($val); + $response->header->status = RequestStatusCode::R_400; + + return; + } + + $attribute = $this->createContractAttributeFromRequest($request); + $this->createModel($request->header->account, $attribute, ContractAttributeMapper::class, 'attribute', $request->getOrigin()); + + $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Attribute', 'Attribute successfully created', $attribute); + } + + /** + * Method to create contract attribute from request. + * + * @param RequestAbstract $request Request + * + * @return Attribute + * + * @since 1.0.0 + */ + private function createContractAttributeFromRequest(RequestAbstract $request) : Attribute + { + $attribute = new Attribute(); + $attribute->ref = (int) $request->getData('contract'); + $attribute->type = new NullAttributeType((int) $request->getData('type')); + + if ($request->hasData('value')) { + $attribute->value = new NullAttributeValue((int) $request->getData('value')); + } else { + $newRequest = clone $request; + $newRequest->setData('value', $request->getData('custom'), true); + + $value = $this->createAttributeValueFromRequest($newRequest); + + $attribute->value = $value; + } + + return $attribute; + } + + /** + * Validate contract attribute create request + * + * @param RequestAbstract $request Request + * + * @return array + * + * @since 1.0.0 + */ + private function validateContractAttributeCreate(RequestAbstract $request) : array + { + $val = []; + if (($val['type'] = !$request->hasData('type')) + || ($val['value'] = (!$request->hasData('value') && !$request->hasData('custom'))) + || ($val['contract'] = !$request->hasData('contract')) + ) { + return $val; + } + + return []; + } + + /** + * Api method to create contract attribute + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param mixed $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiContractAttributeUpdate(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void + { + if (!empty($val = $this->validateContractAttributeUpdate($request))) { + $response->data['attribute_update'] = new FormValidation($val); + $response->header->status = RequestStatusCode::R_400; + + return; + } + + $old = ContractAttributeMapper::get() + ->with('type') + ->with('type/defaults') + ->with('value') + ->where('id', (int) $request->getData('id')) + ->execute(); + + $new = $this->updateContractAttributeFromRequest($request, $old->deepClone()); + $this->updateModel($request->header->account, $old, $new, ContractAttributeMapper::class, 'attribute', $request->getOrigin()); + + if ($new->value->getValue() !== $old->value->getValue()) { + $this->updateModel($request->header->account, $old->value, $new->value, ContractAttributeValueMapper::class, 'attribute_value', $request->getOrigin()); + } + + $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Attribute', 'Attribute successfully updated', $new); + } + + /** + * Method to create contract attribute from request. + * + * @param RequestAbstract $request Request + * + * @return Attribute + * + * @since 1.0.0 + */ + private function updateContractAttributeFromRequest(RequestAbstract $request, Attribute $attribute) : Attribute + { + if ($attribute->type->custom) { + if ($request->hasData('value')) { + // @question: we are overwriting the old value, could there be a use case where we want to create a new value and keep the old one? + $attribute->value->setValue($request->getData('value'), $attribute->type->datatype); + } + } else { + if ($request->hasData('value')) { + // @todo: fix by only accepting the value id to be used + // this is a workaround for now because the front end doesn't allow to dynamically show default values. + $value = $attribute->type->getDefaultByValue($request->getData('value')); + + if ($value->id !== 0) { + $attribute->value = $attribute->type->getDefaultByValue($request->getData('value')); + } + } + } + + return $attribute; + } + + /** + * Validate contract attribute create request + * + * @param RequestAbstract $request Request + * + * @return array + * + * @since 1.0.0 + */ + private function validateContractAttributeUpdate(RequestAbstract $request) : array + { + $val = []; + if (($val['id'] = !$request->hasData('id')) + ) { + return $val; + } + + return []; + } + + /** + * Api method to create contract attribute l11n + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param mixed $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiContractAttributeTypeL11nCreate(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void + { + if (!empty($val = $this->validateContractAttributeTypeL11nCreate($request))) { + $response->data['attr_type_l11n_create'] = new FormValidation($val); + $response->header->status = RequestStatusCode::R_400; + + return; + } + + $attrL11n = $this->createContractAttributeTypeL11nFromRequest($request); + $this->createModel($request->header->account, $attrL11n, ContractAttributeTypeL11nMapper::class, 'attr_type_l11n', $request->getOrigin()); + $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Localization', 'Localization successfully created', $attrL11n); + } + + /** + * Method to create contract attribute l11n from request. + * + * @param RequestAbstract $request Request + * + * @return BaseStringL11n + * + * @since 1.0.0 + */ + private function createContractAttributeTypeL11nFromRequest(RequestAbstract $request) : BaseStringL11n + { + $attrL11n = new BaseStringL11n(); + $attrL11n->ref = $request->getDataInt('type') ?? 0; + $attrL11n->setLanguage( + $request->getDataString('language') ?? $request->header->l11n->language + ); + $attrL11n->content = $request->getDataString('title') ?? ''; + + return $attrL11n; + } + + /** + * Validate contract attribute l11n create request + * + * @param RequestAbstract $request Request + * + * @return array + * + * @since 1.0.0 + */ + private function validateContractAttributeTypeL11nCreate(RequestAbstract $request) : array + { + $val = []; + if (($val['title'] = !$request->hasData('title')) + || ($val['type'] = !$request->hasData('type')) + ) { + return $val; + } + + return []; + } + + /** + * Api method to create contract attribute type + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param mixed $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiContractAttributeTypeCreate(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void + { + if (!empty($val = $this->validateContractAttributeTypeCreate($request))) { + $response->data['attr_type_create'] = new FormValidation($val); + $response->header->status = RequestStatusCode::R_400; + + return; + } + + $attrType = $this->createAttributeTypeFromRequest($request); + $this->createModel($request->header->account, $attrType, ContractAttributeTypeMapper::class, 'attr_type', $request->getOrigin()); + + $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Attribute type', 'Attribute type successfully created', $attrType); + } + + /** + * Method to create contract attribute from request. + * + * @param RequestAbstract $request Request + * + * @return AttributeType + * + * @since 1.0.0 + */ + private function createAttributeTypeFromRequest(RequestAbstract $request) : AttributeType + { + $attrType = new AttributeType($request->getDataString('name') ?? ''); + $attrType->datatype = $request->getDataInt('datatype') ?? 0; + $attrType->custom = $request->getDataBool('custom') ?? false; + $attrType->isRequired = (bool) ($request->getData('is_required') ?? false); + $attrType->validationPattern = $request->getDataString('validation_pattern') ?? ''; + $attrType->setL11n($request->getDataString('title') ?? '', $request->getDataString('language') ?? ISO639x1Enum::_EN); + $attrType->setFields($request->getDataInt('fields') ?? 0); + + return $attrType; + } + + /** + * Validate contract attribute create request + * + * @param RequestAbstract $request Request + * + * @return array + * + * @since 1.0.0 + */ + private function validateContractAttributeTypeCreate(RequestAbstract $request) : array + { + $val = []; + if (($val['title'] = !$request->hasData('title')) + || ($val['name'] = !$request->hasData('name')) + ) { + return $val; + } + + return []; + } + + /** + * Api method to create contract attribute value + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param mixed $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiContractAttributeValueCreate(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void + { + if (!empty($val = $this->validateContractAttributeValueCreate($request))) { + $response->data['attr_value_create'] = new FormValidation($val); + $response->header->status = RequestStatusCode::R_400; + + return; + } + + $attrValue = $this->createAttributeValueFromRequest($request); + $this->createModel($request->header->account, $attrValue, ContractAttributeValueMapper::class, 'attr_value', $request->getOrigin()); + + if ($attrValue->isDefault) { + $this->createModelRelation( + $request->header->account, + (int) $request->getData('type'), + $attrValue->id, + ContractAttributeTypeMapper::class, 'defaults', '', $request->getOrigin() + ); + } + + $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Attribute value', 'Attribute value successfully created', $attrValue); + } + + /** + * Method to create contract attribute value from request. + * + * @param RequestAbstract $request Request + * + * @return AttributeValue + * + * @since 1.0.0 + */ + private function createAttributeValueFromRequest(RequestAbstract $request) : AttributeValue + { + /** @var AttributeType $type */ + $type = ContractAttributeTypeMapper::get() + ->where('id', $request->getDataInt('type') ?? 0) + ->execute(); + + $attrValue = new AttributeValue(); + $attrValue->isDefault = $request->getDataBool('default') ?? false; + $attrValue->setValue($request->getData('value'), $type->datatype); + + if ($request->hasData('title')) { + $attrValue->setL11n($request->getDataString('title') ?? '', $request->getDataString('language') ?? ISO639x1Enum::_EN); + } + + return $attrValue; + } + + /** + * Validate contract attribute value create request + * + * @param RequestAbstract $request Request + * + * @return array + * + * @since 1.0.0 + */ + private function validateContractAttributeValueCreate(RequestAbstract $request) : array + { + $val = []; + if (($val['type'] = !$request->hasData('type')) + || ($val['value'] = !$request->hasData('value')) + ) { + return $val; + } + + return []; + } + + /** + * Api method to create contract attribute l11n + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param mixed $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiContractAttributeValueL11nCreate(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void + { + if (!empty($val = $this->validateContractAttributeValueL11nCreate($request))) { + $response->data['attr_value_l11n_create'] = new FormValidation($val); + $response->header->status = RequestStatusCode::R_400; + + return; + } + + $attrL11n = $this->createAttributeValueL11nFromRequest($request); + $this->createModel($request->header->account, $attrL11n, ContractAttributeValueL11nMapper::class, 'attr_value_l11n', $request->getOrigin()); + $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Localization', 'Localization successfully created', $attrL11n); + } + + /** + * Method to create contract attribute l11n from request. + * + * @param RequestAbstract $request Request + * + * @return BaseStringL11n + * + * @since 1.0.0 + */ + private function createAttributeValueL11nFromRequest(RequestAbstract $request) : BaseStringL11n + { + $attrL11n = new BaseStringL11n(); + $attrL11n->ref = $request->getDataInt('value') ?? 0; + $attrL11n->setLanguage( + $request->getDataString('language') ?? $request->header->l11n->language + ); + $attrL11n->content = $request->getDataString('title') ?? ''; + + return $attrL11n; + } + + /** + * Validate contract attribute l11n create request + * + * @param RequestAbstract $request Request + * + * @return array + * + * @since 1.0.0 + */ + private function validateContractAttributeValueL11nCreate(RequestAbstract $request) : array + { + $val = []; + if (($val['title'] = !$request->hasData('title')) + || ($val['value'] = !$request->hasData('value')) + ) { + return $val; + } + + return []; + } + + /** + * Api method to handle api contract attributes + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param mixed $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiContractAttribute(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void + { + if (!empty($val = $this->validateContractAttributeValueL11nCreate($request))) { + $response->data['attr_value_l11n_create'] = new FormValidation($val); + $response->header->status = RequestStatusCode::R_400; + + return; + } + + $attrL11n = $this->createAttributeValueL11nFromRequest($request); + $this->createModel($request->header->account, $attrL11n, ContractAttributeValueL11nMapper::class, 'attr_value_l11n', $request->getOrigin()); + $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Localization', 'Localization successfully created', $attrL11n); + } +} diff --git a/Controller/BackendController.php b/Controller/BackendController.php index a4a86bd..d3f27bc 100755 --- a/Controller/BackendController.php +++ b/Controller/BackendController.php @@ -69,6 +69,71 @@ final class BackendController extends Controller return $view; } + /** + * Routing end-point for application behaviour. + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param mixed $data Generic data + * + * @return RenderableInterface + * + * @since 1.0.0 + * @codeCoverageIgnore + */ + public function viewContractTypeList(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : RenderableInterface + { + $view = new View($this->app->l11nManager, $request, $response); + + $view->setTemplate('/Modules/ContractManagement/Theme/Backend/contract-type-list'); + $view->data['nav'] = $this->app->moduleManager->get('Navigation')->createNavigationMid(1007901001, $request, $response); + + $mapper = ContractTypeMapper::getAll() + ->with('l11n') + ->where('l11n/language', $response->header->l11n->language) + ->limit(25); + + if ($request->getData('ptype') === 'p') { + $view->data['types'] = $mapper->where('id', $request->getDataInt('id') ?? 0, '<')->execute(); + } elseif ($request->getData('ptype') === 'n') { + $view->data['types'] = $mapper->where('id', $request->getDataInt('id') ?? 0, '>')->execute(); + } else { + $view->data['types'] = $mapper->where('id', 0, '>')->execute(); + } + + return $view; + } + + /** + * Routing end-point for application behaviour. + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param mixed $data Generic data + * + * @return RenderableInterface + * + * @since 1.0.0 + * @codeCoverageIgnore + */ + public function viewContractType(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : RenderableInterface + { + $view = new View($this->app->l11nManager, $request, $response); + + $view->setTemplate('/Modules/ContractManagement/Theme/Backend/contract-type'); + $view->data['nav'] = $this->app->moduleManager->get('Navigation')->createNavigationMid(1007901001, $request, $response); + + $type = ContractTypeMapper::get() + ->with('l11n') + ->where('l11n/language', $response->header->l11n->language) + ->where('id', (int) $request->getData('id')) + ->execute(); + + $view->data['type'] = $type; + + return $view; + } + /** * Routing end-point for application behaviour. * diff --git a/Models/Contract.php b/Models/Contract.php index 30c4646..5b6f3c3 100755 --- a/Models/Contract.php +++ b/Models/Contract.php @@ -99,20 +99,6 @@ class Contract $this->account = new NullAccount(); } - /** - * Add media to item - * - * @param Media $media Media - * - * @return void - * - * @since 1.0.0 - */ - public function addFile(Media $media) : void - { - $this->files[] = $media; - } - /** * {@inheritdoc} */ @@ -142,4 +128,6 @@ class Contract } use \Modules\Media\Models\MediaListTrait; + use \Modules\Editor\Models\EditorDocListTrait; + use \Modules\Attribute\Models\AttributeHolderTrait; } diff --git a/Models/ContractAttributeMapper.php b/Models/ContractAttributeMapper.php new file mode 100644 index 0000000..69ba0da --- /dev/null +++ b/Models/ContractAttributeMapper.php @@ -0,0 +1,86 @@ + + */ +final class ContractAttributeMapper extends DataMapperFactory +{ + /** + * Columns. + * + * @var array + * @since 1.0.0 + */ + public const COLUMNS = [ + 'contractmgmt_contract_attr_id' => ['name' => 'contractmgmt_contract_attr_id', 'type' => 'int', 'internal' => 'id'], + 'contractmgmt_contract_attr_contract' => ['name' => 'contractmgmt_contract_attr_contract', 'type' => 'int', 'internal' => 'ref'], + 'contractmgmt_contract_attr_type' => ['name' => 'contractmgmt_contract_attr_type', 'type' => 'int', 'internal' => 'type'], + 'contractmgmt_contract_attr_value' => ['name' => 'contractmgmt_contract_attr_value', 'type' => 'int', 'internal' => 'value'], + ]; + + /** + * Has one relation. + * + * @var array + * @since 1.0.0 + */ + public const OWNS_ONE = [ + 'type' => [ + 'mapper' => ContractAttributeTypeMapper::class, + 'external' => 'contractmgmt_contract_attr_type', + ], + 'value' => [ + 'mapper' => ContractAttributeValueMapper::class, + 'external' => 'contractmgmt_contract_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 = 'contractmgmt_contract_attr'; + + /** + * Primary field name. + * + * @var string + * @since 1.0.0 + */ + public const PRIMARYFIELD = 'contractmgmt_contract_attr_id'; +} diff --git a/Models/ContractAttributeTypeL11nMapper.php b/Models/ContractAttributeTypeL11nMapper.php new file mode 100644 index 0000000..6d3d5bd --- /dev/null +++ b/Models/ContractAttributeTypeL11nMapper.php @@ -0,0 +1,69 @@ + + */ +final class ContractAttributeTypeL11nMapper extends DataMapperFactory +{ + /** + * Columns. + * + * @var array + * @since 1.0.0 + */ + public const COLUMNS = [ + 'contractmgmt_contract_attr_type_l11n_id' => ['name' => 'contractmgmt_contract_attr_type_l11n_id', 'type' => 'int', 'internal' => 'id'], + 'contractmgmt_contract_attr_type_l11n_title' => ['name' => 'contractmgmt_contract_attr_type_l11n_title', 'type' => 'string', 'internal' => 'content', 'autocomplete' => true], + 'contractmgmt_contract_attr_type_l11n_type' => ['name' => 'contractmgmt_contract_attr_type_l11n_type', 'type' => 'int', 'internal' => 'ref'], + 'contractmgmt_contract_attr_type_l11n_lang' => ['name' => 'contractmgmt_contract_attr_type_l11n_lang', 'type' => 'string', 'internal' => 'language'], + ]; + + /** + * Primary table. + * + * @var string + * @since 1.0.0 + */ + public const TABLE = 'contractmgmt_contract_attr_type_l11n'; + + /** + * Primary field name. + * + * @var string + * @since 1.0.0 + */ + public const PRIMARYFIELD = 'contractmgmt_contract_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/ContractAttributeTypeMapper.php b/Models/ContractAttributeTypeMapper.php new file mode 100644 index 0000000..6101a17 --- /dev/null +++ b/Models/ContractAttributeTypeMapper.php @@ -0,0 +1,94 @@ + + */ +final class ContractAttributeTypeMapper extends DataMapperFactory +{ + /** + * Columns. + * + * @var array + * @since 1.0.0 + */ + public const COLUMNS = [ + 'contractmgmt_contract_attr_type_id' => ['name' => 'contractmgmt_contract_attr_type_id', 'type' => 'int', 'internal' => 'id'], + 'contractmgmt_contract_attr_type_name' => ['name' => 'contractmgmt_contract_attr_type_name', 'type' => 'string', 'internal' => 'name', 'autocomplete' => true], + 'contractmgmt_contract_attr_type_datatype' => ['name' => 'contractmgmt_contract_attr_type_datatype', 'type' => 'int', 'internal' => 'datatype'], + 'contractmgmt_contract_attr_type_fields' => ['name' => 'contractmgmt_contract_attr_type_fields', 'type' => 'int', 'internal' => 'fields'], + 'contractmgmt_contract_attr_type_custom' => ['name' => 'contractmgmt_contract_attr_type_custom', 'type' => 'bool', 'internal' => 'custom'], + 'contractmgmt_contract_attr_type_pattern' => ['name' => 'contractmgmt_contract_attr_type_pattern', 'type' => 'string', 'internal' => 'validationPattern'], + 'contractmgmt_contract_attr_type_required' => ['name' => 'contractmgmt_contract_attr_type_required', 'type' => 'bool', 'internal' => 'isRequired'], + ]; + + /** + * Has many relation. + * + * @var array + * @since 1.0.0 + */ + public const HAS_MANY = [ + 'l11n' => [ + 'mapper' => ContractAttributeTypeL11nMapper::class, + 'table' => 'contractmgmt_contract_attr_type_l11n', + 'self' => 'contractmgmt_contract_attr_type_l11n_type', + 'column' => 'content', + 'external' => null, + ], + 'defaults' => [ + 'mapper' => ContractAttributeValueMapper::class, + 'table' => 'contractmgmt_contract_attr_default', + 'self' => 'contractmgmt_contract_attr_default_type', + 'external' => 'contractmgmt_contract_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 = 'contractmgmt_contract_attr_type'; + + /** + * Primary field name. + * + * @var string + * @since 1.0.0 + */ + public const PRIMARYFIELD = 'contractmgmt_contract_attr_type_id'; +} diff --git a/Models/ContractAttributeValueL11nMapper.php b/Models/ContractAttributeValueL11nMapper.php new file mode 100644 index 0000000..f48ee43 --- /dev/null +++ b/Models/ContractAttributeValueL11nMapper.php @@ -0,0 +1,69 @@ + + */ +final class ContractAttributeValueL11nMapper extends DataMapperFactory +{ + /** + * Columns. + * + * @var array + * @since 1.0.0 + */ + public const COLUMNS = [ + 'contractmgmt_contract_attr_value_l11n_id' => ['name' => 'contractmgmt_contract_attr_value_l11n_id', 'type' => 'int', 'internal' => 'id'], + 'contractmgmt_contract_attr_value_l11n_title' => ['name' => 'contractmgmt_contract_attr_value_l11n_title', 'type' => 'string', 'internal' => 'content', 'autocomplete' => true], + 'contractmgmt_contract_attr_value_l11n_value' => ['name' => 'contractmgmt_contract_attr_value_l11n_value', 'type' => 'int', 'internal' => 'ref'], + 'contractmgmt_contract_attr_value_l11n_lang' => ['name' => 'contractmgmt_contract_attr_value_l11n_lang', 'type' => 'string', 'internal' => 'language'], + ]; + + /** + * Primary table. + * + * @var string + * @since 1.0.0 + */ + public const TABLE = 'contractmgmt_contract_attr_value_l11n'; + + /** + * Primary field name. + * + * @var string + * @since 1.0.0 + */ + public const PRIMARYFIELD = 'contractmgmt_contract_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/ContractAttributeValueMapper.php b/Models/ContractAttributeValueMapper.php new file mode 100644 index 0000000..a1b4a46 --- /dev/null +++ b/Models/ContractAttributeValueMapper.php @@ -0,0 +1,89 @@ + + */ +final class ContractAttributeValueMapper extends DataMapperFactory +{ + /** + * Columns. + * + * @var array + * @since 1.0.0 + */ + public const COLUMNS = [ + 'contractmgmt_contract_attr_value_id' => ['name' => 'contractmgmt_contract_attr_value_id', 'type' => 'int', 'internal' => 'id'], + 'contractmgmt_contract_attr_value_default' => ['name' => 'contractmgmt_contract_attr_value_default', 'type' => 'bool', 'internal' => 'isDefault'], + 'contractmgmt_contract_attr_value_valueStr' => ['name' => 'contractmgmt_contract_attr_value_valueStr', 'type' => 'string', 'internal' => 'valueStr'], + 'contractmgmt_contract_attr_value_valueInt' => ['name' => 'contractmgmt_contract_attr_value_valueInt', 'type' => 'int', 'internal' => 'valueInt'], + 'contractmgmt_contract_attr_value_valueDec' => ['name' => 'contractmgmt_contract_attr_value_valueDec', 'type' => 'float', 'internal' => 'valueDec'], + 'contractmgmt_contract_attr_value_valueDat' => ['name' => 'contractmgmt_contract_attr_value_valueDat', 'type' => 'DateTime', 'internal' => 'valueDat'], + 'contractmgmt_contract_attr_value_unit' => ['name' => 'contractmgmt_contract_attr_value_unit', 'type' => 'string', 'internal' => 'unit'], + 'contractmgmt_contract_attr_value_deptype' => ['name' => 'contractmgmt_contract_attr_value_deptype', 'type' => 'int', 'internal' => 'dependingAttributeType'], + 'contractmgmt_contract_attr_value_depvalue' => ['name' => 'contractmgmt_contract_attr_value_depvalue', 'type' => 'int', 'internal' => 'dependingAttributeValue'], + ]; + + /** + * Has many relation. + * + * @var array + * @since 1.0.0 + */ + public const HAS_MANY = [ + 'l11n' => [ + 'mapper' => ContractAttributeValueL11nMapper::class, + 'table' => 'contractmgmt_contract_attr_value_l11n', + 'self' => 'contractmgmt_contract_attr_value_l11n_value', + '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 = 'contractmgmt_contract_attr_value'; + + /** + * Primary field name. + * + * @var string + * @since 1.0.0 + */ + public const PRIMARYFIELD = 'contractmgmt_contract_attr_value_id'; +} diff --git a/Models/ContractMapper.php b/Models/ContractMapper.php index 06584c5..7a60727 100755 --- a/Models/ContractMapper.php +++ b/Models/ContractMapper.php @@ -19,6 +19,7 @@ namespace Modules\ContractManagement\Models; use Modules\Admin\Models\AccountMapper; use Modules\Media\Models\MediaMapper; use Modules\Organization\Models\UnitMapper; +use Modules\Editor\Models\EditorDocMapper; use phpOMS\DataStorage\Database\Mapper\DataMapperFactory; /** @@ -119,5 +120,17 @@ final class ContractMapper extends DataMapperFactory 'external' => 'contractmgmt_contract_media_media', 'self' => 'contractmgmt_contract_media_contract', ], + 'notes' => [ + 'mapper' => EditorDocMapper::class, /* mapper of the related object */ + 'table' => 'contractmgmt_contract_note', /* table of the related object, null if no relation table is used (many->1) */ + 'external' => 'contractmgmt_contract_note_doc', + 'self' => 'contractmgmt_contract_note_contract', + ], + 'attributes' => [ + 'mapper' => ContractAttributeMapper::class, + 'table' => 'contractmgmt_contract_attr', + 'self' => 'contractmgmt_contract_attr_contract', + 'external' => null, + ], ]; } diff --git a/Models/PermissionCategory.php b/Models/PermissionCategory.php index 86b799b..7ce922d 100755 --- a/Models/PermissionCategory.php +++ b/Models/PermissionCategory.php @@ -27,4 +27,6 @@ use phpOMS\Stdlib\Base\Enum; abstract class PermissionCategory extends Enum { public const CONTRACT = 1; + + public const CONTRACT_TYPE = 2; } diff --git a/Theme/Backend/Lang/Navigation.en.lang.php b/Theme/Backend/Lang/Navigation.en.lang.php index 9315dd0..5edbde3 100755 --- a/Theme/Backend/Lang/Navigation.en.lang.php +++ b/Theme/Backend/Lang/Navigation.en.lang.php @@ -15,6 +15,7 @@ declare(strict_types=1); return ['Navigation' => [ 'Contract' => 'Contract', 'Contracts' => 'Contracts', + 'ContractTypes' => 'Types', 'Create' => 'Create', 'List' => 'List', ]]; diff --git a/Theme/Backend/Lang/en.lang.php b/Theme/Backend/Lang/en.lang.php index 3d925e9..64c7091 100755 --- a/Theme/Backend/Lang/en.lang.php +++ b/Theme/Backend/Lang/en.lang.php @@ -15,6 +15,7 @@ declare(strict_types=1); return ['ContractManagement' => [ 'Account' => 'Account', 'Contract' => 'Contract', + 'ContractTypes' => 'Contract Types', 'Contracts' => 'Contracts', 'End' => 'End', 'Files' => 'Files', @@ -27,4 +28,5 @@ return ['ContractManagement' => [ 'Termination' => 'Termination', 'Costs' => 'Costs', 'Unit' => 'Unit', + 'Parties' => 'Parties', ]]; diff --git a/Theme/Backend/contract-single.tpl.php b/Theme/Backend/contract-single.tpl.php index c97ea1a..bdd865b 100755 --- a/Theme/Backend/contract-single.tpl.php +++ b/Theme/Backend/contract-single.tpl.php @@ -28,6 +28,10 @@ echo $this->data['nav']->render(); ?>
diff --git a/Theme/Backend/contract-type-list.tpl.php b/Theme/Backend/contract-type-list.tpl.php new file mode 100644 index 0000000..a8c84db --- /dev/null +++ b/Theme/Backend/contract-type-list.tpl.php @@ -0,0 +1,71 @@ +data['types']; + +echo $this->data['nav']->render(); ?> + +
+
+
+
getHtml('ContractTypes', 'Contract', 'Backend'); ?>
+
+ + + + + $value) : ++$count; + $url = UriFactory::build('{/base}/contract/type/profile?{?}&id=' . $value->id); + ?> + +
getHtml('ID', '0', '0'); ?> + + + + getHtml('Name'); ?> + + + +
id; ?> + printHtml($value->getL11n()); ?> + + +
getHtml('Empty', '0', '0'); ?> + +
+
+
+
+
diff --git a/Theme/Backend/contract-type.tpl.php b/Theme/Backend/contract-type.tpl.php new file mode 100644 index 0000000..e69de29